Home » Exchange Server » Searching Exchange Server 2010 Message Tracking Logs with PowerShell

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.

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.

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:

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:

I can then pipe that array of servers into the Get-MessageTrackingLog cmdlet.

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.

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.

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.

For example I can find the top 10 senders to Alan Reid within seconds, instead of re-running the entire Get-MessageTrackingLog search again.

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:

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:

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.

Paul is a Microsoft MVP for Office Servers and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul is a co-author of Office 365 for IT Pros and several other books, and is also a Pluralsight author.
Category: Exchange Server


  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.

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

    • Advait says:

      Hello Paul,

      Need some help related to spam.

      There was a spam attack in our organization.

      How can we prevent that from happening.

      What permissions can be given to the security team to get an alert for malicious or suspicious mails?

      Is creating moderator a feasible option?

      • Advait says:

        On EOP what permissions can be given?

        Is there a way to terminate the session if we are suspecting an malicious attack?

  2. John Snedon 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. Kottees 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. Anthony 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. Sukhdev 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.


  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:


    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.


  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?


  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.


  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 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://practical365.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!

        • 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:


    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?


    • 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.

    • 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

  21. Dhananjay says:

    Thanks a bunch Paul,
    I was absolutely clueless why recipient column was not getting exported properly, piping select-object cmdlet saved my soul.


  22. Edinson says:

    Hi, my question is if I restore the tracking logs, I can read with some tool?

    I understand that I can not read the Tracking Log Explorer, or I can do some trick to read?

  23. Kamal says:


    I have tracked some messages using Get-TransportServer | Get-MessageTrackingLog to search for messages sent to outside recipients that appear to be spam. There are multiple messages and each from different sender.
    I noticed under Reference, there is a weird email address. Please help understand where the messages are sent from and how.

    Thank you

    RunspaceId : b06e59c4-4f67-46e8-8233-b1097f3e88ad
    Timestamp : 6/24/2015 10:30:51 AM
    ClientIp :
    ClientHostname :
    ServerIp : ::1
    ServerHostname : EX-CAS1
    SourceContext : 594431127398121473
    ConnectorId :
    Source : MAILBOXRULE
    EventId : RECEIVE
    InternalMessageId : 5011620
    MessageId :
    Recipients : {sunriselive@elfarorestaurante.com}
    RecipientStatus : {To}
    TotalBytes : 9971
    RecipientCount : 1
    RelatedRecipientAddress :
    Reference : {}
    MessageSubject : Automatic reply: stop spamming me
    Sender : peckh@mydomain.org
    ReturnPath :
    MessageInfo : 03I:
    MessageLatency :
    MessageLatencyType : None
    EventData :

  24. Kamal says:

    Nevermind my last reply. The message itself is a spam. I searched inbound messages in Barracuda SPAM filter with that subject and discovered the senders to block.

  25. antar says:

    thanks guys for all this work
    Can someone help me to find a solution (pshell, vbs…) that is able to count the number of smime message in exchange 2010 tracking logs
    thanks a lot

  26. Jake says:

    Hi Paul,

    First off, your site has saved me many times and I am a frequent visitor.

    I’m looking for a way to determine if secondary smtp addresses that are associated to DL’s are being used or not. I have run this script:

    Get-MessageTrackingLog -Start 1/1/2015 -EventId Expand | group-object RelatedRecipientAddress | ft Name,Count -Autosize

    and it returns the PrimarySmtpAddress of the Distribution Group. Is there a way to get it to return the actual address the message was sent too?

    I am trying to determine which aliases I can retire.

    Thank You,


    • Not reliably, because once the email gets into the pipeline all the log entries will start showing the primary SMTP address. I think one of the very early events might show the alias used, but I wouldn’t count on it.

      If you don’t want an address being used any more, remove it and make the emails bounce.

  27. Tarek says:

    why the ” client IP” in message tracking field is always empty – this is the most important data “needed” when tracking an incident?!!! – please help!

  28. Ryan B says:

    Is there a way to run these searches against logs that have been moved to another location? I’m a new admin, and my manager wants me to increase message logging from the default 30 days to 365 . This will require space which we do not have locally. I’d like to set the logging for 6 months, then make a script to just move current logs to another location on the network. But I’m not sure how to search them once they’ve been moved. I appreciate your help!

  29. Manoj says:

    Thank you for this awesome article Paul. Have been following your posts and powershell scripts. Thank you for making our admin jobs a lot easier.

  30. kbar44 says:

    very good article. I have problem with count send messages. This is my part of script
    $msg = Get-MessageTrackingLog -server myserver -resultsize unlimited -eventId Send -Sender $_.emailaddress -Start 9/1/2016 -End 9/30/2016 | Where-Object {$_.recipients -like $rekord}
    I want count only send messages. When $msg has only one entry (one e-mail was sent) $msg.count don’t show anything. When $msg has more than one entries it work fine. How to count it?

  31. Romário Brito says:

    how do I find out who it was that sent an attachment to another user?
    I need to search in all of the user’s outbox, looking for that attachment.
    Can you help me ?

  32. James says:


    Thanks for a great article, and glad you are still active on it. I am really hoping you could help with this. Occasionally a manager/employee will send an email to a lot of people (1,000s) (either on accident or purpose) and we have to track who they sent to and then pull the emails. When tracking, we normally have to pull the list of who they sent it to and then use Word/Excel to manipulate the file to get each address on a single line to be used in a pull script. Eventually, we would like to script it to where the results are stored in a variable and then sent to a pull command automatically.

    (As a bonus, anyway to remove duplicate email addresses? – Currently we use Excel to do this).

    Is there a way to get a single address per line? Here is what we have been using (with the help of this article) – but as you can see it returns multiple addresses per line.

    Get-ExchangeServer | where {$_.isHubTransportServer -eq $true} | get-messagetrackinglog -start “11/11/2016 5:15AM” -End “11/11/2016 8:10 AM” -sender “Tim.doe@company.com” -MessageSubject “Payroll for company” -EventID “Deliver” -ResultSize Unlimited | Select-Object @{Name=”Recipients”;Expression={$_.recipients}} | Export-CSV filename.csv

    Here is results…
    “John.doe@company.com Jill.doe@company.com Lily.doe@company.com Nick.doe@company.com Nin.doe@company.com Apple.doe@company.com Billy.doe@company.com Alfred.doe@company.com Sally.doe@compnay.com
    “Hank.doe@company.com Cathy.doe@company.com Ray.doe@company.com Sam.doe@company.com Henry.doe@company.com Rose.doe@company.com
    “Rich.doe@company.com Nate.doe@company.com Nancy.doe@company.com Sid.doe@company.com

    • You would just need to write some extra code to handle $_.Recipients and split up multi-value results into unique email addresses.

      I’d also recommend you start writing a script, rather than try to jam everything into a one-liner.

  33. James says:

    Hi Paul,

    I’m trying to build a matrix each day of senders and recipients at my company, for analysis by a visiting professor for their research. She wants the following matrix:
    ___________ Recipients ->
    ___________ a@ab.c | b@ab.c | c@ab.c …
    V Sender
    ie every email address and the number of times it sent an email to every other email address!

    I’m pretty sure the data is contained in a file I have generated using this command:
    Get-TransportServer | Get-MessageTrackingLog -ResultSize Unlimited -Start “12/19/2016 12:00:00 AM” -End “12/20/2016 11:59:00 PM” | select sender, {$_.recipients}, recipientcount | Out-File “C:tempEmail_DB_Query.txt”

    Except that it is 1.5Gb and I can’t do anything with it.

    I am wondering if there is a way you know of, or a resource you can point me to, to help me write conditional code into the Powershell script that will just build the matrix with a counter for each sender and each recipient entry.

    Something that output:

    a@ab.c c@ab.c[2]
    b@ab.c a@ab.c[3],c@ab.c[1]

    I am further inhibited by not being allowed direct access to the exchange server, and I am also trying to do this at a company in Vietnam.

    It’s sort of like assembling a model ship in a bottle, in a foreign language! Any help or guidance would be much appreciated!

Leave a Reply

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