Exchange OnlineHow-to

Email never arrived? Using message trace in Exchange Online to find out why

Run a message trace in the Exchange admin center or with Get-MessageTraceV2, read the delivery status and events, and pull older data from downloadable reports.

"I never got that email" is a classic helpdesk ticket, and guessing wastes everyone's time. Message trace shows whether Exchange Online received a message, what it did with it and where it ended up. In this post I'll walk through tracing in the Exchange admin center and with the V2 PowerShell cmdlets, how to read the results, and what to do next for each outcome.

How this guide is organised: Prerequisites → Step-by-step → Verify → Tips & gotchasFlow diagram of the article's sections in reading order: 1. Prerequisites. 2. Step-by-step (5 steps: Run a trace in the Exchange admin center; Read the delivery status; Open the message trace details; Trace from PowerShell with the V2 cmdlets; Go further back with downloadable reports). 3. Verify. 4. Tips & gotchas. Toolbox: Message-ID, Get-MessageTrace, Get-MessageTraceDetail, admin.exchange.microsoft.com, *@fabrikam.com.1Prerequisites2Step-by-step3Verify4Tips & gotchas1Run a trace in theExchange admin c…2Read the deliverystatus3Open the messagetrace details4Trace fromPowerShell with t…5Go further backwith downloadabl…TOOLBOXMessage-IDGet-MessageTraceGet-MessageTraceDetailadmin.exchange.microsoft.com*@fabrikam.comHow this guide is organised: Prerequisites → Step-by-step → Verify → Tips & gotchasFlow diagram of the article's sections in reading order: 1. Prerequisites. 2. Step-by-step (5 steps: Run a trace in the Exchange admin center; Read the delivery status; Open the message trace details; Trace from PowerShell with the V2 cmdlets; Go further back with downloadable reports). 3. Verify. 4. Tips & gotchas. Toolbox: Message-ID, Get-MessageTrace, Get-MessageTraceDetail, admin.exchange.microsoft.com, *@fabrikam.com.1Prerequisites2Step-by-step1Run a trace in the Exchange admin center2Read the delivery status3Open the message trace details4Trace from PowerShell with the V2 cmdlets5Go further back with downloadable reports3Verify4Tips & gotchasTOOLBOXMessage-IDGet-MessageTraceGet-MessageTraceDetailadmin.exchange.microsoft.com*@fabrikam.com
At a glance: how this guide is organised · 5 steps · 5 key settings and tools

Prerequisites#

  • Permissions: the Exchange Administrator role in Microsoft Entra ID, or membership of the Organization Management role group in Exchange Online.
  • Facts from the user: sender, recipient, roughly when it was sent (and in which time zone) and the subject. If anyone has a copy, the Message-ID from the headers is the most precise filter there is.
  • For PowerShell: the ExchangeOnlineManagement module, version 3.7.0 or later.

Traces covering 10 days or less return results almost immediately. You can look back up to 90 days, but each near real-time query covers at most 10 days; anything wider becomes a downloadable report.

Step 1: Run a trace in the Exchange admin center#

  1. In the Exchange admin center (admin.exchange.microsoft.com), go to Mail flow › Message trace. The Exchange message trace link in the Microsoft Defender portal opens the same page.
  2. Select Start a trace. The defaults search all senders and recipients for the last two days.
  3. Enter the Senders and/or Recipients. External addresses work, and so does one wildcard per value, such as *@fabrikam.com.
  4. Set the Time range. Switch to Custom time range to pick a time zone and exact start and end times.
  5. Under Detailed search options, narrow it with a subject filter (starts with, ends with or contains), a delivery status, the Message ID (including the angle brackets) or the direction.
  6. Keep the report type as Summary report and select Search.

Step 2: Read the delivery status#

StatusWhat it meansNext step
DeliveredHanded to the mailbox or the recipient's mail serverMail flow worked. Check Junk Email, Inbox rules and the Other tab.
FailedNot deliveredOpen the details; the Fail event carries the reason and NDR code.
PendingDelivery is being attempted or retriedLook at the Defer events and the To IP; usually a receiving-side problem.
QuarantinedHeld as spam, bulk or phishingReview it on the Quarantine page of the Microsoft Defender portal.
Filtered as spamIdentified as spam and rejected or blocked, not quarantinedCheck the verdict in the details and which anti-spam policy applied.
ExpandedA group was expanded to its membersTrace the individual members.
Getting statusReceived moments ago, no data yetWait a few minutes and refresh.

You may also see Recalled when the sender used Message Recall. Two caveats: you can only filter on Pending, Quarantined and Filtered as spam in searches shorter than 10 days, and the reported status can trail reality by five to ten minutes.

Step 3: Open the message trace details#

Click a row (not its round check box) to open the details. Expand Message events and read them in order: Receive first, then any processing, ending in Deliver, Send, Fail or Defer. Other events worth recognizing are Expand (group expansion), Transfer (recipients moved to a split copy of the message), Resolved (redirected to another address) and DLP rule. Even a healthy message logs several events.

More information adds the Message ID, size, From IP and To IP. To pull every record that shares the same Message ID (forwarding, group expansion, mail flow rules), tick the row's check box and choose Find related.

Step 4: Trace from PowerShell with the V2 cmdlets#

Get-MessageTraceV2 and Get-MessageTraceDetailV2 replace Get-MessageTrace and Get-MessageTraceDetail, which Microsoft is retiring, so update any old scripts. The rules have changed:

  • Data goes back 90 days, but one query can span at most 10 days. Without dates you get the last 48 hours.
  • Results default to 1,000 rows and -ResultSize goes up to 5,000. -Page and -PageSize are gone.
  • Timestamps are in UTC, and a tenant can run 100 queries in any five-minute window.
PowerShell
Connect-ExchangeOnline

# Failed messages to one recipient in the last 24 hours
$trace = Get-MessageTraceV2 -RecipientAddress user@contoso.com -Status Failed `
    -StartDate (Get-Date).AddDays(-1) -EndDate (Get-Date)
$trace | Format-Table Received, SenderAddress, Subject, Status

# Event-by-event detail for the same messages
$trace | Get-MessageTraceDetailV2 | Format-List

Valid -Status values are Delivered, Expanded, Failed, FilteredAsSpam, GettingStatus, Pending and Quarantined. When a result set is larger than one batch, run the query again with -EndDate set to the last row's Received value and -StartingRecipientAddress set to its RecipientAddress.

Step 5: Go further back with downloadable reports#

For ranges longer than 10 days, or when you need more detail, the admin center builds two CSV reports from archived trace data: the Enhanced summary report (adds direction, original client IP and connector) and the Extended report (full routing and event detail). Both need at least a sender, recipient or Message ID. Choose Next, confirm the title and notification address, select Prepare report, then download it from the Downloadable reports tab. Allow several hours, and expect the most recent 24 hours to be missing from the archive.

In PowerShell, the equivalent is a historical search, which covers messages up to 90 days old:

PowerShell
Start-HistoricalSearch -ReportTitle "Partner invoices" -ReportType MessageTraceDetail `
    -StartDate (Get-Date).AddDays(-30) -EndDate (Get-Date).AddDays(-12) `
    -SenderAddress billing@fabrikam.com -NotifyAddress admin@contoso.com

Get-HistoricalSearch | Format-Table ReportTitle, Status, Rows

Verify: what the results usually tell you#

  • No record at all: the message never reached Exchange Online. Recheck the address spelling, time range and time zone, confirm your MX record and connectors, then ask the sender's admin for their outbound logs.
  • Delivered but not visible: look at Junk Email, Inbox rules, Focused Inbox and any auto-delete or retention settings. Message trace can't see what happens after delivery.
  • Failed: the NDR code in the Fail event is your starting point.
  • Quarantined or Filtered as spam: decide whether it's a false positive, release it if appropriate and submit it to Microsoft for review.
  • Pending for hours: the receiving server is deferring. If retries eventually run out, the sender gets an NDR.

Tips & gotchas#

  • The admin center shows times in the time zone from your Exchange account settings, while PowerShell returns UTC. Mixing the two up is an easy way to search the wrong window.
  • For a message sent to more than 1,000 recipients, filter by -MessageTraceId to get complete results.
  • Prefer -SubjectFilterType StartsWith or EndsWith over Contains; Microsoft recommends them for performance.
  • Historical searches are capped at 250 per tenant in 24 hours, and cancelled ones still count.

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.

OE
Written by

Omer Eltayeb

Independent Microsoft Intune consultant 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, Microsoft Entra ID, Microsoft Defender and Exchange Online 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)