Reading email headers is the most reliable way to find out what happened to a message. Headers record every server that handled the mail, how long each hop took and what each authentication check concluded. When a message is late, rejected or lands in spam, the cause is usually written there. This guide shows how to find the headers, read the important lines and match what you see to common problems.
Step 1: Get a message to inspect
Headers belong to a specific delivered message, so you need one. Send a test from the same system and stream that has the problem to an address you control at the mailbox provider where it occurs. Avoid forwarding the message to yourself, because forwarding adds headers and changes authentication results. If the message never arrived, use your sending platform delivery log and the SMTP response instead.
Step 2: Open the full headers
| Mail client | Where to find the headers |
|---|---|
| Gmail (web) | Open the message, select the three-dot menu, then Show original |
| Outlook (web) | Open the message, use the three-dot menu, then View and View message source |
| Outlook (desktop) | Open the message, then File, Properties and read the Internet headers box |
| Apple Mail | Select the message, then View, Message and All Headers or Raw Source |
| Thunderbird | Open the message, then View and Message Source |
Menus change. Mail clients rename and move these options. If you cannot find the exact item, search the help of your client for view original, message source or internet headers.
The map of a header block
A header block is a list of lines of the form name, colon, value. A long value wraps onto following lines that begin with a space. Here are the headers you will use most often:
| Header | What it tells you |
|---|---|
| From | The visible sender address that DMARC checks against |
| Return-Path | The envelope sender, where bounces go and where SPF is checked |
| Received | One line per server that handled the message, newest on top |
| Authentication-Results | The receiving server verdicts for SPF, DKIM and DMARC |
| DKIM-Signature | The signature: signing domain d=, selector s= and signed headers h= |
| Message-ID | A unique identifier you can search for in logs |
| Date | When the sender created the message |
| List-Unsubscribe | The unsubscribe link and, with List-Unsubscribe-Post, one-click support |
| ARC-Seal and ARC-Authentication-Results | Authentication results recorded by an intermediary such as a forwarder |
Step 3: Trace the Received chain
Each server prepends a Received line, so the first hop is at the bottom. Read from the bottom up. A typical chain shows your application, your sending platform, then the receiving mail server.
Received: from mx1.mailbox.example by inbox.mailbox.example; Tue, 14 Oct 2026 09:02:14 +0000
Received: from out1.sendingplatform.example (203.0.113.10) by mx1.mailbox.example; Tue, 14 Oct 2026 09:02:11 +0000
Received: from app.example.com by out1.sendingplatform.example; Tue, 14 Oct 2026 09:02:09 +0000
Here the message left the sender at 09:02:09, reached the receiver at 09:02:11 and was placed in the mailbox at 09:02:14, a total of five seconds. When a message is slow, subtract the timestamps to find the hop where the time went. A gap of several minutes between your platform and the receiver usually means a deferral and retry, for example a rate limit or greylisting. A gap between your application and the platform points to a queue on your own side.
Only trust your own side of the chain. Lines added by servers you do not control can be written by the sender. The reliable lines are those added by your own receiving provider, such as the topmost Received and Authentication-Results.
Step 4: Read Authentication-Results
Authentication-Results: mx.mailbox.example;
spf=pass (sender IP is 203.0.113.10) smtp.mailfrom=bounce.mail.example.com;
dkim=pass header.d=mail.example.com header.s=2026a;
dmarc=pass (p=REJECT) header.from=mail.example.com
Each verdict names the domain it was evaluated against. Look at three things: whether each result is pass, whether the SPF domain (smtp.mailfrom) and the DKIM domain (header.d) relate to the From domain (header.from), and what policy DMARC applied.
| Result | Meaning | Typical cause of a problem |
|---|---|---|
| spf=pass | The sending IP is authorised for the envelope domain | None; check alignment next |
| spf=fail or softfail | The IP is not listed, or is listed with a soft failure | Missing include in the SPF record or a different sending system |
| spf=permerror | The SPF record is invalid | Too many lookups, duplicate records or a syntax error |
| dkim=pass | The signature verified with the published key | None; check the signing domain aligns |
| dkim=fail | The signature did not verify | Message altered in transit, wrong key or missing selector record |
| dkim=none | No signature was present | Signing is not enabled for this stream |
| dmarc=pass | At least one aligned pass | None |
| dmarc=fail | No aligned SPF or DKIM pass | Domains in the headers do not match the From domain |
Step 5: Compare the domains
A very common finding is a message that passes SPF and DKIM and yet fails DMARC. Put the three domains side by side. If the From domain is example.com, the return-path is platform.net and the DKIM domain is platform.net, then both checks passed for the platform domain and neither aligned. The fix is to sign with your own domain and, ideally, use a custom return-path, as described in our guide to custom return-path and tracking domains.
Step 6: Look for spam and policy signals
Some providers add headers that describe how they scored the message, for example a spam status line or a verdict. The names and contents vary, and many large providers show nothing. If you do see one, note the reasons it lists. If you do not, use indirect evidence: compare placement across several test accounts, check your reputation dashboards and look at complaint and bounce rates. The spam troubleshooting checklist turns those observations into actions.
From symptom to header
| Symptom | What to check in the headers | Next step |
|---|---|---|
| Message arrived late | Gaps between Received timestamps | Check deferrals and rate limits in your delivery log |
| Message in spam | Authentication-Results verdicts and any spam header | Fix failures, then review reputation and content |
| Bounce says authentication required | Missing dkim or spf results | Enable signing and publish records |
| Mail from a forwarded address fails | SPF fail at the forwarder, ARC headers | Rely on aligned DKIM, which survives forwarding |
| Unsubscribe button missing | List-Unsubscribe and List-Unsubscribe-Post headers | Add them as described in our one-click unsubscribe guide |
| Duplicate messages | Two different Message-ID values or repeated Received chains | Check for retries or double submission in your application |
A worked example: diagnosing a DMARC failure
A support team reports that password-reset emails from a new service land in spam at one provider. You ask for a test message and open the headers. Reading from the Authentication-Results line, you see this:
Authentication-Results: mx.mailbox.example;
spf=pass smtp.mailfrom=bounces.sendingplatform.example;
dkim=pass header.d=sendingplatform.example;
dmarc=fail (p=QUARANTINE) header.from=example.com
Both SPF and DKIM pass, which can mislead. But each passes for sendingplatform.example, while the From address is at example.com. Neither check aligns with the From domain, so DMARC fails, and the policy on example.com is quarantine, which explains the spam placement. The Received chain shows no delay, so this is not a rate-limit issue.
The fix is to authenticate example.com on the sending platform: publish the DKIM record so that signatures use d=example.com, and set up a custom return-path on a subdomain of example.com. After those changes, send a fresh test and compare the new Authentication-Results line. When it shows dmarc=pass with header.from=example.com, the cause is resolved. Note that the diagnosis took one header block, no guesswork and no changes to the message content.
Privacy and sharing
Headers include IP addresses, host names and the recipient address. When you send them to support or post them in a forum, remove personal data you do not want to share. Support staff generally need the Received lines, Authentication-Results, Return-Path, From, Message-ID and Date, and the body is not needed.
Have headers you cannot interpret? Send us the headers with the recipient address removed and we will point to the line that matters.
Further reading and sources
Frequently asked questions
How do I view the full headers of an email?
In Gmail, open the message, choose the three-dot menu and select Show original. In Outlook on the web, open the message and use View message source or the headers option under the menu. In desktop clients there is usually a View source or Properties option. Wording varies, so look for original, source or internet headers.
Why do I read Received headers from the bottom up?
Each server that handles a message adds a Received line at the top. The newest hop is therefore at the top and the first hop is at the bottom. Reading from the bottom follows the order in which the message actually travelled.
What does Authentication-Results show?
It records the verdicts the receiving server reached when it checked SPF, DKIM and DMARC, including the domains used. It is the quickest way to see whether authentication passed and whether the passing domain aligns with the From address.
Can headers be forged?
Yes, lines added by the sender can be faked, so only trust headers added by servers you trust. The Authentication-Results line added by your own receiving provider is reliable. Received lines below the first trusted hop can be invented by a sender.
Why did my message pass SPF and DKIM but fail DMARC?
DMARC requires alignment. SPF may pass for the return-path domain and DKIM may pass for a signing domain, but if neither matches the domain in the From address, DMARC fails. Compare the three domains in the headers.
How can I find where a delay happened?
Compare the timestamps in successive Received lines. A large gap between two hops shows where the message waited, which is usually a greylisting delay, a rate limit or a queue at the receiving or sending side.
What is ARC and why do I see it?
Authenticated Received Chain headers let intermediaries such as forwarders and mailing lists record the authentication results they saw, so that a later receiver can take them into account. They are most relevant when mail passes through a forwarder.
Which header tells me a message went to spam?
There is no universal one. Some providers add headers with a spam score or verdict, such as X-Spam-Status, but the names differ between providers. Gmail shows spam reasons only indirectly, so combine headers with Postmaster Tools data and your delivery logs.
Is it safe to share headers with support?
Headers can contain IP addresses, internal server names and message identifiers. Remove or mask recipient addresses you do not want to expose, and share them only with people who need them. Never share passwords or API keys, which do not appear in headers.