Searching Exchange Server 2010 Message Tracking Logs with PowerShell

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 exporer
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
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 Recipient and RecipientStatus output
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.

Comments

  1. Patrik says

    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.

    • says

      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

      • Nani says

        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

    • vakhtang says

      $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)

  2. says

    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?

  3. says

    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.

  4. says

    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?

  5. Ruan says

    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 !

  6. Martin says

    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!

  7. says

    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

  8. josh says

    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

  9. EmaTek says

    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?

  10. Gareth says

    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

    • says

      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.

  11. Dawn says

    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

  12. Chris says

    Hey guys, have you ever had this scenario? User opens a ticket complaining that her attachment is missing. The unix guys say (and show) that they delivered the attachment with the message in their logs. Now management is asking in the Message Logs in Exchange show that the attachment was delivered to the MAILSTORE. I’ve looked around but I don’t think the MessageLogs show that.
    — Any hints or successes in this area???

  13. Anjali says

    Hi Paul,

    Great Article buddy

    However i would like to know is there any way to get the count of mails which are holding the attachments in HUB Server through GUI/Powershell

  14. Atul says

    Dear Paul,

    can you please help me what permission we should have to run “Tracking Log Explorer” option in exchange 2010 Sp2 Rollup 6.

    Regards,
    Atul

  15. Mason says

    In our environment we have a new Exchange 2013 envrionment setup but all forwarding is still going through the old Exchange 2010 environment. I’m looking for a way to determine what users are still only using the old Exchange 2010 system (i.e. a way to parse traffic to not include the forwarded traffic). Do you know of an easy way to do this via Powershell?
    Thanks in advance!
    Mason

      • Mason says

        Here’s the scenario. We have our old domain running Exchange 2010, we’ve since migrated all of our users to the new domain, running Exchange 2013. On the old system we have SMTP forwarding setup to forward mail to the new system. On the new system we have transport rules setup to check and see if mail has been delivered to the old address, if not then it forwards the email. This has worked out well for our relatively small 500+ user environment but now I’m stuck with the task of trying to determine which users still utilizes the old system.

        I followed your other article (http://exchangeserverpro.com/exchange-2010-report-top-sender-ips-log-parser/), which was very informative and helpful, however the IPs returned are only for load balancers or other Exchange Servers and not actual end users.

        I have a feeling there is a way to do it via IIS logs but any guidance you can provide is greatly appreciated :)

      • Mason says

        I should also note the new system is an entirely new Windows 2012 domain as well. So when I said users were migrated thats a bit inaccurate, they were essentially recreated I suppose.

      • Mason says

        Actually, I think I figured it out. If you parse the IIS logs from the old email server for “SendAs=SMTP” or “ActAs” it seems to show what I’m looking for. If you have any other tips I’ll take them but thanks for taking a look regardless!

        • says

          No other suggestions right now. I’m still trying to visualise your scenario properly. Sounds a bit difficult, but I’m sure you had good reasons to do a whole new domain.

          If all your users are migrated to the new server I guess there is no reason why any mail should be flowing through the old server now… unless you’ve still got MX records or other servers/apps still using that server for SMTP. In which case that log parser tip you already found is how I tend to investigate that.

  16. Tom says

    Hi Paul

    I have something similar to Mason.

    I have Exchange 2003 and Exchange 2010 (CAS/HT Test box) and another Exchange 2010 (Live CAS/HT).

    The ex2010 (Test) has smtp Relay has two IPs to it. The secondary ip i have moved to the live environment on a new smtp relay. However i see exchange 2003 server is still using this old smtp relay however i cannot see anything on the ex2003 to be using the old smtp relay on the other ip. Is this something to do with the routing group connector?

  17. Sime says

    Hi

    I have migrated from Exchange 2007 to Exchange 2013 and I have removed Exchange 2007. How can I open message tracking logs from Exchange 2007 I have backup from Exchange 2007 hub servers?

    S

    • says

      A message tracking log file is basically just a text file in CSV format. You can open it with Notepad or import it as a CSV into Excel. You can also search it with tools like Log Parser, Findstr, or PowerShell’s Select-String. Or really any text parsing utility.

  18. Stephanie Burnside says

    Hi Paul.

    Thanks. Lots of good information here. Would you happen to know how I can pull the message tracking logs (recipient and timestamp only) for all mailboxes in a specific OU?

    I’ve tried various combinations of commands, but no luck, so any help you can provide would be most appreciated.

    Thanks again.

    • says

      The Get-MessageTracking cmdlet has no way of filtering to a particular OU of mailbox users. Remember, it is basically querying text/log files. If you wanted to query the message tracking logs for an OU of users you’d need to write a script that pulls *all* of the email addresses from those users then runs Get-MessageTracking queries to retrieve the results.

      So the short answer is, yes it’s possible but requires some custom scripting.

  19. Stephanie Burnside says

    I am using the following to gather the smtp addresses of the mailboxes in the OU:
    get-mailbox -resultsize unlimited -OrganizationalUnit “*Sharepoint*”|select-object primarysmtpaddress > MailboxesInOU.csv

    I am then trying to pipe this into the Get-MessageTracking cmdlet using the following, but it is pulling the information from all of the mailboxes, not just those in the OU. I am fairly new to scripting. Is there something fairly simple that I am missing?
    Import-csv MailboxesInOU.csv | foreach {get-messagetrackinglog -recipient $_.primarysmtpaddress -resultsize unlimited |select-object recipients,timestamp |sort timestamp –descending} > OUTrackLogs.csv

  20. Chris says

    Hey Paul:

    Nice site. Im looking for a way to do the following:

    Get a list of all DL’s with a particular sub-domain. We are corp.com and I only need av.corp.com

    The managed by for each one

    Recent activity (message received)

    Any help will be appreciated!

    Thanks, Chris

Leave a Reply

Your email address will not be published. Required fields are marked *