How to Read an Email Header
Every email has two From addresses, and they're checked by different things. A line-by-line tour of three headers, adapted from real captures, and what each one is actually useful for.
On this page
Nobody reads email headers for pleasure. You open one because you have a question, and there are a handful of questions a header answers well.
Is my mail actually being authenticated? You configured SPF, DKIM and DMARC months ago and the dashboard says it's fine. The header shows you what a receiving server concluded when a real message actually arrived, which is a different thing.
Is this phishing? The display name says one company. The header shows you which domain really sent it, whether anything was signed, and whether the two have any relationship at all.
What changed? Migrating platforms, adding a subdomain, moving to a new IP pool. The header tells you whether the change landed the way you intended, or whether something stopped signing and nobody noticed.
There's also idle curiosity, which is underrated. You can usually tell which platform any company sends on by opening one of their emails.
Where to find it
In Gmail, open the message, click the three dots and choose Show original.
In new Outlook and Outlook on the web, it's More actions → View → View message details. Classic Outlook for Windows keeps it at File → Properties → Internet headers.
Either way you need the message itself, so seed yourself on every campaign. If you're chasing someone else's copy, ask them to use Show original and paste you the text — clicking Forward composes a new message and the original headers don't come with it.
The two From addresses
Before the walkthrough, the one thing that makes the rest of a header make sense.
Every email carries two sender addresses, and most people only know about one of them.
The header From is the one in your inbox list. It's part of the message content, the sender typed it, and nothing verifies it on its own.
The envelope sender is transmitted before the message, in an SMTP command called MAIL FROM. It's where bounces go. The receiving server records it in the header as Return-Path. You'll also see it called the envelope from, the bounce address, or the return-path address.
They're often on different domains, and that's completely normal — most email platforms bounce to their own infrastructure. What matters is which one each check covers:
| Check | Authenticates | Must align with the visible From domain? |
|---|---|---|
| SPF | the envelope sender's domain | No |
| DKIM | the d= domain in the signature | No |
| DMARC | the alignment itself | Yes |
DKIM normally signs the From header, so it isn't blind to it — but the domain DKIM proves is whatever the signer put in d=, and nothing forces that to match. SPF doesn't look at the From line at all. DMARC is the only check that requires the visible domain to line up with something that passed, and even then it's the domain, not the display name. Nothing anywhere validates the friendly name your subscriber actually reads.
The three examples
Three examples run alongside this piece, adapted from real messages to my own mailboxes. Domains, addresses, IPs, identifiers and signature values are all replaced, so nothing below can be revalidated against DNS or a live key. Header order, folding and every malformation are exactly as they arrived.
They were picked because they disagree with each other:
| Authentication | Landed in | |
|---|---|---|
| A newsletter, direct | Everything passed | Inbox |
| A newsletter, forwarded | Everything failed | Spam |
| A credential phish | SPF passed | Spam |
The panel switches between them as you scroll, and the lines under discussion light up. You can also switch by hand.
Delivered-To: dana@example.com Received: by 2001:db8:7300:2392::bd42 with SMTP id z22eva5535860fip; Sun, 16 Aug 2026 10:05:50 -0700 (PDT) X-Received: by 2001:db8:6f4a::2a0 with SMTP id m06o72z38788o-30q335b923vhz607527560qm.23; Sun, 16 Aug 2026 10:05:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1786899950; cv=none; d=google.com; s=arc-20260327; b=MTznxWhcFueSTdi9ikOEPipSjsDFgUAyePgkQAhGev8z/lHiGZs... ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=feedback-id:message-id:list-unsubscribe :list-unsubscribe-post:mime-version:subject:to:from:date:dkim-signature; bh=iPNLQSJaE9eP238B2oG7e/lBd/JUPh4cIAtTo10V5cU=; b=V8SI8uf8hSHhF7Bwaa... ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@e.verityart.example header.s=k7q2m4x9v1b3n8c5w6t0; dkim=pass header.i=@cloudses.example header.s=p3r8s2y5h9j4l7d1f6g0; spf=pass (google.com: domain of 020004b71c9a773c-be2d45fa-ecfb-5677 -cc67-d5eed89ee879-000000@b.e.verityart.example designates 198.51.100.26 as permitted sender); dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=verityart.example Return-Path: <020004b71c9a773c-be2d45fa-ecfb-5677-cc67-d5eed89ee879-000000 @b.e.verityart.example> Received: from a5-77.smtp-out.cloudses.example (a5-77.smtp-out.cloudses.example. [198.51.100.26]) by mx.google.com with ESMTPS id f34h04y06700z-87g95667v49pv29073144jy.527 for <dana@example.com> (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 16 Aug 2026 10:05:50 -0700 (PDT) Received-SPF: pass (google.com: domain of 020004b71c9a773c-be2d45fa-ecfb-5677 -cc67-d5eed89ee879-000000@b.e.verityart.example designates 198.51.100.26 as permitted sender) client-ip=198.51.100.26; Authentication-Results: mx.google.com; dkim=pass header.i=@e.verityart.example header.s=k7q2m4x9v1b3n8c5w6t0 header.b=S7LYO4ax; dkim=pass header.i=@cloudses.example header.s=p3r8s2y5h9j4l7d1f6g0 header.b=zomgBHEM; spf=pass (google.com: domain of 020004b71c9a773c-be2d45fa-ecfb-5677 -cc67-d5eed89ee879-000000@b.e.verityart.example designates 198.51.100.26 as permitted sender); dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=verityart.example DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=k7q2m4x9v1b3n8c5w6t0; d=e.verityart.example; t=1786899950; h=Date:From:To:Subject:MIME-Version:Content-Type:List-Unsubscribe-Post: List-Unsubscribe:Message-ID; bh=vAeCPEx99UHu/BfWMndA9BvK5LxpqJTyUrvRPmcbLtZ=; b=S7LYO4axlW6eV5Pk... DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=p3r8s2y5h9j4l7d1f6g0; d=cloudses.example; t=1786899950; h=Date:From:To:Subject:MIME-Version:Content-Type:List-Unsubscribe-Post: List-Unsubscribe:Message-ID:Feedback-ID; bh=vAeCPEx99UHu/BfWMndA9BvK5LxpqJTyUrvRPmcbLtZ=; b=zomgBHEMfVYU5JsN... Date: Sun, 16 Aug 2026 17:05:49 +0000 From: Verity Art <notification@e.verityart.example> To: dana@example.com Subject: Our next collection opens Friday MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_085645_2879927958.5728948411601" List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: <https://api.verityart.example/emails/unsubscribe ?token=m8t5g7j5h5d85g41&contentType=announcements&contentMedium=email> Message-ID: <020004b71c9a773c-be2d45fa-ecfb-5677-cc67-d5eed89ee879-000000 @email.cloudses.example> Feedback-ID: ::1.us-east-1.b5cUd5Nt2mZ2dmuTWLmHGUJaoBpybe6a=:CloudSES X-CloudSES-Outgoing: 2026.08.16-198.51.100.26
Adapted from a real capture. Identifiers and signature values are replaced, so nothing here can be revalidated.
01 · From, Reply-To, Subject
The From address you see
The name in the inbox list, the address behind it, the subject, and where a reply would go. This is your subscriber's entire first impression, and none of it is verified by anything. The sender typed all four. Anyone can put any name and any address in a From line.
Standards people call this one the header From, or RFC5322.From if you ever end up reading the DMARC spec. Worth knowing, because there is a second From address in every email that your subscriber never sees, and the two are checked by completely different things. That's the next line.
02 · Return-Path
The From address you don't
Before a single line of the message is transmitted, the sending server opens the SMTP conversation with a command: MAIL FROM. The address it gives there is the envelope sender. When the receiving server finally delivers the message, it writes that value into the header as Return-Path.
You will see the same thing called the envelope from, the bounce address, the return-path address, and RFC5321.MailFrom. One address, five names, depending who you're talking to.
It exists so failures have somewhere to go, which is why it reads like a reference number rather than a mailbox: this platform has encoded an identifier into it so a bounce can be matched back to a specific send. Common, but a choice rather than a rule.
And here is the part worth carrying around for the rest of your career: SPF checks this address, not the one in the From line. A sender can pass SPF perfectly while showing your subscriber a completely unrelated name. The third example on this page does exactly that.
03 · Authentication-Results
What the receiver actually checked
The receiving server's record of what it was able to verify. Three checks, and the thing to memorize is which address each one covers.
SPF takes the domain of the envelope sender and asks whether the connecting IP is on its approved list. It never looks at the From line.
DKIM verifies a signature, and the From header is normally part of what that signature covers. What it proves is the d= domain inside the signature, chosen by whoever signed. Nothing requires that domain to match the one in the From line.
DMARC is the only one that requires the address your reader sees to line up. It passes when the header From domain aligns with a domain that just passed SPF or DKIM. The display name beside it isn't checked by anything.
So SPF and DKIM each prove a domain that doesn't have to be the one in the From line, and DMARC is the check that ties the visible domain to one of them. Here everything lines up: the envelope is on b.e.verityart.example, the signature on e.verityart.example, the visible sender on e.verityart.example. Different subdomains, one organizational domain, which is what relaxed alignment allows. Domains that don't match aren't automatically a problem.
Results are not just pass and fail, either. You'll meet none, neutral, softfail, temperror and permerror, and they mean different things.
One warning before you rely on any of it: only the topmost Authentication-Results, written by your own provider, counts. Everything below it arrived with the message, and anything that arrived with the message could have been typed by whoever sent it. The third example abuses exactly that.
04 · Received
Read from the bottom up
Each server that handles the message adds a Received: line at the top, so the stack runs newest-first and you read it upwards to follow the message forwards in time.
Not all the way to the bottom, though. Only the lines your own provider and the servers it trusts wrote are evidence. Below the point where that chain started, the lines arrived with the message and the sender could have invented them, which the third example on this page did. Start at the oldest hop inside the run you trust, not the oldest line on screen.
This route is about as short as bulk mail gets: the platform's outbound server handed straight to Google, one hop, over TLS 1.3. Check the timestamps against the Date line and the whole trip took a second. A gap of hours between two lines means the message sat somewhere, which is worth knowing before you go hunting for a content problem.
05 · Message-ID
The line to quote in a support ticket
One identifier for this exact message, everywhere it went. Quote it to your platform's support team and they can pull that single send out of their logs, which beats describing it. You need a copy of the message to read it here, so in practice it comes off your own seed address, or off a copy a subscriber pasted back to you.
It gives something away for free, too. The domain on the end belongs to the sending platform, not the brand. That's usually how you can tell who a company sends through by opening one of their emails.
06 · List-Unsubscribe
The exit you didn't design
Two lines that work as a pair. List-Unsubscribe offers a way out; List-Unsubscribe-Post marks it as one-click, so the mailbox provider can act on it without the reader ever loading your page.
The detail almost everyone misses is sitting in the DKIM signatures above. For one-click to be trusted, the signature's h= list has to cover both headers; otherwise the request can't be tied to the message and it gets ignored. Both signatures here list them.
Whether Gmail then shows its own unsubscribe control is a separate question. The header makes it possible, not certain; reputation is part of that decision too.
Second capture · failed, spam
Now one where everything failed
Different sender, different day, same six lines. This one landed in the spam folder, and the verdict is blunt about what the receiver couldn't verify: spf=fail, dkim=fail twice, dmarc=fail.
Read the route before you read anything into that. There are Microsoft servers in the chain, there's a Resent-From line, and the To: address isn't the address this was delivered to. The message was forwarded out of another mailbox.
That explains SPF: the forwarding server isn't in the original sender's SPF record, and this forwarder passed the envelope through unchanged. Forwarders that rewrite it — the scheme is called SRS — avoid this. Both signatures broke too. They verified at Microsoft an instant earlier, so something in the signed content most likely changed in transit, though the header records the failure rather than the cause.
And notice what the failure did not compel. dmarc=fail arrives with p=NONE, so the sender asked for no quarantine and no rejection. That only settles what DMARC required; Gmail is still free to weigh the failure as one signal among many, and clearly weighed something, because this went to spam.
Second capture · the other verdict
Two verdicts, and only one of them is yours
Scroll further down the panel and there's a second Authentication-Results, written by Microsoft when the message first arrived there: spf=pass, dkim=pass twice, dmarc=pass, compauth=pass.
Same message. Both verdicts are accurate. The sender did nothing wrong; forwarding broke the chain afterwards. Read only the lower block and you'd call this sender healthy. Read only the upper one and you'd call them spoofed. Neither is the story.
So a failure here is a statement about the last hop, not an accusation about the sender. Before you escalate a spf=fail, check whether the mail was forwarded.
Third capture · passed, spam
And one that passed SPF while trying to rob me
Third message, and the check that failed on the last one passes here: spf=pass. This is a credential phish.
There is no dkim= result, because nothing was signed. There is no dmarc= result at all. The single thing Gmail could confirm is that whoever controls the envelope sender's domain authorized that IP to send for it, and the attacker registered the domain, published the record and rented the IP. They passed a test they set themselves.
Here are the two From addresses again, doing exactly what line 02 warned about. The envelope sender is on billing-alert.cdn-assets.mx.qorenbatil.example. The address your reader sees is lkcslenvbol@geop.dqlpjxvycer.example. Different domains, no relationship between them, and SPF never looks at the second one. DMARC is the check that would have caught the gap, and there is no DMARC result here at all.
Everything else that gives it away is in the part no test covers. The display name reads Cloud-Storage over that gibberish address. The subject carries the recipient's name, a threat and a deadline. The To: is a different person entirely. And the machine announced itself as one hostname while its reverse DNS said another.
None of that is in the verdict line, and Gmail filtered it anyway. Authentication shows which domains were authorized to send, or took responsibility for the message. Not who the person is, not what they want, not whether any of it is safe. DMARC would at least have tested whether the visible domain lined up here, and plenty of phishing passes DMARC too, on domains the attacker owns outright.
Third capture · the fake evidence
Headers a spammer wrote to reassure you
Further down, this message carries a second Delivered-To, a Received line with no receiving server and no timestamp, a Message-Id ending in @mx.google.com, and (the good one) X-Google-Sender-Delegation: dana@example.com Trusted Sender.
Google wrote none of it. A header is just text until a server you trust adds it, and every one of these was typed by the sender to survive a skim. This is the concrete version of the warning from line 02: read the topmost Authentication-Results, confirm your own provider's name is on it, and treat everything underneath as the sender's claim rather than the receiver's finding.
One practical note while you're here. The List-Unsubscribe on this message points at plain HTTP on a throwaway domain, with no List-Unsubscribe-Post beside it. On mail like this, unsubscribing is how you confirm the address is real. Don't.
What you can conclude
Less than people expect.
A pass means the receiver confirmed a domain. Which domain depends on which check, and none of them means the message is safe or wanted. The phish passed SPF because the attacker registered the domain, published the record and rented the IP. They graded their own exam.
A fail means the receiver couldn't confirm. It doesn't mean the sender did anything wrong. The forwarded newsletter failed at Gmail and passed at Microsoft, because a mailbox rule broke the chain after the sender was done with it.
What you get reliably is narrower and more useful than a verdict: whether your own authentication is working, which domains are actually involved, where the message traveled and how long it took, and the identifiers that turn "it went to spam" into a question support can answer.
What it won't tell you
A header is one message, at one provider, at one moment.
It won't tell you that your spam rate at Gmail has been climbing for three weeks, that a shared IP picked up a neighbor with a list problem, or that a domain stopped signing the day you migrated platforms. It won't tell you why a message was filtered when authentication passed, because receivers don't publish that reasoning. And it won't tell you where the message landed. Placement isn't recorded in a header — I know which folder each of these three arrived in because I went and looked.
That gap is the difference between reading a header and monitoring deliverability. A header answers what could this receiver verify. Monitoring answers is this getting worse.
Read your own
Open something in your inbox and paste its header into the free header analyzer. It pulls out the authentication results, both From addresses, the sending IP, the hop timings, the TLS versions and the domain alignment, so you don't have to squint at folded text.
Tom Sather
Email deliverability expert with 20+ years of experience helping companies improve inbox placement and authentication. Founder of Email Lookout.
Need help with deliverability? Book a free assessment →Related Posts
Ready to Improve Your Email Deliverability?
Get a free assessment of your email authentication setup and actionable recommendations to boost your inbox placement.