Exchange ServerHow-to

Reading email headers to find mail delays in Exchange Server: Received lines and hops

An email arrived an hour late? Read the Received headers bottom-up, convert every timestamp to UTC, find the slow hop and confirm it with Exchange message tracking.

"This email took an hour to arrive" is a complaint you can answer precisely, because every server that handled the message wrote a timestamped line into its header. Read those lines in the right order, convert the times, and the slow hop stands out. In this post I'll show how to get the header from the right copy, read the Received lines, use Microsoft's Message Header Analyzer, and confirm the finding with Exchange message tracking.

How this guide is organized: How it works → Step-by-step → Verify → Tips & gotchasFlow diagram of the article's sections in reading order: 1. How it works. 2. Step-by-step (5 steps: Get the header from the recipient's copy; List the hops bottom-up and convert to UTC; Let Message Header Analyzer do the arithmetic; Confirm the hop in message tracking; Match the gap to a cause). 3. Verify. 4. Tips & gotchas. Toolbox: Get-Queue, Message-ID, File › Properties, DELIVER, Date:.1How it works2Step-by-step3Verify4Tips & gotchas1Get the header fromthe recipient's copy2List the hopsbottom-up and co…3Let MessageHeader Analyzer d…4Confirm the hop inmessage tracking5Match the gap to acauseTOOLBOXGet-QueueMessage-IDFile › PropertiesDELIVERDate:How this guide is organized: How it works → Step-by-step → Verify → Tips & gotchasFlow diagram of the article's sections in reading order: 1. How it works. 2. Step-by-step (5 steps: Get the header from the recipient's copy; List the hops bottom-up and convert to UTC; Let Message Header Analyzer do the arithmetic; Confirm the hop in message tracking; Match the gap to a cause). 3. Verify. 4. Tips & gotchas. Toolbox: Get-Queue, Message-ID, File › Properties, DELIVER, Date:.1How it works2Step-by-step1Get the header from the recipient's copy2List the hops bottom-up and convert to UTC3Let Message Header Analyzer do the arithmetic4Confirm the hop in message tracking5Match the gap to a cause3Verify4Tips & gotchasTOOLBOXGet-QueueMessage-IDFile › PropertiesDELIVERDate:
At a glance: how this guide is organized · 5 steps · 5 key settings and tools

How it works#

  • Each SMTP server that accepts a message adds a Received: line at the top of the header. The first hop is therefore the bottom Received line, and the last hop is the top one.
  • Each line says who handed the message over (from), who took it (by) and when, in that server's local time with its UTC offset, such as +0200.
  • The Date: header is set by the sender's mail client, not by a server. A big gap between Date: and the first Received line means the message waited before it ever reached a mail server: an offline Outbox, deferred delivery or an application retrying.
  • Exchange also stamps organization headers that start with X-MS-Exchange-Organization-, for example X-MS-Exchange-Organization-AuthAs (how the sender was authenticated: Anonymous for internet mail, Internal for your own servers and users), X-MS-Exchange-Organization-AuthSource (the server that accepted it) and X-MS-Exchange-Organization-SCL (spam confidence level).
  • The header firewall removes organization headers when mail crosses a connector that isn't trusted to keep them, so you won't see another organization's values. Some organizations also strip their internal Received lines from outbound internet mail, which hides those hops from external recipients.

Step-by-step#

Matching the largest header gap to its causeWhere is the largest gap, with every hop converted to UTC? if Before any server: Check the sending client or application (Offline Outbox, deferred delivery or application retries.); if In sender's hops: Send your hop table to their admin (Their queues or filtering held the message.); if On your side: Which part of your side holds the gap? if Into your gateway: Your side deferred the connection (Check receive protocol logs, gateway logs and back pressure.); if Between your hops: Delay inside Exchange transport (Check Get-Queue and third-party transport agents.); if Outbound: Check DNS and the next hop (DNS failures, timeouts or recipient-side deferrals.)Where is the largest gap, withevery hop converted to UTC?FIXCheck thesending client orapplicationOffline Outbox,deferred delivery orapplication retries.Before any serverSTOPSend your hoptable to theiradminTheir queues orfiltering held themessage.In sender's hopsWhich part of your side holdsthe gap?FIXYour sidedeferred theconnectionCheck receiveprotocol logs,gateway logs andback pressure.Into your gatewayFIXDelay insideExchangetransportCheck Get-Queueand third-partytransport agents.Between your hopsFIXCheck DNS andthe next hopDNS failures,timeouts orrecipient-sidedeferrals.OutboundOn your sideMatching the largest header gap to its causeWhere is the largest gap, with every hop converted to UTC? if Before any server: Check the sending client or application (Offline Outbox, deferred delivery or application retries.); if In sender's hops: Send your hop table to their admin (Their queues or filtering held the message.); if On your side: Which part of your side holds the gap? if Into your gateway: Your side deferred the connection (Check receive protocol logs, gateway logs and back pressure.); if Between your hops: Delay inside Exchange transport (Check Get-Queue and third-party transport agents.); if Outbound: Check DNS and the next hop (DNS failures, timeouts or recipient-side deferrals.)Where is the largest gap, with every hopconverted to UTC?Before any serverFIXCheck the sending client or applicationOffline Outbox, deferred delivery or applicationretries.In sender's hopsSTOPSend your hop table to their adminTheir queues or filtering held the message.On your sideWhich part of your side holds the gap?Into your gatewayFIXYour side deferred the connectionCheck receive protocol logs, gateway logs andback pressure.Between your hopsFIXDelay inside Exchange transportCheck Get-Queue and third-party transportagents.OutboundFIXCheck DNS and the next hopDNS failures, timeouts or recipient-side deferrals.
Figure 1 · Decision tree Matching the largest header gap to its cause. Read the Received lines bottom-up in UTC, find the largest gap, then confirm it in message tracking before you act.

1. Get the header from the recipient's copy#

The sender's Sent Items copy has never crossed the wire, so it tells you nothing about delivery. Use the recipient's copy:

  • Classic Outlook: open the message in its own window, then File › Properties, and copy the Internet headers box.
  • Outlook on the web: open the message's more actions menu (…) and view the message details.

2. List the hops bottom-up and convert to UTC#

Here is a simplified inbound header (protocol details shortened):

Text
Received: from EX01.contoso.com (10.0.0.11) by EX02.contoso.com (10.0.0.12) with ...; <date> 11:12:24 +0200
Received: from gw01.contoso.com (10.0.1.5) by EX01.contoso.com (10.0.0.11) with ...; <date> 11:12:22 +0200
Received: from mail.fabrikam.com (203.0.113.25) by gw01.contoso.com (10.0.1.5) with ESMTPS; <date> 09:12:20 +0000
Received: from client.fabrikam.com (192.0.2.10) by mail.fabrikam.com with ESMTPSA; <date> 09:40:55 +0100
Hop (bottom-up)Local timeUTCGap
Client → mail.fabrikam.com09:40:55 +010008:40:55start
mail.fabrikam.com → gw01 (your gateway)09:12:20 +000009:12:2031 min 25 s
gw01 → EX0111:12:22 +020009:12:222 s
EX01 → EX0211:12:24 +020009:12:242 s

Without converting, the hops look hours apart, or even out of order. In UTC the picture is clear: the half hour was lost before your gateway accepted the message. Either the sender's server held it, or your side deferred its attempts.

3. Let Message Header Analyzer do the arithmetic#

Microsoft's Message Header Analyzer parses the header, converts the times and flags suspected delays. Use the web version at mha.azurewebsites.net, or install the Outlook add-in from AppSource to analyze the selected message directly. Treat a slow hop as a lead, then confirm it in the logs.

4. Confirm the hop in message tracking#

Take the Message-ID: value from the header and search every transport server:

PowerShell
$id = "<CAF1x2y3z@mail.fabrikam.com>"
$t = Get-TransportService | ForEach-Object {
    Get-MessageTrackingLog -Server $_.Name -MessageId $id -Start (Get-Date).AddDays(-2) -ResultSize Unlimited
} | Sort-Object Timestamp

for ($i = 1; $i -lt $t.Count; $i++) {
    "{0}  {1,-10} {2,-12} +{3:n0} s" -f $t[$i].Timestamp, $t[$i].EventId, $t[$i].Source,
        ($t[$i].Timestamp - $t[$i-1].Timestamp).TotalSeconds
}

Good looks like a RECEIVE followed within seconds by SEND or DELIVER. Repeated DEFER events, or a long gap before DELIVER, place the delay inside Exchange. If the first RECEIVE is already late, the delay happened before Exchange accepted the message. My message tracking guide explains every event.

5. Match the gap to a cause#

Where the time wentUsual causesCheck
Between Date: and the first Received lineOffline Outbox, deferred delivery, application retriesThe sending client or application
Inside the sender's own hopsTheir queues or filteringSend your hop table to their admin
Into your gateway or first Exchange serverYour side deferring the connection: back pressure, filtering or connection limitsSMTP receive protocol logs, gateway logs, back pressure
Between your Exchange hops or before DELIVERTransport queues, transport agents, database or delivery issuesGet-Queue, third-party transport agents
Outbound, after your last hopDNS failures, timeouts to the next hop, recipient-side deferrals451 4.4.0 DNS, 441 4.4.1 timeouts

Verify#

  • After fixing the cause, send a test through the same path and read the new header: every hop should be seconds apart in UTC.
  • Message tracking for the test shows RECEIVE to DELIVER (or SEND) without DEFER events.
  • Get-Queue | Where-Object { $_.MessageCount -gt 0 } shows no queue building up on any transport server.

Tips & gotchas#

  • Trust only Received lines added by servers you control; anything below the first hop into your organization was written by others and could be forged.
  • Clock drift makes hops look negative or out of order. Check time sync on your Exchange servers and gateways before blaming the network.
  • Inside Exchange, an internal message still passes through the Transport service, so a message to a colleague on the same server has several hops too.
  • Intentional waits look like delays: moderation, delayed delivery and a recipient's deferral of first attempts are all normal.
  • Keep enough message tracking history: by default Exchange keeps up to 30 days.

References#

Written and checked against current Microsoft Learn documentation. Test changes with a pilot group before rolling them out to everyone, and if an admin center path has moved since, search for the setting name instead.

Spotted a mistake, or did this fix work differently for you? Email me or message me on LinkedIn — corrections are credited in the article.

Written by

Omer Eltayeb

Intune Subject Matter Expert in Cairo, Egypt, former Microsoft Cloud Solutions Architect, Microsoft Certified Trainer and Microsoft Innovative Educator Expert (2024–26) and Microsoft Elevate Educator Expert (2026–27). I share practical, step-by-step guides, study plans, scripts and toolkits for Microsoft Intune, Configuration Manager, Microsoft Entra ID, Microsoft Defender, Exchange and Microsoft 365 with the community.

Microsoft Certified Trainer (MCT) 2026Microsoft Innovative Educator Expert 2025–2026Microsoft Elevate Educator Expert 2026–2027ISC2 Certified Information Systems Security Professional (CISSP)Microsoft 365 Certified: Enterprise Administrator Expert (MS-102)