---
title: "Analyze email headers"
description: "Paste a message's headers to see its SPF, DKIM and DMARC results, alignment, unsubscribe headers and the delay at each hop. Nothing leaves your browser."
url: https://www.unitpost.com/tools/email-header-analyzer
section: Free tools
updated: 2026-11-02
---
# Analyze email headers

Email headers record how a message traveled and how the receiving server judged it. Paste the full original headers and this tool lists each Received hop from first to last with the delay it added, reads the receiver's Authentication-Results for SPF, DKIM and DMARC, checks whether the DKIM and Return-Path domains align with the From domain, and flags missing List-Unsubscribe, Message-ID or Date headers.

> Interactive tool: https://www.unitpost.com/tools/email-header-analyzer. The headers are parsed in your browser and never leave it. Nothing is sent to Unitpost, and there's no sign-up.

## How to copy the original headers

> 

Open the message in the mailbox that received it and copy its original source. Forwarding the message doesn't work: the forward carries new headers, not the ones you need.

| Mail app | Steps |
| --- | --- |
| Gmail on the web | Open the message, click More (the three dots beside Reply), choose Show original, then Copy to clipboard. |
| Outlook on the web, Outlook.com and new Outlook | Open the message, select More actions at the top of the message, then View, then View message details. |
| Classic Outlook for Windows | Double-click the message to open it in its own window, choose File, then Properties, and copy the Internet headers box. |
| Apple Mail on Mac | Open the message and choose View, then Message, then All Headers. Raw Source in the same menu shows the whole message. |

Paste from the first header line. Including the body is fine: the analyzer reads up to the first blank line, which is where headers end.

## Reading Received hops from the bottom up

> 

Every server that handles a message adds a Received header at the top, so the bottom one is the first hop, usually the sender's own server, and the top one is the last, inside the recipient's mailbox provider.

**One Received header**

```bash
Received: from mail.example.com (mail.example.com [203.0.113.10])
        by mx.mailhost.example with ESMTPS id abc123
        for <jane@mailhost.example>; Mon, 02 Nov 2026 14:05:09 +0000
```

`from` is the server that handed the message over, `by` is the server that took it, `with` is the protocol, and the time after the semicolon is when it arrived. The delay at a hop is the gap between its time and the time on the hop below. Servers' clocks drift, so a few seconds either way, or a negative gap, means clock skew rather than a problem.

Only the hops your own mailbox provider added are trustworthy. Anything below its first hop was written by servers before it and can be forged.

## Reading Authentication-Results

> 

Authentication-Results (RFC 8601) is the receiving server's own verdict on SPF, DKIM and DMARC. The topmost one, added by the recipient's mailbox provider, is the one that counts, and it is the one the analyzer reads. It reports those verdicts; it doesn't re-verify signatures, which needs the body and live DNS.

**A passing, aligned message**

```bash
Authentication-Results: mx.google.com;
       dkim=pass header.i=@example.com header.s=s1;
       spf=pass smtp.mailfrom=unitpost.example.com;
       dmarc=pass (p=NONE) header.from=example.com
```

| Result | Meaning |
| --- | --- |
| `pass` | The check succeeded for the domain named on the line. |
| `fail` | The check ran and failed: an unlisted server for SPF, a signature that didn't verify for DKIM, no aligned pass for DMARC. |
| `softfail` | SPF only: the server isn't listed and the record ends in `~all`. |
| `neutral` | SPF: the record makes no claim (`?all`). Some receivers also use it for a DKIM key they couldn't find. |
| `none` | Nothing to check: no SPF record, no DKIM signature, or no DMARC record. |
| `temperror` | A DNS lookup failed at the time; it may pass on retry. |
| `permerror` | The record is broken (two SPF records, too many lookups, a malformed key) and fails every time. |

DMARC passes when SPF or DKIM passes for a domain aligned with `header.from`. Compare `smtp.mailfrom` and the DKIM `header.i` or `header.d` with the From domain to see which one carried it. In the example, DKIM passed for `example.com` itself, and SPF passed for a subdomain of it.

## Errors and how to fix them

### No email headers found in the pasted text

Also reported as: Can't parse email headers; Invalid email header format

Nothing in the paste looks like `Name: value` header lines starting at the top. That happens when the paste begins with the body, with a blank line, or with the short From, To and Subject summary a mail app shows instead of the source.

1. Copy the original source with the steps in [how to copy the original headers](/tools/email-header-analyzer#copy-headers).
2. Paste from the very first line, often `Delivered-To:` or `Received:`.
3. Remove any blank lines before the first header.

### SPF fail in Authentication-Results

Also reported as: spf=fail; spf=softfail; spf=permerror; spf=temperror

The receiver's SPF result for the envelope sender (`smtp.mailfrom`) was fail, softfail, temperror or permerror: the server that delivered the message isn't authorized by that domain's SPF record, or the record couldn't be evaluated.

1. Check the `smtp.mailfrom` domain with the [SPF checker](/tools/spf-checker). A permerror there, such as too many lookups or two records, fails every message.
2. For a fail or softfail, authorize the sending service in that domain's record, or have the service use a return-path subdomain of yours with its own record.
3. For a temperror, check that your nameservers answer; it was a DNS failure at delivery time.
4. A forwarded message fails SPF because the forwarder's server isn't in your record. DKIM is what survives forwarding.

### DKIM fail: no signature verified

Also reported as: dkim=fail; dkim=neutral (body hash did not verify); dkim=permerror

The message carries DKIM results and none of them is a pass. Either the message changed after it was signed (a footer, rewritten links, a forwarding rule), or the public key in DNS doesn't match the private key that signed it.

1. Look up each signature's `s=` and `d=` with the [DKIM checker](/tools/dkim-checker). A missing, revoked or truncated key fails every message.
2. If the key is fine and only some messages fail, look for something that edits mail after it is sent: a mailing list, a security gateway, a disclaimer added by a mail server.
3. Send a fresh test straight to a Gmail address and check its headers. Causes in detail: [why DKIM verification fails](/blog/troubleshooting/dkim-verification-failing).

### Message is not DKIM-signed

Also reported as: dkim=none; No DKIM signature; Missing DKIM-Signature header

The message has no DKIM-Signature header and the receiver reported no DKIM result. DMARC can then pass only through SPF, which breaks on forwarding, and Gmail, Yahoo and Microsoft require bulk senders to sign with DKIM.

1. Turn on DKIM in your sending service for your domain and publish the record it gives you at `<selector>._domainkey.<domain>`.
2. Check that the signing domain (`d=`) is yours, not the service's, so the signature aligns with From.
3. Send a test and paste its headers again.

### DMARC fail in Authentication-Results

Also reported as: dmarc=fail; 550 5.7.26 Unauthenticated email is not accepted due to domain's DMARC policy; DMARC policy failure

The receiver's DMARC result wasn't a pass. `dmarc=fail` means neither SPF nor DKIM passed for a domain aligned with From; `dmarc=none` means the From domain has no DMARC record; `temperror` or `permerror` means the record couldn't be fetched or read.

1. Read the SPF and DKIM lines above it. A pass for a domain other than the From domain doesn't count.
2. Make DKIM sign with your From domain (`d=example.com`) or its parent; that alignment survives forwarding.
3. Or set the Return-Path to a subdomain of your From domain, so SPF aligns too.
4. For `dmarc=none`, publish a record; the [DMARC generator](/tools/dmarc-generator) builds one.

### SPF and DKIM domains don't align with From

Also reported as: DMARC alignment failure; From domain not aligned; 421 4.7.32 From header not aligned

Neither the DKIM signing domain (`d=`) nor the Return-Path domain shares an organizational domain with the From address. SPF and DKIM can both pass and DMARC still fails, because they passed for someone else's domain, usually your email provider's.

1. Set up DKIM for your own domain in your sending service, so it signs with `d=yourdomain`.
2. Use a custom return-path (MAIL FROM) subdomain of your domain. Unitpost does both: it signs with your domain and uses `unitpost.<your domain>` as the return path.
3. Send a test and check that `header.d` or `smtp.mailfrom` ends in your domain.

### No List-Unsubscribe header

Also reported as: Missing List-Unsubscribe; Unsubscribe header missing

The message has no List-Unsubscribe header. Receipts, password resets and other transactional mail don't need one. Marketing and subscribed mail does: Gmail and Yahoo require one-click unsubscribe from bulk senders, and the header is what puts an Unsubscribe button in the inbox.

1. Add both headers to marketing and subscribed mail: `List-Unsubscribe: <https://example.com/unsubscribe/opaque-token>` and `List-Unsubscribe-Post: List-Unsubscribe=One-Click`.
2. Keep an unsubscribe link in the body too.
3. Unitpost campaigns carry both headers. For mail you render yourself, set them on the send: [use your own unsubscribe](/docs/deliverability#deliverability-own-unsubscribe).

### List-Unsubscribe-Post header missing (no one-click)

Also reported as: One-click unsubscribe missing; RFC 8058 one-click unsubscribe not supported

List-Unsubscribe is present but `List-Unsubscribe-Post: List-Unsubscribe=One-Click` isn't, so the inbox can't unsubscribe the reader with a single request. Gmail and Yahoo require one-click (RFC 8058) on marketing and subscribed mail from bulk senders.

1. Add `List-Unsubscribe-Post: List-Unsubscribe=One-Click`.
2. Make sure List-Unsubscribe contains an `https://` URL; a `mailto:` alone can't take a one-click request.
3. Cover both headers with your DKIM signature by listing them in its `h=` tag.
4. Answer the POST without a redirect, and process the unsubscribe within two days. Details: [one-click unsubscribe](/blog/deliverability/bulk-sender-requirements-gmail-yahoo-microsoft#one-click-unsubscribe).

### Email delayed between servers

Also reported as: Slow email delivery; Email delayed in transit; Long delay in Received headers

More than five minutes passed between two Received timestamps. That usually means greylisting (the receiver deferred the first attempt on purpose), a queue on the sending side, or a retry after a temporary 4xx reply. Clock drift between servers can make a gap look longer than it was.

1. Find the hop: the delay sits on the server named in its `by` field.
2. If it is the first hop inside the recipient's provider, greylisting is the likely cause; it delays the first message from a new server, not every message.
3. If it is inside your own systems, check that server's queue and logs for deferrals, and look up the reply codes with the [SMTP code lookup](/tools/smtp-codes).

### Missing Message-ID header

Also reported as: No Message-ID header; Message-ID header missing

The message has no Message-ID, which RFC 5322 says every message should carry. Gmail lists a missing Message-ID among the reasons for its `550 5.7.1` rejections, and spam filters score it.

1. Let your mail library or server generate it, in the form `Message-ID: <unique-id@yourdomain>`.
2. Most libraries add one by default; a missing one usually means a hand-built message or a script speaking raw SMTP.

### Missing Date header

Also reported as: No Date header; Date header required

RFC 5322 requires a Date header giving the time the message was written. Without it, receivers can treat the message as malformed.

1. Set it when the message is created, in RFC 5322 form: `Date: Mon, 02 Nov 2026 14:05:00 +0000`.
2. Mail libraries add it unless something strips it, so check any code that builds headers by hand.

## FAQ

### How do I see the full headers of an email in Gmail?

Open the message, click **More** (the three dots beside Reply) and choose **Show original**. The page that opens has a **Copy to clipboard** button.

### How do I read Received headers?

From the bottom up. The bottom Received header is the first server the message passed through, the top one is the last, and the gap between their timestamps is the delay at each hop.

### What does dmarc=fail mean?

Neither SPF nor DKIM passed for a domain that matches the From address. Often both passed, but for your email provider's domain instead of yours.

### Can email headers be faked?

Anything a sender writes can be: From, Date, and every Received line added before the message reached the recipient's provider. The lines that provider added, and its Authentication-Results, are the ones to trust.

### Are the headers I paste sent anywhere?

No. The analyzer runs in your browser and makes no network requests with them, so nothing reaches Unitpost.

## Related

- [SMTP reply and status codes](https://www.unitpost.com/tools/smtp-codes): Look up an SMTP reply such as 550 5.7.26 or 421 4.7.0: what the basic and enhanced codes mean, whether to retry, and what to fix.
- [SMS character and segment calculator](https://www.unitpost.com/tools/sms-segment-calculator): Count SMS characters and segments as you type: see GSM-7 or UCS-2 encoding, which characters force UCS-2, and the cost per message by country.
- [Check your email domain's SPF, DKIM and DMARC](https://www.unitpost.com/tools/domain-checker): Check a domain's SPF, DKIM, DMARC and MX records in your browser and get a graded report that names each problem and the record that fixes it.
