---
url: https://findutils.com/blog/how-to-read-email-received-headers-trace-the-path-and-find-the-delay
title: "How to Read Email Received Headers: Trace the Path and Find the Delay"
description: "Read Received headers from the bottom up: each mail server adds one line at the top. What from, by, with, id, for and the timestamp mean, how to work out where a message waited, which lines a sender can fake, and a worked example."
category: security
content_type: blog
cluster: email-deliverability
locale: en
read_time: 8
status: published
author: "olgunozoktas"
published_at: 2026-10-28T15:08:00Z
excerpt: "Every mail server that accepts a message writes one Received line at the top of its headers, so the route is recorded newest first. Read the lines from the bottom up, convert each timestamp to one time zone, and the biggest gap shows where the message waited. This post explains each part of a Received line, walks through a four-hop example where a message lost 35 minutes, and shows which lines you can trust."
tag_ids: ["email", "email-headers", "received-header", "deliverability", "smtp"]
tags: ["Email", "Email Headers", "Received Header", "Deliverability", "SMTP"]
primary_keyword: "email received headers"
secondary_keywords: ["how to read email headers", "trace email path", "why was my email delayed", "received header explained", "esmtps meaning", "email header timestamps"]
tool_tag: "email-header-analyzer"
related_tool: "email-header-analyzer"
related_tools: ["email-header-analyzer", "ip-address-lookup", "reverse-dns-lookup", "ip-blacklist-checker", "timezone-converter", "email-security-checker"]
updated_at: "2026-10-28T15:08:00Z"
og_image: "/images/content/blog/how-to-read-email-received-headers-trace-the-path-and-find-the-delay-cover-20261028.webp"
image_alt: "A vertical stack of four header strips on a dark navy background, read from the bottom up along an arrow, with a small clock beside the one gap that is much wider than the others."
---

To read email **Received headers**, start at the **bottom** and work up. Every mail server that accepts a message adds one `Received:` line at the **top** of the headers, so the lowest line is the first hop and the highest is the last. Each line says who handed the message over (`from`), who took it (`by`), how (`with`) and **when** (the date after the semicolon). Convert those dates to one time zone, subtract each from the next, and the biggest gap shows where the message waited.

If you want the arithmetic done for you, paste the headers into the FindUtils [Email Header Analyzer](/network/email-header-analyzer/). It lists the hops oldest first with the time between them. This post explains what the tool is reading, so you can check the result and spot the lines that cannot be trusted.

## Why the Route Is Written Upside Down

The rule comes from the SMTP standard, RFC 5321. A server that accepts a message "MUST insert trace ("time stamp" or "Received") information at the beginning of the message content", and servers "MUST prepend Received lines to messages; they MUST NOT change the order of existing lines". Each new stamp goes on top of the pile, so the pile reads newest first.

That gives you two simple rules:

1. **The bottom `Received:` line is the oldest hop.** It is usually the server that took the message from the sender's mail program or application.
2. **The top `Received:` line is the newest.** It is usually written by your own provider, at or near final delivery.

The `Return-Path:` line that often sits above them is added at final delivery too. It holds the envelope sender (where bounces go), which can differ from the `From:` address you see.

## The Parts of a Received Line

A typical line, wrapped over several lines as headers often are:

```
Received: from mx.example.org (mx.example.org. [198.51.100.40])
        by mx.google.com with ESMTPS id k7si120345
        for <reader@example.com>
        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
        Tue, 27 Oct 2026 07:21:41 -0700 (PDT)
```

| Part | What it means |
|---|---|
| `from mx.example.org` | The name the sending machine gave when it said hello. The sender chooses it. |
| `(mx.example.org. [198.51.100.40])` | What the receiving server saw: usually the reverse DNS name of the connection and its IP address in square brackets. RFC 5321 says the address comes from the TCP connection, so this part is written by the receiver, not by the sender. |
| `by mx.google.com` | The server that accepted the message and wrote this line. |
| `with ESMTPS` | The protocol. `ESMTP` is extended SMTP, `ESMTPS` adds TLS encryption, `ESMTPA` means the sender logged in, and `ESMTPSA` means both (RFC 3848). `LMTP` usually marks the last hand-off inside a provider, to the mailbox store. |
| `id k7si120345` | The receiving server's own ID for the message. Quote it when you ask that provider about a message. |
| `for <reader@example.com>` | The recipient this copy was for. It is optional. |
| `; Tue, 27 Oct 2026 07:21:41 -0700` | When this server accepted the message, by its own clock, with its time-zone offset. |

Header lines are allowed to wrap: RFC 5322 lets a long field continue on the next line if that line starts with a space or tab. When you read headers by hand, treat the indented lines as part of the line above.

## A Worked Example: Where Did 35 Minutes Go?

Here are the four `Received:` lines of a sample message (shortened, with documentation addresses), newest first as they appear in the headers:

```
Received: by 2002:a05:6400:1b2c:b0:2a1:9f3e:7c41 with SMTP id m12csp88123;
        Tue, 27 Oct 2026 07:21:42 -0700 (PDT)
Received: from mx.example.org (mx.example.org. [198.51.100.40])
        by mx.google.com with ESMTPS id k7si120345 ...;
        Tue, 27 Oct 2026 07:21:41 -0700 (PDT)
Received: from queue.example.org (queue.example.org [203.0.113.18])
        by mx.example.org (Postfix) with ESMTPS id 4Nf2Xq;
        Tue, 27 Oct 2026 13:46:58 +0000 (UTC)
Received: from [192.168.1.23] (unknown [203.0.113.77])
        by queue.example.org (Postfix) with ESMTPSA id 4Nf0Zt;
        Tue, 27 Oct 2026 13:46:54 +0000 (UTC)
Date: Tue, 27 Oct 2026 16:46:52 +0300
```

Read from the bottom up and convert everything to UTC:

| Hop | Accepted by | Timestamp (UTC) | Gap |
|---|---|---|---|
| Date header | sender's mail program | 13:46:52 | |
| 1 | queue.example.org | 13:46:54 | 2 s |
| 2 | mx.example.org | 13:46:58 | 4 s |
| 3 | mx.google.com | 14:21:41 (07:21:41 -0700) | **34 min 43 s** |
| 4 | Google's internal server | 14:21:42 | 1 s |

The message left the sender's laptop and crossed the sender's own two servers in six seconds. Then it took almost 35 minutes to be accepted by the recipient's provider. In the Email Header Analyzer, the same headers show as four hops with `+4s`, `+35m` and `+1s` badges.

The key point: **a gap is charged to the hop before it**. The `+35m` sits on hop 3, but the message spent that time on **mx.example.org**, the server that was trying to hand it over. Hop 3's stamp only records when the receiving side finally said yes.

Common reasons a message waits at a hand-off like this:

- **A temporary rejection and a retry.** The receiving server answered with a 4xx "try again later" code, and the sending server queued the message. RFC 5321 says a sender "MUST delay retrying" after a failed attempt and that the retry interval "SHOULD be at least 30 minutes". Greylisting (RFC 6647) uses exactly this: it temporarily rejects mail from unfamiliar sources and accepts the retry.
- **A busy or rate-limited outgoing queue** on the sending side, common with bulk senders.
- **A scheduled send.** If the gap is between the `Date:` header and the first hop instead, the message was probably written earlier and sent later. RFC 5322 says the `Date:` field is when the creator marked the message ready, such as pressing Send, and is "specifically not intended to convey the time that the message is actually transported".

The headers tell you where the time went. Only the logs of the server that held the message can tell you why. Give that server's administrator the `id` from its line and the timestamps.

## Which Lines You Can Trust

A sending program can put any text it likes into the headers it sends, including made-up `Received:` lines. Only lines added by servers you trust are reliable, and the only servers you know for sure are your own provider's.

So, to find where a suspicious message really came from:

1. Find the **highest** `Received:` line written by a server outside your provider. Its `by` part names your provider's server, and its `from` part names the outside machine.
2. Take the IP address in square brackets **inside the parentheses** of that line. Your provider's server recorded it from the connection.
3. Treat every line below it as a claim, not a fact.

Watch for the case in hop 1 above: `from [192.168.1.23] (unknown [203.0.113.77])`. The first bracketed address is what the sending machine called itself, a private home-network address here. The address the server saw is `203.0.113.77`, inside the parentheses. Name and address checks then go on that second one: look it up in [IP Address Lookup](/network/ip-address-lookup/), check its name with [Reverse DNS Lookup](/network/reverse-dns-lookup/), and see whether it is listed in [IP Blacklist Checker](/network/ip-blacklist-checker/).

The same caution applies to `Authentication-Results:`. RFC 8601 tells receiving servers to delete any such header that claims to come from inside their own domain before adding their own, so read the one with your provider's name at the start.

## Clock Trouble: When a Later Hop Looks Earlier

Each timestamp comes from the clock of the server that wrote it. If one clock is off, a later hop can show an earlier time, which looks like a negative delay. That is not a delay at all; it means at least one server's clock is wrong. RFC 5321 asks servers to write explicit offsets such as `-0800`, which is why you can always convert to one zone. A [Timezone Converter](/productivity/timezone-converter/) helps when you work through the times by hand.

The Email Header Analyzer shows the size of each gap, not its direction, so when a gap looks odd, compare the two timestamps in the raw text.

## A Checklist for Reading Received Headers

- Copy the **full** headers (Gmail: Show original; Outlook: View message details; Apple Mail: Raw Source).
- Read `Received:` lines **from the bottom up**, joining wrapped lines.
- Convert every timestamp to **UTC** before subtracting.
- Compare `Date:` with the first hop to catch a scheduled or delayed send.
- Find the **biggest gap** and remember it belongs to the server **before** that hop.
- Trust only the lines your **own provider** wrote, and use the address **inside the parentheses**.
- For authentication results, read the `Authentication-Results:` line written by your provider.

Need help with a project? The team behind FindUtils takes on freelance work through [Upwork](https://www.upwork.com/freelancers/~010a5875eab37b4bd7), including [a Laravel bug fix, version upgrade or new feature for your app](https://www.upwork.com/services/product/development-it-a-laravel-bug-fix-version-upgrade-or-new-feature-for-your-app-2112347524955159675).

## FAQ

### Should I read email headers from the top or the bottom?

From the bottom. Each server adds its `Received:` line at the top, so the lowest line is the first hop and the highest is the last.

### How do I tell where an email was delayed?

Convert each `Received:` timestamp to one time zone and subtract each from the next. The biggest gap shows where the message waited, and that time was spent on the server of the hop before the gap.

### What does ESMTPS or ESMTPSA mean in a Received header?

They are protocol names from RFC 3848. `ESMTPS` means the hand-off used TLS encryption. `ESMTPSA` means TLS was used and the sender logged in, which is typical for the first hop from a mail program.

### Can Received headers be faked?

The lines below your provider's first one can be, because the sender supplies them. The lines your own provider added, and the connection address it recorded, are the ones to rely on.

### Why is the Date header earlier than every Received line?

The `Date:` header is set by the sender's program when the message is marked ready, not when it travels. A short gap is normal. A long one usually means a scheduled send or a message that sat in an outbox.

## Related Reading

- [Email Header Analyzer guide](/guides/email-header-analyzer-guide/)
- [SPF, DKIM and DMARC explained: why email lands in spam](/blog/spf-dkim-dmarc-explained-why-email-lands-in-spam/)
- [Understanding IP addresses](/blog/understanding-ip-addresses-complete-guide/)

## Sources

- [RFC 5321: Simple Mail Transfer Protocol (section 4.4 Trace Information, section 4.5.4.1 Sending Strategy)](https://www.rfc-editor.org/rfc/rfc5321)
- [RFC 5322: Internet Message Format (sections 2.2.3, 3.6.1 and 3.6.7)](https://www.rfc-editor.org/rfc/rfc5322)
- [RFC 3848: ESMTP and LMTP Transmission Types Registration](https://www.rfc-editor.org/rfc/rfc3848)
- [RFC 6647: Email Greylisting](https://www.rfc-editor.org/rfc/rfc6647)
- [RFC 8601: Message Header Field for Indicating Message Authentication Status](https://www.rfc-editor.org/rfc/rfc8601)
- [Gmail Help: Trace an email with its full header](https://support.google.com/mail/answer/29436)
