How to read email headers: tracing a message hop by hop
Every email carries a hidden log of its own delivery. The headers record which servers handled the message, when each handoff happened, and whether the sending domain passed authentication. Reading them is the fastest way to answer the two questions that come up constantly: is this message really from who it claims, and where did it get stuck.
Getting the raw headers
Mail clients hide headers by default, but every major one will show you the full source.
Gmail: open the message, click the three dot menu in the top right, choose Show original. Gmail opens a new tab with the complete raw message plus a summary table of SPF, DKIM, and DMARC results at the top.
Outlook (desktop): open the message in its own window, then File → Properties. The headers appear in the small Internet headers box at the bottom. In Outlook on the web, use the three dot menu and choose View → View message source.
Apple Mail: select the message, then View → Message → All Headers for the common fields, or View → Message → Raw Source for the complete original.
Copy the whole block. Headers wrap across lines, and a continuation line starts with whitespace, so partial copies break the structure. Once you have the raw text, you can paste it into the email header analyzer to get the hop chain and authentication results parsed out, entirely in your browser.
The Received chain: read it bottom up
Each server that handles a message prepends a Received header to the top of the message. Prepends, not appends. That means the bottom Received header is the first hop (the sender's own mail server) and the top one is the last hop (your provider's server that finally accepted it). To trace the path, read from the bottom up.
A typical hop looks like this:
Received: from mail-sor-f41.google.com (mail-sor-f41.google.com [209.85.220.41])
by mx.example.com (Postfix) with ESMTPS id 4Xk2...
for <you@example.com>; Wed, 11 Jun 2026 14:02:11 +0000 (UTC)
The from part is what the connecting server claimed plus its actual IP address as observed by the receiver. The by part is the server writing the header. The timestamp at the end is when that server took the message.
The timestamps are the diagnostic gold. Subtract each hop's timestamp from the next one and you get the delay at every handoff. A message that took forty minutes to arrive usually spent thirty nine of them sitting at one specific hop, and the Received chain tells you exactly which server to blame: the sender's outbound queue, a relay in between, or your own provider's spam scanning.
What Authentication-Results tells you
The receiving server records its authentication verdicts in a single header:
Authentication-Results: mx.example.com;
spf=pass smtp.mailfrom=newsletter.example.org;
dkim=pass header.d=example.org header.s=s2048;
dmarc=pass header.from=example.org
Three separate checks, three separate meanings.
spf=passmeans the connecting IP was authorized to send for the domain insmtp.mailfrom(the envelope sender, also visible asReturn-Path). You can verify what a domain publishes with an MX lookup on its DNS records.dkim=passmeans a cryptographic signature over the headers and body verified against the public key of the domain inheader.d. The message was signed by that domain and not modified afterward.dmarc=passmeans at least one of those two checks passed and its domain aligns with the visibleFromaddress, which is the only address a human ever sees.
DMARC is the one that matters for spoofing, because SPF and DKIM on their own can both pass for a domain the recipient never looks at. If a domain you operate does not yet publish a DMARC policy, the DMARC generator will build a correct record to start with.
Spotting spoofing: From vs Return-Path
The From header is just text. Anyone can write anything in it. The Return-Path (the envelope sender, captured by the receiving server) is harder to fake usefully, because SPF is checked against it. So a classic spoof looks like this:
From: "PayPal Support" <service@paypal.com>
Return-Path: <bounce@mail-relay-7.cheaphost.example>
A mismatch is not automatically malicious. Newsletters and transactional mail services legitimately use their own bounce domains. But combine a mismatched Return-Path with dmarc=fail or dmarc=none in Authentication-Results, and a sending IP whose reverse DNS has nothing to do with the claimed sender, and you are looking at a forgery. The Received chain confirms it: the bottom hops will show infrastructure that the real organization would never use.
Which headers can be forged
This is the part people miss. A sender controls everything in the message before it leaves their server: From, Subject, Date, Message-ID, Reply-To, and crucially, any Received headers they choose to fabricate. A spammer can prepend fake hops that make the message appear to have traveled through reputable servers.
What a sender cannot forge is anything added after the message reached infrastructure you trust. Find the first Received header written by your own provider, reading from the top down. That header and everything above it is trustworthy, including the IP address your provider observed on the connection. Everything below that line is, strictly speaking, just claims. Usually the claims are honest, because most mail is honest. But when you are investigating a suspicious message, treat the trusted boundary as the start of the evidence and the rest as testimony.
A short checklist
When a message looks wrong, this sequence takes about two minutes:
- Get the raw source and run it through the email header analyzer.
- Check
Authentication-Resultsfor the DMARC verdict against the visible From domain. - Compare
FromwithReturn-Path. - Read the Received chain bottom up, and stop trusting it below your provider's first hop.
- Look at the timestamps if the question is delay rather than authenticity.
Headers do not lie above the trust boundary, and they rarely need to. Most forgeries fall apart at step two.