To trace a missing email in Exchange Online today, open the Exchange admin center at Mail flow > Message trace, select Start a trace, and filter by sender, recipient or Message ID over a range of 10 days or less to get instant results. In PowerShell, use Get-MessageTraceV2 and pipe the result to Get-MessageTraceDetailV2 for the event-by-event history; the legacy Get-MessageTrace cmdlets were deprecated in September 2025. Both tools search the last 90 days, 10 days per query.
Who this is for and what you will have
This guide is for Exchange Online administrators and help desk staff who answer "I never got that email" tickets, and for anyone whose scripts still call Get-MessageTrace. At the end you will have:
- A repeatable way to find a message in the new EAC message trace and read its events.
- PowerShell commands that work within the V2 limits, including retrieving more than 5,000 results.
- A clear idea of when to use a downloadable report, a historical search or the Microsoft Graph API.
- A list of common reasons a trace comes back empty or incomplete.
What changed in message trace
Microsoft rebuilt message trace and made the new version generally available in mid-2025. According to Microsoft 365 message center post MC1092458:
- The new experience replaces the legacy one in the EAC at Mail flow > Message trace.
- The new cmdlets are
Get-MessageTraceV2andGet-MessageTraceDetailV2. - The legacy EAC experience and the
Get-MessageTraceandGet-MessageTraceDetailcmdlets were deprecated starting September 1, 2025. - Message trace support in the Reporting Web Service was scheduled to begin deprecating on March 18, 2026, and users of that service were told to move to the new cmdlets. Since then Microsoft has also published a Microsoft Graph message trace API, described later in this guide, which is the other option for integrations.
The main differences you notice in scripts are summarized here:
| Area | Behavior in V2 |
|---|---|
| Search window | Last 90 days; 10 days of data per query |
| Default range | Last 48 hours if you don't specify dates |
| Results per query | 1,000 by default, up to 5,000 with -ResultSize |
| Paging | Not supported; -PageSize and -Page are gone |
| Throttling | 100 query requests per tenant in a rolling 5-minute window |
| Time stamps | Output is in UTC |
| Module | ExchangeOnlineManagement 3.7.0 or later |
Prerequisites
- Membership in the Organization Management role group in Exchange Online, or the Exchange Administrator role in Microsoft Entra ID. Microsoft recommends against using Global Administrator for this.
- The ExchangeOnlineManagement module, version 3.7.0 or later, for the V2 cmdlets.
- From the user: the sender address, recipient address, approximate send time and, ideally, the Message-ID header of the message (or of the NDR they received).
Check your module version before you start:
Get-Module ExchangeOnlineManagement -ListAvailable | Format-Table Name,Version
Update-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@contoso.comTrace a message in the Exchange admin center
Start the trace
- In the EAC at
https://admin.exchange.microsoft.com, go to Mail flow > Message trace. - Select Start a trace. The defaults search all senders and all recipients for the last two days.
- Fill in Senders and Recipients. You can type external addresses, use a single wildcard such as
*@fabrikam.com, or paste a list separated by semicolons, spaces or new lines. - Set the Time range. The Slider view saves a relative range when you save the query; Custom time range lets you choose a time zone and exact start and end times.
- Open Detailed search options if you need them:
- Subject filter with starts with, ends with or contains.
- Delivery status: All, Delivered, Expanded, Failed, Pending, Recalled, Quarantined, Filtered as spam or Getting status. Pending, Quarantined and Filtered as spam are only available for searches shorter than 10 days.
- Message ID, which must include the angle brackets, for example
<d9683b4c-127b-413a-ae2e-fa7dfb32c69d@contoso.com>. - Network Message ID, the value that persists across copies of the message created by bifurcation. You can read it from headers such as
X-MS-Exchange-Organization-Network-Message-Id. - Direction: All, Inbound or Outbound.
- Original client IP address.
- Choose a report type and select Search (or Next for downloadable reports).
The Message trace page also keeps Default queries, Custom queries your admins saved, and Autosaved queries with the last 10 queries you ran.
Choose the right report type
| Report type | When it's available | Maximum results | Delivery |
|---|---|---|---|
| Summary report | Time range of 10 days or less | 20,000 | Instant, in the browser |
| Enhanced summary report | Any range up to 90 days; needs a sender, recipient or Message ID filter | 100,000 | Downloadable CSV, can take hours |
| Extended report | Any range up to 90 days; needs a sender, recipient or Message ID filter | 1,000 | Downloadable CSV with routing and event detail |
If your range is even slightly longer than 10 days, the results are only available as a downloadable CSV prepared from archived data, and the last 24 hours of archived data typically aren't included. Downloadable reports appear on the Downloadable reports tab with the status Not started, In progress or Complete, and a notification goes to an address in one of your accepted domains. A CSV larger than 800 MB can't be opened in Excel or Notepad, so narrow the filters rather than widening the range.
The Original client IP address is only included in the Enhanced summary and Extended reports, and only for 10 days.
Read the result
The summary report lists Date, Sender, Recipient, Subject and Status, newest first. The first 250 rows load immediately and more load as you scroll, up to 10,000. A distribution group recipient appears first, followed by each member on its own line.
Select a row to open the details flyout. The Message events section is where the answer usually is:
| Event | Meaning |
|---|---|
| Receive | The service received the message |
| Send | The service sent the message onward, for example to an external server |
| Deliver | The message was delivered to a mailbox |
| Fail | Delivery failed |
| Defer | Delivery was postponed and might be retried |
| Expand | A distribution group was expanded |
| Transfer | Recipients were moved to a bifurcated copy |
| Resolved | The recipient was redirected to a new address based on a directory lookup |
| DLP rule | A data loss prevention rule matched |
The More information section shows the Message ID, message size, From IP (blank for outbound mail sent from Exchange Online) and To IP (blank for inbound mail). If a message shows as Quarantined, continue with the quarantine workflow in quarantine policies in Defender for Office 365.
Trace with Get-MessageTraceV2
Basic queries
Messages from one sender over two days:
Get-MessageTraceV2 -SenderAddress john@contoso.com -StartDate 10/09/2026 -EndDate 10/11/2026Dates use the short date format of the computer you run the command on; the examples here assume MM/dd/yyyy. To include a time, quote the value, for example "10/09/2026 5:00 PM". Remember that the output time stamps are in UTC.
A specific message by its Message ID, with the full event history:
Get-MessageTraceV2 -MessageId "<d9683b4c-127b-413a-ae2e-fa7dfb32c69d@contoso.com>" -StartDate 10/04/2026 -EndDate 10/11/2026 |
Get-MessageTraceDetailV2Only failed or quarantined messages to one recipient:
Get-MessageTraceV2 -RecipientAddress alina@contoso.com -Status Failed,Quarantined -StartDate 10/01/2026 -EndDate 10/11/2026Other filters include -FromIP, -ToIP, -Subject with -SubjectFilterType (Contains, StartsWith or EndsWith; Microsoft recommends the last two over Contains) and -MessageTraceId, the network message ID GUID. Microsoft says MessageTraceId is required to get complete results for a message sent to more than 1,000 recipients.
Detail queries
Get-MessageTraceDetailV2 requires -MessageTraceId and -RecipientAddress. You can supply them by piping from Get-MessageTraceV2, as above, or directly:
Get-MessageTraceDetailV2 -MessageTraceId ae5c1219-4c90-41bf-fef5-08d837917e7c -RecipientAddress robert@contoso.comUse -Event to filter by events such as RECEIVE, SEND, FAIL, DELIVER, EXPAND, TRANSFER or DEFER.
Retrieving more than 5,000 results
V2 has no paging. Results are ordered by Received (newest first) and then by RecipientAddress. To get the next batch, run the same query with EndDate set to the Received value of the last row and StartingRecipientAddress set to its recipient address. This loop follows Microsoft's documented pattern:
$params = @{
SenderAddress = 'noreply@contoso.com'
StartDate = (Get-Date).AddDays(-7)
EndDate = Get-Date
ResultSize = 5000
}
$all = @()
do {
$batch = @(Get-MessageTraceV2 @params)
$all += $batch
if ($batch.Count -eq $params.ResultSize) {
$params.EndDate = $batch[-1].Received.ToString('O')
$params.StartingRecipientAddress = $batch[-1].RecipientAddress
Start-Sleep -Seconds 5
}
} while ($batch.Count -eq $params.ResultSize)
$all | Export-Csv .\trace.csv -NoTypeInformationKeep the date range itself at 10 days or less, and remember that every iteration counts against the 100-requests-per-5-minutes tenant limit. Shared automation, monitoring tools and other admins all draw from the same quota.
Other ways to get message trace data
Historical search
For a CSV of up to 100,000 rows from the last 90 days, without staying within the 10-day window, use a historical search. You must specify at least one of MessageID, RecipientAddress or SenderAddress:
Start-HistoricalSearch -ReportTitle "Fabrikam invoices" -StartDate 07/15/2026 -EndDate 10/10/2026 `
-ReportType MessageTrace -SenderAddress billing@fabrikam.com -NotifyAddress admin@contoso.comHistorical searches cover messages between about 1 to 4 hours and 90 days old, and you can submit up to 250 in 24 hours (cancelled searches count). If you search for a distribution group as the recipient, not all messages might be returned; search for the individual recipient instead. When the search completes, a notification goes to the NotifyAddress mailbox, which must be in one of your accepted domains.
Microsoft Graph message trace API
For applications and SIEM integrations, Microsoft Graph exposes message trace at GET /admin/exchange/tracing/messageTraces, with the ExchangeMessageTrace.Read.All permission. It follows the same rules as the cmdlets: 90 days, 10 days per query, 48 hours by default, $top from 1 to 5,000 and 100 requests per 5 minutes. Unlike the cmdlet, it does support paging through @odata.nextLink. Before the first call you must create a service principal in your tenant for the application ID 8bd644d1-64a1-4d4b-ae52-2e0cbf64e373:
Connect-MgGraph -Scopes "Application.ReadWrite.All"
New-MgServicePrincipal -BodyParameter @{ appId = "8bd644d1-64a1-4d4b-ae52-2e0cbf64e373" }Provisioning can take several hours, and requests fail with 401 (Unauthorized) until it completes. At the time of writing the v1.0 endpoint is listed for the global service only, not the US Government or China clouds.
Troubleshooting
An old script still calls the legacy cmdlets. Get-MessageTrace and Get-MessageTraceDetail are deprecated. Replace them with the V2 cmdlets, replace -PageSize with -ResultSize, and replace page loops with the StartingRecipientAddress pattern above.
The trace is empty for a message that was just sent. Recently received messages show Getting status until more data is available, and Microsoft notes a five to ten minute delay between actual and reported status. Wait and search again.
The time looks wrong or the message seems missing. PowerShell output is in UTC, while the EAC uses the time zone from your Exchange account settings. Widen the range by a few hours on each side.
A Message ID search finds nothing. Include the full value with the angle brackets and enclose it in quotation marks. Message IDs created by other mail systems can use different formats.
The query fails because the date range is too long. Each query can cover only 10 days. Split the range, or use a downloadable report or Start-HistoricalSearch.
Graph returns "Your recent queries have surpassed the permitted limit, please try again later." You exceeded 100 requests in 5 minutes. Add a delay between calls and narrow the filters so fewer requests are needed.
The message was rejected with a 5.4.1 NDR. The recipient address isn't in your directory; see fix 550 5.4.1 Recipient address rejected.
Checklist
- ExchangeOnlineManagement 3.7.0 or later installed on every admin workstation and automation host.
- Scripts migrated from
Get-MessageTracetoGet-MessageTraceV2and from-PageSizeto-ResultSize. - Queries kept to 10 days and to as narrow a filter as possible.
- Large exports use the
EndDateplusStartingRecipientAddressloop and stay under 100 requests per 5 minutes. - Help desk knows how to ask users for the Message-ID header.
- Integrations that used the Reporting Web Service moved to the V2 cmdlets or to the Graph message trace API, with the service principal provisioned.
References
- Message trace in the new EAC in Exchange Online
- Get-MessageTraceV2
- Get-MessageTraceDetailV2
- Start-HistoricalSearch
- Graph-based message trace API onboarding guide
- List messageTraces (Microsoft Graph v1.0)
- Announcing General Availability of the New Message Trace in Exchange Online
- MC1092458 archive: New Message Trace GA and legacy Message Trace retirement