In my introduction to Exchange Server 2010 message tracking I wrote that PowerShell provides one of the most useful and powerful ways to search message tracking logs.
Although the message tracking log explorer is fine for simple searches on a single server, it doesn’t work so well when you want to do wildcard searches, search multiple servers at once, or export data for further analysis.
Message tracking log explorer
For those operations PowerShell is the way to go, and frankly once you’ve seen how powerful PowerShell is for message tracking log searches you’ll probably never use the explorer tool again.
Getting Started with Searching Message Tracking Logs Using PowerShell
Message tracking log searches are performed in the Exchange Management Shell by running the Get-MessageTrackingLog cmdlet. You can run this cmdlet with no parameters on any Edge Transport, Hub Transport or Mailbox server and it will return all of the log entries on that server.
[PS] C:\>Get-MessageTrackingLog
EventId Source Sender Recipients MessageSubject
------- ------ ------ ---------- --------------
RECEIVE SMTP Ivana.Ferrary@exchangeserverpro.net {Ana.Williams@exchangeserverpro.net} Luminary asep...
DELIVER STOREDRIVER John.Tilleray@exchangeserverpro.net {Lucy.Spratley@exchangeserverpro.net} Egress concor...
RECEIVE STOREDRIVER Ambrine.Berry@exchangeserverpro.net {Lorraine.Oza@exchangeserverpro.net} Brazen
DELIVER STOREDRIVER Ivana.Ferrary@exchangeserverpro.net {Ana.Williams@exchangeserverpro.net} Luminary asep...
RECEIVE SMTP Donna.A'Bear@exchangeserverpro.net {Marc.Itoje@exchangeserverpro.net} Garble expedi...
RECEIVE SMTP Priya.Smith@exchangeserverpro.net {Melanie.Thomas@exchangeserverpro.net} Enthral boorish
DELIVER STOREDRIVER Donna.A'Bear@exchangeserverpro.net {Marc.Itoje@exchangeserverpro.net} Garble expedi...
RECEIVE SMTP Jane.Martin@exchangeserverpro.net {Charlotte.Bonsey@exchangeserverpro.net} Palate causti...
DELIVER STOREDRIVER Ambrine.Berry@exchangeserverpro.net {Lorraine.Oza@exchangeserverpro.net} Brazen
RECEIVE SMTP Yvette.Willis@exchangeserverpro.net {Jan.Marway@exchangeserverpro.net} Malign edible
DELIVER STOREDRIVER Priya.Smith@exchangeserverpro.net {Melanie.Thomas@exchangeserverpro.net} Enthral boorish
RECEIVE STOREDRIVER Joy.Singh@exchangeserverpro.net {Mary.Friel@exchangeserverpro.net} Obfuscate
HAREDIRECT ROUTING Joy.Singh@exchangeserverpro.net {Mary.Friel@exchangeserverpro.net} Obfuscate
....
You can also search a remote server using the -Server parameter. This is useful when you are running the search from your own admin workstation or a separate management server.
[PS] C:\>Get-MessageTrackingLog -Server HO-EX2010-MB2
The Get-MessageTrackingLog cmdlet also accepts input from the pipeline. This is a very convenient way to perform searches on multiple servers at once. For example to search all Hub Transport servers at once:
[PS] C:\>Get-TransportServer | Get-MessageTrackingLog
Sometimes you may wish to search the transport servers only within a particular site. Because I might need to work with that list in a few different commands I’ll usually collect those into a variable first, for example all Hub Transport servers in the “HeadOffice” site:
[PS] C:\>$hubs = Get-ExchangeServer | Where {$_.Site -like "*HeadOffice" -and $_.IsHubTransportServer -eq $true}
I can then pipe that array of servers into the Get-MessageTrackingLog cmdlet.
[PS] C:\>$hubs | Get-MessageTrackingLog
Remember Default Resultsize of 1000
Often you will be running message tracking log searches that return a lot of results. However, by default the cmdlet will return only 1000 results.
Because of this you should try to get in to the habit of using the -Resultsize parameter to return unlimited results when running Get-MessageTrackingLog.
[PS] C:\>Get-TransportServer | Get-MessageTrackingLog -Resultsize unlimited
Run Long Queries Once by Collecting Results in a Variable
When you’re performing investigative searches of your message tracking logs, particularly across multiple servers, those queries can take a long time to return the results. If you then found you needed to adjust the query, for example to be more specific, or to format the results in a different way, you have to wait a long time for the query to run a second time as well.
So a good tip is to always collect your query results into a variable, particularly very broad queries that take a long time to run, so that you can pick apart the collected data without having to re-run the query.
For example, if I want to investigate reports of email problems sending to Alan Reid, I can run one broad query across all Hub Transport servers and collect the results in a variable I will call $msgs.
[PS] C:\>$msgs = Get-TransportServer | Get-MessageTrackingLog -Recipients "Alan.Reid@exchangeserverpro.net" -resultsize unlimited
I’ve now got thousands of records that I can begin to filter and dissect in different ways without having to re-run my query.
[PS] C:\>$msgs.count 13297
For example I can find the top 10 senders to Alan Reid within seconds, instead of re-running the entire Get-MessageTrackingLog search again.
[PS] C:\>$msgs | Group-Object -Property Sender | Select-Object name,count | sort count -desc | select -first 10 | ft -auto Name Count ---- ----- Andrea.Sharma@exchangeserverpro.net 110 Richard.Bennett@exchangeserverpro.net 108 Judy.Mollo@exchangeserverpro.net 104 Ferzana.King@exchangeserverpro.net 102 Debra.Lowe@exchangeserverpro.net 100 Nicola.Noad@exchangeserverpro.net 100 Diane.Hall@exchangeserverpro.net 96 Caroline.Ball@exchangeserverpro.net 96 Chris.Majumdar@exchangeserverpro.net 96 Hugh.Sharma@exchangeserverpro.net 96
According to Measure-Command the above command took 1.3 seconds to complete, whereas the re-running the full log search again would take 47.4 seconds. By collecting the results into a variable the first time all of the subsequent analysis of that data is able to be performed much faster.
Each Single Message is Multiple Log Entries
You’ll notice as you begin looking at message tracking logs that each individual email message generates multiple log entries. This is because each message goes through multiple events in the process of getting from sender to recipient, that the number of events will vary depending on how the message needs to be routed throughout your organization, as well as whether it is successfully delivered or not.
So a single email message may record a series of events such as:
EventId Source Sender Recipients MessageSubject
------- ------ ------ ---------- --------------
RECEIVE SMTP Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
DEFER STORE... Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
DUPLI... STORE... Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
RECEIVE STORE... Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
DELIVER STORE... Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
RESUBMIT DUMPSTER Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
TRANSFER STORE... Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
SEND SMTP Famida.Ghtoray@exchangeserverp... {Alan.Reid@exchangeserverpro.net} Prolix apropos embellish
Dealing with System.String[] in Exported Message Tracking Log Data
At some stage you will want to export some message tracking log data to CSV for further analysis in Excel. If you were to pipe the output above into the Export-CSV cmdlet you will notice that some of the fields, such as Recipients, will appear as System.String[] in the output file.
The Export-CSV System.String problem
To resolve this issue you need to first pipe your Get-MessageTrackingLog results into Select-Object and select the Recipients and RecipientStatus fields like this:
... | Select-Object eventid,sender,timestamp,@{Name="Recipients";Expression={$_.recipients}},@{Name="RecipientStatus";Expression={$_.recipientstatus}},messagesubject | Export-CSV filename.csv
This will give you the correct exported data.
Correct Recipients and RecipientStatus output
Examples of Message Tracking Log Searches
In the next part of this article series I’ll cover some specific examples of message tracking log searches using PowerShell.




Hi, nice article.
I’v been trying to search multiple HUB and CAS with the help of:
Get-TransportServer | Get-MessageTrackingLog
The problem I’m facing is that I can’t get the result presented in the right timeline. It searches one server at a time and present the findings the same way. So when looking at the searchresult it is not so easy to follow the message.
Piping into “… | Sort-Object timestamp” will put all the results in order.
Also, when I’ve identified a specific messageID I want to track I’ll filter my results down to just that messageID, eg
$msgs | where {$_.messageid -eq “themessageid”} | Sort-Object timestamp | Format-List
Hey Paul, when I am trying to search in all hubs at single shot, getting errora as exchange transport log search service at other hub servers are not running. Infact it is running normal. Sometimes, winrm service is not ableto access..
Whatmight be issue. Note my orgz is large with 100+ servers with 10 sites
Firewalls perhaps?
For the winrm issues, you’ve confirmed remoting is enabled?
$msgs | Group-Object -Property Sender | Select-Object name,count | sort count -desc | select -first 10 | ft -auto
Hello This command does not show anything, what is a reason of this? ( Exchange 2010)
Thanks
very nice article
Great article, going to send this around work so I don’t have to do so many searches!
The other handy thing to include would be to indicate what each event equates to- as you say each message will have multiple events, might be good to include a quick “mail flow by events”. So for example, you can get distribution group stats by looking at the EXPAND event.
Also, does -expandproperty not work for recipients?
Not sure about -Expandproperty yet. I’ve been tinkering with it but haven’t got it working in the scenarios I’ve tried so far.
Hello Paul,
Good article, thanks.
It would be better if we could get via powershell only the failed message logs which did not deliver to the internal users from external world.
Hello Paul.
Very nice article. I refer to this page often.
I was wondering if you had any idea or any reference links on exporting these logs to a syslog server using clog-sh?
Great article Paul. your site has helped me through Exchange migrations , starting with power shell and a host of other Exchange issues Ive had. Awesome resource, thanks a million !
Just had an urgent need to prove which messages were redirected over a set period, and this easy-to-use article got me straight there.
Thank you for a really useful article!
HI Paul, I have a little bit query, how we can track message on the basis of recipient basis.
exm:- how many users sending mails more than 100 recipient in a mail.
Regards.
Sukhdev
Hi all,
Do you guys know a powershell command to track a message from a specific sender? What I need to pull out is the: : InternalMessageId,TimeStamp and Message Size in MB
Any thought? I’m kind of new working on PS
Here’s some tips on searching message tracking logs by sender/recipient:
http://exchangeserverpro.com/searching-message-tracking-logs-by-sender-or-recipient-email-address
Hi Paul:
Your PS command ” … | Select-Object eventid,sender,timestamp,@{Name=”Recipients”;Expression={$_.recipients}},@{Name=”RecipientStatus”;Expression={$_.recipientstatus}},messagesubject | Export-CSV filename.csv ” is a great life saver. It gave me most of the data I am looking for when tracking the message logs.
I tried to add the following to get delivery status “@{Name=”DeliveryStatus”;Expression={$_.DeliveryStatus}}” with no external quotes offcourse. However, I am not able to get delivery status. Is there any trick to get delivery status to confirm if a message is delivered or failed to deliver to the intended recipients?
Hi,
Ive used this document a few times, very useful.
But what about finding emails of certain sizes. We have high limits internally & externally (100Mb), we are considering lowering them. But I wanted to report on say how many emails to/from/within the org were over a size of say 25Mb and 50Mb. That way I can understand the impact to the business.
Thanks,
Gareth
Message tracking logs record a TotalBytes value that could be used for this.
Or perhaps use Exchange Web Services to inspect actual mailboxes, though I don’t have any samples for that.
Great info Paul! I have a scenario that I’m trying to work out. I have a list of mailboxes that I need to find the total sent and received on a particular day. How would you import the list and for each look through the message tracking logs?
Thanks
Dawn