How to read email headers like a postmaster
Received chains read bottom-to-top, Authentication-Results don't lie, and a five-minute header read explains most delivery mysteries. A field guide.
By David Lara, Founder
Founder-reviewed ·How we research and correct articles
Every email carries its own flight recorder. Hidden above the message you read is the full forensic record: every server it passed through, when, what each one thought of the sender, and which security checks passed or failed. When something goes wrong — delays, spam placement, a suspicious message — the headers usually contain the entire answer.
Most people never look, because raw headers are genuinely ugly. Five concepts fix that.
Getting the headers
- Gmail: open the message → three-dot menu → Show original.
- Outlook: open the message → … → View → View message source.
You’ll get a wall of text. Copy all of it — and either read on, or paste it into our free Email Header Analyzer, which renders the verdicts and the route as a table, in your browser, nothing uploaded.
1. The Received chain reads bottom-to-top
Each server that handles a message stamps a Received: header on top
of the existing ones. So the bottom Received is the origin — the
server closest to the sender — and the top is the final delivery. Read
it bottom-up and you have the route.
Two things to extract:
- The origin. Does the first hop make sense for the claimed sender? An invoice “from your bank” that originates at a residential ISP in another country has already told you everything.
- The timestamps. Subtract each hop from the next. The route should take seconds. A gap of minutes or hours at one hop is where your “email was slow” mystery lives — typically greylisting (a deliberate first-attempt rejection forcing a retry), rate limiting, or an overloaded queue.
2. Authentication-Results is the verdict line
Near the top you’ll find the receiving server’s own scorecard:
Authentication-Results: mx.google.com;
spf=pass smtp.mailfrom=example.com;
dkim=pass header.d=example.com;
dmarc=pass header.from=example.com
This is the receiver telling you, in one line, how
SPF,
DKIM and
DMARC scored the message. For your
own mail, this line is the ground truth of your setup — send yourself a
test and read it. The classic find: dkim=pass but on
header.d=yoursendingtool.com instead of your domain — a valid signature
that does nothing for your alignment.
3. From vs Return-Path: the two-sender trick
From: is what the recipient sees; Return-Path is the envelope address
the SMTP conversation actually used. They legitimately differ (most
sending platforms route bounces through their own domain) — but the
combination of a mismatched Return-Path, a Reply-To pointing at a
third, unrelated domain, and failing authentication is the standard
anatomy of a phish.
4. The minor headers that talk
Message-ID— its domain should roughly match the sending org.X-Mailer/User-Agent— what software sent it; bulk tools announce themselves here.Received-SPF— SPF’s working notes, useful when the verdict line is terse.- A hop with
tlsorESMTPSin itsReceivedline was encrypted in transit; whether your own domain enforces that is a separate check — our MTA-STS & TLS-RPT Checker reads the policy in one pass.
A worked example: reading a real chain
Here’s a trimmed, representative Received chain — three hops, oldest at
the bottom the way it actually appears in a raw header dump:
Received: by mx.google.com with SMTP id abc123
for <you@example.com>; Tue, 14 Jul 2026 09:14:02 -0700 (PDT)
Received: from mail-relay-03.senderdomain.com (mail-relay-03.senderdomain.com [198.51.100.44])
by mx.google.com with ESMTPS id xyz789
for <you@example.com>; Tue, 14 Jul 2026 09:13:58 -0700 (PDT)
Received: from localhost (unknown [203.0.113.9])
by mail-relay-03.senderdomain.com with ESMTP id def456
for <you@example.com>; Tue, 14 Jul 2026 08:47:11 -0700 (PDT)
Reading bottom to top: the message originated at 203.0.113.9 at 08:47:11,
handed off to the sender’s own relay (mail-relay-03.senderdomain.com),
which then delivered to Google at 09:13:58 — roughly 26 minutes later. That
gap is the tell. A healthy hop takes seconds; 26 minutes between the first
and second hop, with nothing unusual at the third, points to the relay
itself queuing or retrying, not a network problem downstream. If this were
a live delivery complaint, that’s exactly where you’d start looking — not
at content, not at the recipient’s filter settings, but at whatever the
sending relay was doing for those 26 minutes (commonly a temporary
rate limit or a queue backup on the sender’s side).
Notice, too, that the origin IP (203.0.113.9) and the relay’s own IP
(198.51.100.44) are different machines — normal for any setup where
outbound mail routes through a dedicated sending service rather than the
originating server talking directly to Gmail. What would be a red flag is
that same origin IP resolving to a residential ISP block or a country with
no plausible connection to the claimed sender; that mismatch, on its own,
is often enough to explain a delivery or spam-placement mystery without
reading another header.
What a suspicious set of headers looks like
Contrast that ordinary chain with the anatomy of a typical phishing
attempt: the origin hop resolves to a residential or hosting-provider IP
with no relationship to the claimed sender, Authentication-Results shows
spf=fail or dkim=none rather than a clean pass, the Return-Path
domain has nothing to do with the From: domain, and a Reply-To header
quietly redirects replies to a third domain entirely different from both.
Any one of those alone can have an innocent explanation — legitimate
services frequently set a different Reply-To on purpose. It’s the
combination, arriving together on one message, that’s the reliable
signal: a real sender rarely fails authentication, originates somewhere
implausible, and redirects replies elsewhere, all at once.
The five-minute diagnostic, assembled
Delivery mystery? Pull headers and ask, in order: where did it originate
(bottom Received) → where did it stall (timestamp gaps) → what did the
receiver verify (Authentication-Results) → do the sender identities
agree (From / Return-Path / Reply-To / Message-ID)? To identify any
mystery server along the way, our DNS Lookup resolves
it both directions.
Frequently asked questions
Why do the timestamps in different Received headers sometimes look out
of order? Each server stamps its own local clock, and clocks drift —
usually by seconds, occasionally by more on a misconfigured server. Compare
the UTC offsets, not just the raw times, and treat a few seconds of
apparent disagreement as normal rather than a sign of tampering.
Is a dkim=pass always good news? Only if the signing domain
(header.d=) matches the domain you actually care about. A message can
show a perfectly valid dkim=pass signed by a sending platform’s own
shared domain — technically true, but doing nothing for your own domain’s
alignment or reputation, which is the distinction that trips up most
people the first time they read this line closely.
Can headers be faked? The visible ones a client shows you by default —
From, Subject, Reply-To — are trivially easy to set to anything.
That’s exactly why Received and Authentication-Results matter more:
they’re written by servers along the delivery path, not by the sender, so
forging them convincingly requires actually controlling infrastructure
along that path rather than just editing a compose window.
That’s the whole skill. The flight recorder was always on — postmasters just know where the panel is.