Tracing Emails in the Cloud
Ten years ago, Paul Cunningham described how to search Exchange Server message tracking logs with PowerShell to find details of emails logged as they pass through the transport service. That article focuses on the Get-MessageTrackingLog cmdlet that doesn’t exist in Exchange Online. A different technique is needed to run Exchange Online message traces and find messages in the cloud where the Get-MessageTrace cmdlet does the heavy lifting. And while you can run a message trace through the Exchange admin center GUI, running traces through PowerShell allows you to pipe the results to other cmdlets, create reports, and so on (here’s an example of using message trace to create a report for management about external email).
One big thing to remember is that Get-MessageTrace can return information about messages for up to ten days after they’re sent. After that, the Start-HistoricalSearch cmdlet must be used. Another point is that it takes a couple of minutes after a message is sent before Exchange Online can trace its progress.
Paul’s article used an email about a payroll report sent to three recipients as its test case. Figure 1 shows my example:
![A message that we want to trace
Exchange Online message trace](https://s40823.pcdn.co/wp-content/uploads/2022/06/Payroll-Message-1024x736.jpg)
Exchange Online Message Trace by Sender Email Address
The results returned by any search depend on the criteria used to find items. To begin, we can find the message sent by the user by including their primary SMTP address in the Sender parameter.
Get-MessageTrace -SenderAddress Terry.Hegarty@office365itpros.com -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) Received Sender Address Recipient Address Subject -------- -------------- ----------------- ------- 11/06/2022 10:24:22 Terry.Hegarty@office365itpros.com james.ryan@office365itpros.com Attention: May Payroll Details 11/06/2022 10:24:22 Terry.Hegarty@office365itpros.com chris.bishop@office365itpros.com Attention: May Payroll Details 11/06/2022 10:24:22 Terry.Hegarty@office365itpros.com brian.weakliam@office365itpros.com Attention: May Payroll Details
This information doesn’t give the same insight as the Get-MessageTrackingLog cmdlet delivers in terms of how the Exchange transport system processed the message. You can add the Status parameter to the search to return messages with a certain processing status. For instance, this command only returns messages that have been successfully delivered. Other status values include Failed, Pending, and Quarantined.
Get-MessageTrace -SenderAddress Terry.Hegarty@office365itpros.com -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) -Status Delivered
To see more detail about the steps in processing, we need the message trace identifier. Get-MessageTrace doesn’t show the message trace identifier unless you ask for it:
Get-MessageTrace -SenderAddress Terry.Hegarty@office365itpros.com -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) | Format-table MessageTraceId, SUbject, RecipientAddress MessageTraceId Subject RecipientAddress -------------- ------- ---------------- 1b312cde-f274-409e-7350-08da4b948d74 Attention: May Payroll Details james.ryan@office365itpros.com 1b312cde-f274-409e-7350-08da4b948d74 Attention: May Payroll Details chris.bishop@office365itpros.com 1b312cde-f274-409e-7350-08da4b948d74 Attention: May Payroll Details brian.weakliam@office365itpros.com
Now we can run Get-MessageTraceDetail to discover what happened to a message.
Get-MessageTraceDetail -MessageTraceId 1b312cde-f274-409e-7350-08da4b948d74 -RecipientAddress James.Ryan@office365itpros.com Date Event Detail ---- ----- ------ 11/06/2022 10:24:23 Receive Message received by: PAXPR04MB8621.eurprd04.prod.outlook.com 11/06/2022 10:24:23 Submit The message was submitted. 11/06/2022 10:24:27 Deliver The message was successfully delivered.
Tracing Messages by Recipient Email Address
Searching by recipient works no matter what kind of recipient (TO, CC, or BCC) a message recipient is. Here we search for Chris Bishop (a CC address), and the search succeeds:
Get-MessageTrace -RecipientAddress Chris.Bishop@office365itpros.com -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) | Format-List Message Trace ID : 1b312cde-f274-409e-7350-08da4b948d74 Message ID : <DB6PR04MB3158B4FBF516094B399D23C0B4A99@DB6PR04MB3158.eurprd04.prod.outlook.com> Received : 11/06/2022 10:24:22 Sender Address : Terry.Hegarty@office365itpros.com Recipient Address : chris.bishop@office365itpros.com From IP : 2a01:cb1d:5b0:1500:fd9f:cfb5:a3e6:e6cb To IP : Subject : Attention: May Payroll Details Status : Delivered Size : 57013
You can specify multiple recipient SMTP addresses by separating the recipient addresses with a comma. When you do this the condition is an “or” not an “and”. In other words, any message sent to any one of the recipients is included in the results. In this case, we look for messages sent to two mailboxes, one of which is a recipient on the payroll email. The message trace finds two messages:
Get-MessageTrace -RecipientAddress Chris.Bishop@office365itpros.com, Ben.Owens@office365itpros.com -StartDate (Get-Date).AddHours(-1) -EndDate (Get-Date) | fl Message Trace ID : 92827190-e015-4faf-586f-08da4b972420 Message ID : <DB6PR04MB315846EE7664C474A7435554B4A99@DB6PR04MB3158.eurprd04.prod.outlook.com> Received : 11/06/2022 10:42:54 Sender Address : Terry.Hegarty@office365itpros.com Recipient Address : ben.owens@office365itpros.com From IP : 2a01:cb1d:5b0:1500:fd9f:cfb5:a3e6:e6cb To IP : Subject : Business Development Meeting Status : Delivered Size : 12933 Message Trace ID : 1b312cde-f274-409e-7350-08da4b948d74 Message ID : <DB6PR04MB3158B4FBF516094B399D23C0B4A99@DB6PR04MB3158.eurprd04.prod.outlook.com> Received : 11/06/2022 10:24:22 Sender Address : Terry.Hegarty@office365itpros.com Recipient Address : chris.bishop@office365itpros.com From IP : 2a01:cb1d:5b0:1500:fd9f:cfb5:a3e6:e6cb To IP : Subject : Attention: May Payroll Details Status : Delivered Size : 57013
Message Tracing for Wildcard Values or Partial Matches
The Get-MessageTrackingLog cmdlet doesn’t support wildcard searches against the SenderAddress and RecipientAddress parameters. However, Get-MessageTrace can run searches like this (the example finds any message sent to a microsoft.com address in the defined period):
Get-MessageTrace -RecipientAddress *@microsoft.com -StartDate 3-June-2022 -EndDate 10-June-2022 -Status Delivered
You can also run a wildcard search against sender addresses. For instance, here’s how to find all the messages delivered to my tenant from quest.com in the last week. The results cover all messages sent from quest.com addresses to any mail-enabled recipient in the tenant:
Get-MessageTrace -SenderAddress *@quest.com -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) -Status Delivered | ft senderaddress, recipientaddress, subject, status
Message Trace by Subject
Unfortunately, the Get-MessageTrace cmdlet doesn’t include a Subject parameter to allow a search for a specific message with a matching subject. This deficit is easily overcome by piping the results of the search to the Where-Object cmdlet. For instance, here’s how to take the set of messages received from Quest.com and match only those containing the string “Zero-day” in the message subject:
Get-MessageTrace -SenderAddress *@quest.com -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) -Status Delivered | ? {$_.Subject -like "*Zero-day*"}
Summary
Message tracing is different in the cloud. On-premises servers generally have more control over how long logs remain available whereas cloud systems tend to keep information online for more limited periods. The use of Get-MessageTrace cmdlet differs from the Get-MessageTrackingLog cmdlet, but it doesn’t take much to become fluent in its capabilities.
all of this does not work in case of using delivery to big audiense >30000 recipients.
The Real Person!
The Real Person!
I suspect that running a message trace for > 30,000 recipients is likely to consume a lot of resources. If the cmdlet can’t handle this amount of recipients, you should file a support incident with Microsoft so that an engineer can investigate and update the cmdlet if necessary.
Amazing!!
Thank’s for your time. I really enjoyed your information.
I would like to know if the received message has been read or not.
It is possible?
Once again, thanks for your help.
The Real Person!
The Real Person!
Not unless the recipient has an Office 365 E5 or advanced audit license. If this is true, the MailItemsAccessed audit event might tell you. https://office365itpros.com/2020/03/06/mailitemsaccessed-audit-events/
Sir,
I want full day summary report via email in my admin email address in table format. For all the emails flow in my organization.
The Real Person!
The Real Person!
I’m sure that you do want a summary report. Have you tried to generate one with PowerShell?
Is there a way to determine what message traces have been run tenant wide and by whom they were run?
It doesn’t look as if either the mail admin audit log or unified audit log (Search-AdminAuditLog and Search-UnifiedAuditLog) capture audit events for message tracing. At least, I did some traces and looked for audit records and couldn’t find anything.
Great article. Thanks for the detailed examples, they’ve enabled me to start improving observability into our fairly recent migration to Exchange Online. It does bring a question though… With on premises, I was able to pull specific metrics other than Sent and Received; t be specific, Deferred, Bad Mail, Dropped and Queued. I’m unable to find a way to collect similar message traffic metrics from Exchange Online. The powershell commands I’ve been using for years simply don’t apply/exist in Exchange Online. Suggestions?
The Real Person!
The Real Person!
I don’t believe that these statistics are available in Exchange Online.
Thanks Tony. I’ll keep looking for a different way and advise if I find something viable.
Hi
I appreciate your work, your articles and all the very helpfull information you give to the community.
Many thanks – Bueschu