Email Security

How do I read and interpret Received headers?

Received headers show email's journey through mail servers. Learn to read these crucial headers to trace email origin and detect spoofing.

By Inventive HQ Team

Received headers are prepended by each mail server in reverse chronological order, so read them bottom-to-top to see the true path an email actually traveled — the bottom-most Received header is the oldest, closest to the original sender, and the top-most header is the newest, added last by the server closest to your own infrastructure. That top-most header is also the most trustworthy one in the stack, because it's the header a server you control or recognize wrote down from what it directly observed on the network connection — everything below it is, to some degree, a claim the sender's own systems made about themselves, and claims can be forged. The rest of this guide breaks down exactly what each field in a Received header means, how to verify it, and how to spot the specific patterns that indicate spoofing.

How a Received header is built

Every time a message hops from one mail server to the next, the receiving server writes a new Received header and stacks it on top of whatever headers were already there. Nothing is ever edited or removed — only added — which is what makes the stack a reliable (if occasionally forgeable) audit log of the message's journey.

Basic Received header

Received: from mail.example.com ([192.0.2.1]) by mx.company.com with SMTP id abc123def for <john@company.com>; Wed, 15 Jan 2025 14:32:10 -0500

Here's that same header broken into its six parts, with the level of trust you should place in each one:

Anatomy of a Received header The Received header split into its from, IP, by, with, id, for, and timestamp fields, each paired with a trust rating: verify, trustworthy, or informational. Anatomy of a Received header Seven fields, three different levels of trust RAW HEADER, FIELD BY FIELD from mail.example.com ([192.0.2.1]) by mx.company.com with SMTP id abc123def for <john@company.com> Wed, 15 Jan 2025 14:32:10 -0500 FROM — hostname the server claims Self-reported by the connecting client verify
<rect x="392" y="150" width="304" height="34" rx="8" fill="#ffffff" stroke="#f59e0b" stroke-width="1.5"/>
<text x="408" y="163" font-size="12" font-weight="bold" fill="#b45309">IP ADDRESS &#8212; what the server saw</text>
<text x="408" y="177" font-size="10" fill="#64748b">Logged by the receiving server itself</text>
<circle cx="680" cy="167" r="4" fill="#16a34a"/>
<text x="672" y="170" text-anchor="end" font-size="9" fill="#15803d">trust</text>

<rect x="392" y="200" width="304" height="34" rx="8" fill="#ffffff" stroke="#0d9488" stroke-width="1.5"/>
<text x="408" y="213" font-size="12" font-weight="bold" fill="#0d9488">BY &#8212; this hop's own hostname</text>
<text x="408" y="227" font-size="10" fill="#64748b">Trustworthy if you recognize this server</text>
<circle cx="680" cy="217" r="4" fill="#16a34a"/>
<text x="672" y="220" text-anchor="end" font-size="9" fill="#15803d">trust</text>

<rect x="392" y="250" width="304" height="34" rx="8" fill="#ffffff" stroke="#7c3aed" stroke-width="1.5"/>
<text x="408" y="263" font-size="12" font-weight="bold" fill="#7c3aed">WITH &#8212; protocol used</text>
<text x="408" y="277" font-size="10" fill="#64748b">SMTP / ESMTP / ESMTPS</text>
<circle cx="680" cy="267" r="4" fill="#64748b"/>
<text x="672" y="270" text-anchor="end" font-size="9" fill="#475569">info</text>

<rect x="392" y="300" width="304" height="34" rx="8" fill="#ffffff" stroke="#c026d3" stroke-width="1.5"/>
<text x="408" y="313" font-size="12" font-weight="bold" fill="#c026d3">ID &#8212; transaction ID</text>
<text x="408" y="327" font-size="10" fill="#64748b">Server's internal tracking number</text>
<circle cx="680" cy="317" r="4" fill="#64748b"/>
<text x="672" y="320" text-anchor="end" font-size="9" fill="#475569">info</text>

<rect x="392" y="350" width="304" height="34" rx="8" fill="#ffffff" stroke="#e11d48" stroke-width="1.5"/>
<text x="408" y="363" font-size="12" font-weight="bold" fill="#e11d48">FOR &#8212; recipient at this hop</text>
<text x="408" y="377" font-size="10" fill="#64748b">Can mislead with lists / BCC</text>
<circle cx="680" cy="367" r="4" fill="#f59e0b"/>
<text x="672" y="370" text-anchor="end" font-size="9" fill="#b45309">verify</text>

<rect x="392" y="400" width="304" height="34" rx="8" fill="#ffffff" stroke="#475569" stroke-width="1.5"/>
<text x="408" y="413" font-size="12" font-weight="bold" fill="#475569">TIMESTAMP &#8212; when it was logged</text>
<text x="408" y="427" font-size="10" fill="#64748b">Trustworthy, but check the timezone</text>
<circle cx="680" cy="417" r="4" fill="#16a34a"/>
<text x="672" y="420" text-anchor="end" font-size="9" fill="#15803d">trust</text>
Loading interactive tool...

The rule of thumb: anything the receiving server measured directly (the connecting IP, its own hostname, its own clock) is hard to fake. Anything the connecting client simply announced about itself (the "from" hostname, the "for" recipient) is a claim, not a measurement — verify it before you trust it.

Reading the email's path: why bottom-to-top matters

Each server prepends — it never edits or replaces — so the header stack is a literal, append-only log of the message's journey. The oldest entry (added first, by the sender's own server) ends up at the bottom; the newest entry (added last, by the server closest to you) ends up on top. Read bottom to top and you're reading the message's actual chronological path.

The multi-hop email journey, read bottom to top A message travels upward from the original sender's server through two relays to your mail server, mirroring how each hop's Received header stacks above the last. An animated marker travels the same path from bottom to top on a loop. The multi-hop journey: read the stack bottom to top Each hop prepends a new Received header above the last one Your mail server adds this header LAST
<rect x="210" y="220" width="220" height="64" rx="10" fill="#0d9488"/>
<text x="320" y="246" font-size="13" font-weight="bold" fill="#ffffff">Relay 2</text>
<text x="320" y="264" font-size="10" fill="#ccfbf1">e.g. destination spam filter</text>

<rect x="210" y="350" width="220" height="64" rx="10" fill="#7c3aed"/>
<text x="320" y="376" font-size="13" font-weight="bold" fill="#ffffff">Relay 1</text>
<text x="320" y="394" font-size="10" fill="#ede9fe">e.g. sender's outbound relay</text>

<rect x="210" y="480" width="220" height="64" rx="10" fill="#b45309"/>
<text x="320" y="506" font-size="13" font-weight="bold" fill="#ffffff">Original sender's server</text>
<text x="320" y="524" font-size="10" fill="#fde68a">adds this header FIRST</text>
Topmost = newest Closest to infrastructure you control — hardest to forge.
<text x="450" y="498" font-size="12" font-weight="bold" fill="#b45309">Bottom = oldest</text>
<text x="450" y="514" font-size="11" fill="#475569">Self-reported by the</text>
<text x="450" y="528" font-size="11" fill="#475569">sender's own system &#8212;</text>
<text x="450" y="542" font-size="11" fill="#475569">verify before trusting.</text>
READ BOTTOM → TOP
Advertisement

Worked example

Email from: john.doe@example.com
To: alice@company.com

Headers as they appear (TOP TO BOTTOM in the raw source):

3. (TOP — newest, added last)
Received: from mail.company.com by mx.company.com
         with SMTP id abc123; Wed, 15 Jan 14:32:20 -0500
Analysis: Company's own mail server received it — final hop.

2. (MIDDLE)
Received: from mail.gmail.com by mail.company.com
         with ESMTPS id def456; Wed, 15 Jan 14:32:15 -0500
Analysis: Gmail relayed it to the company's server.

1. (BOTTOM — oldest, added first)
Received: from smtp.example.com ([192.0.2.1])
         by mail.gmail.com with ESMTP id ghi789
         for <alice@company.com>; Wed, 15 Jan 14:32:05 -0500
Analysis: John's own server made first contact — origin of the message.

Path traced bottom to top: example.com (sent) → gmail.com (relayed) → company.com (received)

Which fields can you trust?

Not every field in a Received header carries the same evidentiary weight. Use this as a quick reference before you draw conclusions from a header chain:

FieldWho wrote it downTrust level
from hostnameThe connecting client announces this about itselfVerify — trivial to fake
IP address in (...)The receiving server observed this on the actual connectionTrustworthy — hard to fake
by (receiving server)The server writing this line, about itselfTrustworthy, if you recognize it as legitimate infrastructure
with (protocol: SMTP/ESMTP/ESMTPS)The receiving serverInformational only
id (transaction ID)The receiving server's internal systemInformational only
for (recipient)The receiving server, based on envelope dataVerify — can look odd on lists or BCC
TimestampThe receiving server's own clockTrustworthy, but check the timezone offset

Interpreting each component in detail

From (sending server)

Received: from smtp.gmail.com

What it shows: the hostname the connecting server announced, as an FQDN or IP, possibly via reverse DNS.

Verify: is this a legitimate server for the claimed sender? Does the hostname match the sender's domain? Confirm with a WHOIS or DNS lookup rather than taking it at face value.

IP address in brackets

Received: from smtp.gmail.com ([142.250.185.46])

What it shows: the actual IP address of the sending server — more reliable than the hostname because it's logged by the receiving server, not self-reported.

Verify: look up the IP's geolocation and ownership, check it against the sender's known ranges, and run it through an IP reputation tool.

By (receiving server)

Received: by mx.company.com

What it shows: the hostname of the server that received the message at this hop.

Verify: is this the expected next hop? Does the server actually belong to the company named in the message?

With (protocol and ID)

Received: with SMTP id 47h8ai23skd

What it shows: SMTP (unencrypted, older), ESMTP (extended features), ESMTPS (ESMTP over TLS — encrypted), or LMTP (local delivery) — plus a unique transaction ID for that hop.

For (recipient at this hop)

Received: for <john@company.com>

What it shows: who the server believed the intended recipient was at that point. This can legitimately differ across hops when a mailing list is involved — the last "for" is the final recipient.

Timestamp

Wed, 15 Jan 2025 14:32:10 -0500

What it shows: when this server received the message, plus its timezone offset (-0500 = EST).

Verify: does the sequence make sense — should each Received header have an earlier timestamp than the one above it? Large or backwards gaps are worth a second look.

Symptom, cause, and fix: common Received-header red flags

SymptomLikely causeWhat to do
Only one Received header on a message that claims to be externalHeaders stripped, or the message was injected directly rather than relayedTreat as suspicious; check the Authentication-Results header for SPF/DKIM/DMARC
from hostname names a trusted brand, but the IP isn't in that brand's published rangesSpoofed sender / hostname-IP mismatchLook up the IP's real owner and compare against the brand's documented sending ranges
Hostname shows unknownReverse DNS (PTR) lookup failed for that IPInvestigate the IP directly with WHOIS and a reputation lookup
A private IP (127.0.0.1, 192.168.x.x, 10.x.x.x) appears in an externally-received headerForged header — private IPs should never traverse the public internetTreat the message as spoofed
Timestamps decrease as you read up the stackManipulated or manually inserted headersRe-verify the entire chain; don't trust the claimed path
The from server has no relationship to the sender's claimed domainAn attacker-controlled relay, not the real senderConfirm SPF/DKIM/DMARC results and verify with the sender out-of-band

Detail: the six patterns worth knowing by name

Missing Received headers. A message with only a single, top-level Received header is either an internal forward, stripped headers, or a forged/injected message. Ask whether that's expected for this type of email.

Hostname/IP mismatch. Received: from gmail.com ([192.0.2.99]) — Gmail's real sending IPs live in ranges like 2607:f8b0::/32 and 142.250.0.0/15. An address like 192.0.2.99 isn't Google's. Treat as spoofed.

Reverse DNS failure. Received: from unknown ([192.0.2.50]) — the hostname "unknown" means the IP has no PTR record. Not proof of malice by itself, but worth an IP reputation check.

Private IP addresses. Received: from localhost ([127.0.0.1]) or a 192.168.* / 10.* address should never legitimately appear in the path of an externally-delivered message. Treat as forged.

Time sequence issues. If timestamps go backwards as you read up the stack (later hop shows an earlier time than the hop below it), the chain has likely been manipulated.

Server chain doesn't match the sender. From claims john@example.com, but the Received chain shows attacker.net. The email came from attacker.net — not example.com — regardless of what the From address says.

Reading multiple Received headers together

Email from: john.doe@example.com
To: alice@company.com
Subject: Important update

Headers (read BOTTOM TO TOP):

3. (TOP)
Received: from mail.company.com by mx.company.com
         with SMTP id abc123; Wed, 15 Jan 14:32:20 -0500
Analysis: Company's mail server received it

2. (MIDDLE)
Received: from mail.gmail.com by mail.company.com
         with ESMTPS id def456; Wed, 15 Jan 14:32:15 -0500
Analysis: Gmail relayed it to company server

1. (BOTTOM - ORIGINAL)
Received: from smtp.example.com ([192.0.2.1])
         by mail.gmail.com with ESMTP id ghi789
         for <alice@company.com>; Wed, 15 Jan 14:32:05 -0500
Analysis: John's company's server sent it

Path traced: example.com (john sends) → gmail.com (relayed) → company.com (alice receives)

Checking server legitimacy

Verifying Gmail emails

Legitimate Gmail sending IPs live in ranges including 2607:f8b0::/32 (IPv6), 142.250.0.0/15 (IPv4), and other Google-owned blocks.

Check: is the server gmail.com? Is the IP inside Google's range? Does the hostname match Gmail? If all three line up, it's likely legitimate. If the hostname says "gmail.com" but the IP is something like 192.0.2.1, that's spoofed.

Verifying Office 365 emails

Legitimate Microsoft mail infrastructure typically routes through outlook.office365.com, mail.outlook.com, or protection.outlook.com. Check that the server name and IP both fall within Microsoft's documented ranges before trusting the message.

Unknown companies

  1. Extract the IP from the Received header.
  2. Look up IP ownership with whois.
  3. Check whether the IP matches the claimed company.
  4. Verify against the company's actual published mail servers.
  5. Check email reputation databases for the IP.

Tools for header analysis

Online tools

Inventive HQ Email Header Analyzer — paste raw headers and get visual parsing, a path diagram, and automatic red-flag detection:

Loading interactive tool...

Google Admin Toolbox — free header analysis that shows the path clearly and surfaces SPF/DKIM/DMARC results.

MXToolbox — header analyzer with built-in IP reputation checks and reverse DNS lookups.

Command line

# Extract all Received headers
grep "^Received:" email.eml | tac  # tac reverses order (bottom to top)

# Check specific IP
whois 192.0.2.1

# Reverse DNS lookup
nslookup -x 192.0.2.1

# IP geolocation
curl -s "http://ip-api.com/json/192.0.2.1"

Step-by-step header reading process

Step 1: Get the headers. View full headers in your email client and copy the raw text.

Step 2: Read from the bottom up. Find the original Received header at the bottom and note the "from" server and IP.

Step 3: Verify the IP. Look up ownership and check whether it belongs to the claimed sender's company. A mismatch is suspicious.

Step 4: Check authentication. Look for the Authentication-Results header and check the SPF, DKIM, and DMARC results (pass/fail).

Step 5: Verify the path. Read each Received header bottom to top and confirm each hop makes sense — no anomalies, no breaks in the chain.

Step 6: Make a decision. All checks pass → likely legitimate. Red flags found → likely spoofed. Uncertain → verify with the sender through a separate channel.

Common legitimate variations

Forwarded emails

A forward adds a new Received header from the forwarder on top of the original — having multiple Received headers is completely normal for a forwarded message.

Mailing lists

A mailing list server receives the original message and then re-sends it to subscribers, so both the list server's Received header and the original sender's Received header will legitimately appear.

BCC recipients

BCC doesn't change the Received headers at all — every recipient sees the same header chain regardless of whether they were BCC'd.

Real-world scenarios

Scenario 1: legitimate corporate email

From: ceo@company.com
Claims: Urgent wire transfer needed

Received: from mail.company.com ([203.0.113.10])

Step 1: Is 203.0.113.10 the company's IP?           ✓ Yes, matches company website
Step 2: Reverse DNS: 203.0.113.10 → mail.company.com ✓
Step 3: Authentication: spf=pass, dkim=pass, dmarc=pass ✓
Step 4: Pattern matches a legitimate internal send    ✓

Verdict: LIKELY LEGITIMATE — but always verify urgent financial requests through a second channel.

Scenario 2: phishing attempt

From: support@amazon.com
Claims: Verify your account

Received: from attacker.com ([192.0.2.99])

Step 1: Is 192.0.2.99 Amazon's server?               ✗ No, doesn't match Amazon's ranges
Step 2: Reverse DNS: 192.0.2.99 → unknown/attacker.com ✗
Step 3: Authentication: spf=fail, dkim=fail, dmarc=fail ✗
Step 4: Pattern matches phishing                       ✗

Verdict: PHISHING — do not click any links.

Conclusion

The From address is what an attacker wants you to see; the Received chain is what actually happened. Read it bottom to top, trust the fields your own infrastructure measured directly over the fields the sender merely announced, and always cross-check the result against SPF, DKIM, and DMARC before you make a call. Master those two habits and you'll catch the great majority of spoofed and phished email before it does any damage.

Frequently Asked Questions

Do you read Received headers top to bottom or bottom to top?

Bottom to top. Every server that handles a message prepends its own Received header above the ones already there, so the stack grows from the bottom up. The bottom-most Received header is the oldest entry — closest to the original sender — and the top-most header is the newest, added by the last server to touch the message before it landed in your inbox. Reading bottom to top gives you the true chronological order the email actually traveled.

Can Received headers be faked?

Partially, yes. Anyone composing a raw email can type fake "Received:" lines directly into the message before sending it, so headers further down the stack — closer to the claimed origin — can be entirely fabricated. What can't be faked is the header your own trusted receiving infrastructure adds when it accepts the connection, because that server logs the real IP address it saw on the wire, not something the sender typed. That's why the top-most header (or the first one added by a mail server you control) is the most reliable anchor point.

How do I trace the real sender of an email?

Start at the bottom Received header and work upward, noting the "from" hostname and the IP address in parentheses at each hop. Stop trusting the chain the moment you hit a header added by infrastructure you don't control or recognize — everything below that point is the sender's own claim and should be verified independently. Cross-check the IP with a WHOIS or reverse DNS lookup, and confirm the result against the SPF, DKIM, and DMARC results in the Authentication-Results header rather than relying on Received headers alone.

Which part of a Received header can't be spoofed?

The IP address that the receiving server logged when it accepted the SMTP connection. Unlike the "from" hostname (which the connecting server announces about itself and can lie about), the IP address is observed directly at the network layer by the server writing the header. If that server is one you trust, its logged IP is far more reliable than any hostname claim elsewhere in the chain.

Why do the from hostname and the IP address sometimes not match?

A mismatch between the claimed hostname (e.g., "gmail.com") and the actual IP address in brackets is one of the clearest spoofing signals there is. Legitimate mail servers announce a hostname that resolves back to their own IP ranges. If a header claims to be from a major provider but the IP doesn't belong to that provider's published ranges, the hostname is almost certainly forged and the message should be treated as suspicious until SPF/DKIM/DMARC checks prove otherwise.

What does unknown mean in a Received header?

"Unknown" in place of a hostname means the reverse DNS (PTR) lookup for that IP address failed — the IP has no hostname registered that points back to it. Legitimate, well-run mail infrastructure almost always has proper reverse DNS configured, so a bare "unknown" is a mild red flag worth investigating with a direct IP reputation or WHOIS lookup, though it isn't proof of malice on its own.

How many Received headers should a normal email have?

There's no fixed number — it depends on how many servers relayed the message. A simple send between two mailboxes on the same provider might have just one or two hops; a message that passes through a sending platform, a spam filter, a forwarding rule, and a corporate gateway can easily have five or six. What matters is whether the chain makes logical sense end to end, not the raw count. A single Received header on a message that claims to come from outside your organization is the unusual case worth double-checking.

Is the topmost Received header always trustworthy?

Only if it was added by a server you control or explicitly trust, such as your own company's mail gateway. The topmost header is trustworthy because it's the most recently added and therefore the hardest for an external attacker to forge — but if you're looking at headers forwarded to you from an unknown source, verify which hop is actually "yours" before anchoring your trust there.

Do Received headers replace SPF, DKIM, and DMARC checks?

No — they complement each other. Received headers show you the physical path a message took hop by hop, which is great for spotting anomalies like private IPs or hostname/IP mismatches. SPF, DKIM, and DMARC are cryptographic and policy-based authentication checks that tell you whether the sending server was authorized to send on behalf of that domain. Always check both: the Received chain for a plausible path, and the Authentication-Results header for pass/fail verdicts.

email headersreceived headersemail tracingemail forensicsheader analysis