# How to read email headers

URL: https://iblockspam.com/blog/how-to-read-email-headers
Last updated: 2026-10-09
Published: 2026-10-09
Topic: Running email day to day
Author: iBlockSpam Team

> Read email headers step by step: the Received chain from the bottom up, Authentication-Results, ARC, Return-Path, Message-ID and Microsoft 365 anti-spam fields.

## Short answer

Open the full headers, then read the Received lines from the bottom up to trace the path from sender to you. Next, find the Authentication-Results header added by your own mail system and check spf, dkim and dmarc. Compare the From, Return-Path and DKIM domains. Mismatches and unexpected servers are your clues.

Email headers are the message's travel record. They show which servers handled it, whether it passed SPF, DKIM and DMARC, and what your spam filter decided. Once you know which lines to trust, you can answer most "why did this land in spam?" and "is this real?" questions in a few minutes.

## How do I see the full email headers?

Every client hides headers by default. Here's where to find them:

| Client | Steps |
|---|---|
| Gmail (web) | Open the message, select **More** (three dots) next to Reply, then **Show original**. Select **Copy to clipboard**. |
| New Outlook for Windows and Outlook on the web | Open the message, select **More actions**, then **View** > **View message details**. |
| Classic Outlook for Windows | Double-click to open the message in its own window, then **File** > **Properties**. Headers are in the **Internet headers** box. |
| Apple Mail (Mac) | Select the message, then **View** > **Message** > **All Headers**. |

The steps come from [Gmail Help](https://support.google.com/mail/answer/29436), [Microsoft Support](https://support.microsoft.com/office/cd039382-dc6e-4264-ac74-c048563d212c) and [Apple's Mail guide](https://support.apple.com/guide/mail/show-detailed-email-headers-mlhlp1089/16.0/mac/15.0). Copy everything, from the first line to the blank line before the message body.

If a user forwards you a suspicious email, the headers you see belong to the forward, not the original. Ask them to send it as an attachment, or to copy the headers using the steps above.

## Which email headers can you trust?

This is the most important idea in header analysis. A header is only as trustworthy as the system that wrote it.

- **Written by the sender:** From, To, Subject, Date, Reply-To, Message-ID, and any Received lines added before the message reached your systems. The sender can put anything here.
- **Written by your receiving systems:** the top Received lines, Authentication-Results, and filter headers such as Microsoft's X-Forefront-Antispam-Report. These are reliable, as long as you know which servers are yours.

[RFC 8601](https://www.rfc-editor.org/rfc/rfc8601.html), which defines Authentication-Results, requires a receiving server to delete any copy of that header that claims to come from its own domain but arrived from outside. That stops an attacker pre-stamping `dmarc=pass`. It only works if you read the header with **your** provider's name in it.

## How to read the Received chain (bottom up)

Each mail server that accepts a message must add a Received line **at the top** of the header. [RFC 5321, section 4.4](https://www.rfc-editor.org/rfc/rfc5321.html#section-4.4) says servers must not change or reorder existing lines. So the newest hop is at the top, and the oldest is at the bottom.

A simplified chain:

```
Received: from mx.filter.example (mx.filter.example [198.51.100.25])
    by mail.yourcompany.example with ESMTPS id 4Xk2...; Thu, 8 Oct 2026 09:14:07 +0000
Received: from out.mailer.example (out.mailer.example [203.0.113.40])
    by mx.filter.example with ESMTPS id a81f...; Thu, 8 Oct 2026 09:14:05 +0000
Received: from [192.0.2.17] (helo=laptop)
    by out.mailer.example with ESMTPSA; Thu, 8 Oct 2026 09:14:03 +0000
```

Read it from the bottom:

1. A device at `192.0.2.17` submitted the message to `out.mailer.example` (the `SA` in `ESMTPSA` means TLS plus SMTP authentication, per [RFC 3848](https://www.rfc-editor.org/rfc/rfc3848.html)).
2. `out.mailer.example`, at `203.0.113.40`, delivered it to the filtering server.
3. The filtering server passed it to your mail server.

Each line has the same parts: **from** (the host name it claimed and the IP the receiving server actually saw), **by** (the server that wrote the line), **with** (the protocol; `ESMTPS` means TLS was used), and a timestamp.

### What to look for in the Received chain

- **The handover point.** Find the first line written by a server you trust, such as your provider or gateway. The IP in its `from` part is the real connecting server. Everything below it is the sender's claim.
- **Gaps in time.** Compare timestamps hop by hop. A long gap shows where a message was delayed, for example when a server was down and the sender retried.
- **Mismatched names.** A server that calls itself `mail.bank.example` but connects from an IP with no matching reverse DNS is worth a closer look.
- **Unexpected routes.** If mail to your domain reaches your mailboxes without passing your filter, someone may be bypassing your MX. See [how to block direct-to-tenant delivery](https://iblockspam.com/blog/block-direct-to-tenant-bypass).

## How to read Authentication-Results

Find the Authentication-Results header that starts with your receiving system's name. In Microsoft 365, a typical one looks like this:

```
Authentication-Results: spf=pass (sender IP is 203.0.113.40)
  smtp.mailfrom=bounce.mailer.example; dkim=pass (signature was verified)
  header.d=example.com; dmarc=pass action=none header.from=example.com;
  compauth=pass reason=100
```

The key fields, as described by [Microsoft Learn](https://learn.microsoft.com/en-us/defender-office-365/message-headers-eop-mdo):

| Field | Meaning |
|---|---|
| `spf=` | Result of SPF for the envelope sender: pass, fail, softfail, neutral, none, temperror or permerror |
| `smtp.mailfrom=` | The envelope sender's domain, which SPF checked |
| `dkim=` | Result of DKIM: pass, fail (with a reason) or none |
| `header.d=` | The domain that signed with DKIM |
| `dmarc=` | Result of DMARC for the From domain |
| `header.from=` | The domain in the visible From address |
| `action=` | What Microsoft did based on the DMARC result, such as `oreject` (it overrode a reject policy and treated the message as spam) |
| `compauth=` | Microsoft's composite result: pass, fail, softpass or none |
| `reason=` | A three-digit code explaining compauth |

Now compare the three domains. In the example, SPF passed for `bounce.mailer.example`, which doesn't align with `example.com`. DKIM passed for `example.com`, which does. That aligned DKIM pass is why DMARC passed. For a refresher on alignment, see [SPF vs DKIM vs DMARC](https://iblockspam.com/blog/spf-vs-dkim-vs-dmarc).

A few compauth reason codes worth knowing: `000` means explicit DMARC failure against a quarantine or reject policy; `001` means implicit failure, often a sender with weak or missing records; `130` means a trusted ARC sealer overrode a DMARC failure; `905` means DMARC wasn't enforced because of complex routing, such as mail passing through a non-Microsoft service first.

## What are ARC headers?

When a mailing list or forwarding service changes a message, SPF and DKIM can break, and DMARC fails. [ARC (RFC 8617)](https://www.rfc-editor.org/rfc/rfc8617.html) lets each intermediary record what the authentication results were when it received the message, then seal that record with a signature.

Each intermediary adds a set of three headers, numbered with `i=1`, `i=2` and so on:

- **ARC-Authentication-Results:** the results that intermediary saw.
- **ARC-Message-Signature:** a DKIM-like signature over the message.
- **ARC-Seal:** a signature over the ARC headers, with `cv=` (chain validation) set to `none`, `pass` or `fail`.

ARC is an Experimental RFC. A receiver only uses it if it trusts the sealer. In Microsoft 365, admins can add [trusted ARC sealers](https://learn.microsoft.com/en-us/defender-office-365/email-authentication-arc-configure), which is how compauth reason `130` happens.

## Return-Path and Message-ID

**Return-Path** is added by the server that makes final delivery. It records the envelope sender (the SMTP `MAIL FROM` address), which is where bounces go ([RFC 5321, section 4.4](https://www.rfc-editor.org/rfc/rfc5321.html#section-4.4)). It's often different from From. Mailing platforms usually use their own bounce domain, which is normal. A Return-Path on a domain with no connection to the From domain, combined with failing DKIM, is a stronger warning sign.

**Message-ID** is a unique identifier the sending system creates. [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.6.4) says every message should have one. The part after the `@` often hints at the system that created it. It's useful for searching logs and message traces, but it's written by the sender, so it proves nothing on its own.

## How to read Microsoft 365 anti-spam headers

Microsoft 365 adds two headers to every inbound message. [Microsoft Learn](https://learn.microsoft.com/en-us/defender-office-365/message-headers-eop-mdo) documents the useful fields:

| Header and field | What it tells you |
|---|---|
| `X-Forefront-Antispam-Report: CIP` | Connecting IP address |
| `CTRY` | Country of the connecting IP, which may differ from the original sender's |
| `H` | The HELO/EHLO name the connecting server used |
| `PTR` | Reverse DNS of the source IP |
| `DIR` | Direction: `INB` inbound, `OUT` outbound, `INT` internal |
| `SFV` | Spam filtering verdict, such as `NSPM` (not spam), `SPM` (spam), `SKA` (allowed by anti-spam policy), `SFE` (user's Safe Senders), `BLK` (user's Blocked Senders) |
| `CAT` | Policy category applied, such as `SPM`, `HSPM`, `PHSH`, `HPHISH`, `SPOOF`, `BULK`, `MALW` |
| `SCL` | Spam confidence level. Microsoft says it doesn't decide filtering in cloud organizations; use `CAT` and `DIR` instead |
| `SFTY` | Impersonation or first-contact safety tip markers, such as `9.19`, `9.20`, `9.25` |
| `X-Microsoft-Antispam: BCL` | Bulk complaint level; higher means more likely to draw complaints |

Every SFV and CAT value, plus the compauth reason codes, is listed in [Microsoft 365 spam headers explained](https://iblockspam.com/blog/microsoft-365-spam-headers-explained).

If `CIP` shows your gateway's IP rather than the original sender's, Microsoft is judging the gateway, not the sender. That's what [Enhanced Filtering for Connectors](https://iblockspam.com/blog/microsoft-365-third-party-spam-filter-enhanced-filtering) fixes.

## A five-minute header check

1. Copy the full headers using the steps above.
2. Paste them into the [Email Header Analyzer](https://iblockspam.com/tools/email-header-analyzer) to lay out the hops and results.
3. Find the first Received line written by a server you trust. Note the connecting IP.
4. Read the Authentication-Results from your own system. Check `spf`, `dkim` and `dmarc`, and compare `smtp.mailfrom`, `header.d` and `header.from`.
5. If you use Microsoft 365, read `CAT`, `SFV` and `compauth` to see what the filter decided and why.
6. Note anything that doesn't fit: a lookalike domain in From, a Reply-To on a different domain, a failed DMARC check, or an unusual route.

## What do common header warning signs mean?

| What you see | Likely meaning | What to do |
|---|---|---|
| `dmarc=fail` with `header.from` on your own domain | Someone is spoofing your domain, or one of your tools isn't aligned | Check your DMARC reports and sending tools |
| `dkim=fail (body hash did not verify)` | The message was changed after signing, often by a forwarder or footer | Look for ARC headers or a list server in the chain |
| `spf=softfail` or `spf=fail` | The connecting IP isn't in the sender's SPF record | Check whether a forwarder sits in the chain |
| Reply-To on a different domain from From | Replies go somewhere other than the apparent sender | Treat payment or credential requests with suspicion |
| `SFV:SKA` or `SFV:SFE` on a phishing message | An allow list let it skip filtering | Review your allow lists |
| Large gap between two timestamps | Delay at that hop | Check that server's queue or availability |

If the message is suspicious, the patterns in [what is email spoofing](https://iblockspam.com/blog/what-is-email-spoofing) will help you decide what it is.

## Next steps

- Practice on a message you know is legitimate, so you recognize your own normal path.
- Bookmark the [Email Header Analyzer](https://iblockspam.com/tools/email-header-analyzer). It runs in your browser, so nothing is uploaded.
- If legitimate mail keeps landing in junk, work through [why did this email land in spam](https://iblockspam.com/blog/why-did-this-email-land-in-spam).
- If you use a filtering service such as iBlockSpam, its Received line will appear between the sender and your mailbox. Knowing its host names makes the handover point easy to find.

Browse more guides on [running email day to day](https://iblockspam.com/blog/topic/operations).

## Frequently asked questions

### Which Received header is the sender's?

The lowest one, usually. Each server adds its Received line at the top, so the bottom line is the oldest. But the sender's own servers write the lowest lines, and an attacker can fake those. Trust starts at the first line added by a server you control or trust, and works down from there.

### Can email headers be faked?

Some can. The sender controls From, Reply-To, Message-ID and any Received lines added before the message reached your systems. They can't forge the Received and Authentication-Results lines your own mail servers add, which is why you read those first.

### Why is the Return-Path different from the From address?

Often for a good reason. Return-Path records the envelope sender, where bounces go. Newsletter platforms and ticketing tools commonly use their own bounce domains. It only matters for DMARC if neither SPF nor DKIM produces a pass for a domain aligned with the From address.

### What does SCL mean in Microsoft 365 headers?

SCL is the spam confidence level. Microsoft says that in cloud organizations it doesn't decide whether a message is treated as spam. To understand how Microsoft 365 filtered a message, read the CAT and SFV values in X-Forefront-Antispam-Report instead.

### Is it safe to paste headers into an online analyzer?

Headers contain names, addresses, internal server names and IP addresses. Use a tool you trust, or one that processes headers locally. Our Email Header Analyzer runs in your browser, so the headers you paste aren't uploaded.

## Sources

- [RFC 5321: Simple Mail Transfer Protocol, section 4.4 Trace Information](https://www.rfc-editor.org/rfc/rfc5321.html#section-4.4)
- [RFC 5322: Internet Message Format, section 3.6.4 Identification Fields](https://www.rfc-editor.org/rfc/rfc5322.html#section-3.6.4)
- [RFC 8601: Message Header Field for Indicating Message Authentication Status](https://www.rfc-editor.org/rfc/rfc8601.html)
- [RFC 8617: The Authenticated Received Chain (ARC) Protocol](https://www.rfc-editor.org/rfc/rfc8617.html)
- [Microsoft Learn: Anti-spam message headers](https://learn.microsoft.com/en-us/defender-office-365/message-headers-eop-mdo)
- [Microsoft Support: View internet message headers in Outlook](https://support.microsoft.com/office/cd039382-dc6e-4264-ac74-c048563d212c)
- [Gmail Help: Trace an email with its full headers](https://support.google.com/mail/answer/29436)
- [Apple Support: Show detailed headers in Mail on Mac (macOS Sequoia)](https://support.apple.com/guide/mail/show-detailed-email-headers-mlhlp1089/16.0/mac/15.0)

## Free tools for this guide

- [Email Header Analyzer](https://iblockspam.com/tools/email-header-analyzer): Trace hops and authentication results — runs entirely in your browser.
- [SMTP Error Code Lookup](https://iblockspam.com/tools/smtp-error-codes): Paste a bounce or type a code like 550 5.7.26: plain-English meaning, likely causes and fixes, with sources.
- [SPF Checker](https://iblockspam.com/tools/spf-checker): Count real DNS lookups, find PermErrors, loops and risky "all" settings.
- [DMARC Checker](https://iblockspam.com/tools/dmarc-checker): Check your policy, reporting and the safe path from p=none to reject.

---

Source: iBlockSpam, https://iblockspam.com/blog/how-to-read-email-headers (this is a Markdown copy; the HTML page is canonical). Quote with attribution and a link. Site index for AI assistants: https://iblockspam.com/llms.txt
