- Possible uses for message tracking logs
- Message tracking logs location and structure
- Configure message tracking
- What is in the message tracking logs
- Using the Get-MessageTrackingLog cmdlet
Message tracking logs are a valuable source of information for any Exchange admin. While Office 365 has its message tracing, which works just fine, on-premises Exchange stores much more data in the logs, which can serve many purposes.
Possible uses for message tracking logs
Good old message tracking logs may serve many different purposes:
- Solving delivery issues – If you know what you look for, message tracking logs can tell you why a message was not delivered, if its delivery was delayed and more (see what is in the message tracking logs)
- Statistics – Message tracking logs keep traces of every single message that went through your servers. There is quite an easy way to get some data for analysis – how many messages were processed, or who sent most messages in the company.
- Forensics – Say someone deletes an email and you did not have an email backup. What is worse, the email contained confidential information and was sent to your competitive company. That is where message tracking logs can save you by providing some valuable information on emails.
- Litigation – Similar to the above situation. Message tracking logs can and are often used when evidence is required for litigation purposes.
- Testing transport rules – Especially useful when you have configured multiple transport rules in your organization. Whenever a transport rule is applied, it leaves a trace, and you can use the Get-MessageTrackingLog to see when a transport rule or a DLP policy was triggered.
Message tracking logs location and structure
What are message tracking logs? Message tracking logs are simple CSV files (with a LOG extension) stored on your Exchange server. The default path to their physical location is %ExchangeInstallPath%TransportRoles\Logs\MessageTracking. The logs have a set naming convention. Mind that although you can change file names in logs, doing so will prevent you from searching them using Get-MessageTrackingLog cmdlet. What is more, files with changed names will not be counted towards the folder size limit. This may lead to exceeding the limits you have configured.
To manage space and amount of data stored on servers, Exchange employs circular logging. In other words, the oldest files are overwritten whenever a folder exceeds its maximum size, or a log file reaches its maximum age. If you stick to the default settings, the max age for a log file is 30 days, and the maximum size for a single file is 10 MB. By default, all message tracking logs in the default directory cannot exceed 1 GB. You can change all those limits using PowerShell (See configure message tracking for details)
Each day, a new message tracking log file is created. The naming convention is:
MSGTRKServiceyyyymmdd-nnnn.log where:
- Service depends on which service created a log. MSGTRK points towards logs created by the Transport service; additional letters specify which other services generated the log. MA stands for the Message Approval, MD for the Mailbox Transport Delivery service, MS for the Mailbox Transport Submission service.
- yyyymmdd specifies the date when the message log was created.
- nnnn is the number for the log file. Whenever a log file reaches its maximum size limit, a next copy will be created. The value is incremental, and every day it starts from (quite logically) 1.
I have mentioned some default values. As you might suspect, those values can be easily changed.
Configure message tracking
Before you start changing the default values of message tracking logs, make sure you know what you are doing. Message tracking logs can become quite cumbersome, size-wise. What is more, if you decide to collect data for an indefinite period, each large-scale search in the message tracking logs will take a considerable amount of time. Especially if you do not limit your search criteria. If you plan to collect information on your mail flow for an indefinite period, consider exporting message tracking logs contents to files. Then, you can store data on all emails, excluding those pointing to, for example, Health Mailboxes.
You can configure message tracking logs using the Set-TransportService cmdlet. Using this cmdlet, you can:
- Enable or disable message tracking,
- Change the location for storing message tracking logs,
- Modify the size and age limits for message tracking logs
- And enable or disable subject logging. A word of explanation: by default, message tracking logs do not store any content of emails, except for the subject line. While having the subject line in the logs greatly improves the tracking experience, some organizations require disabling this feature for security or privacy reasons.
Here is an example which changes all parameters at once:
Set-TransportService Mailbox_Server -MessageTrackingLogEnabled $true -MessageTrackingLogPath “M:\logs” -MessageTrackingLogMaxFileSize 30MB -MessageTrackingLogMaxDirectorySize 2.5GB -MessageTrackingLogMaxAge 365.00:00:00
The cmdlet above turns on message tracking for Mailbox_Server and sets the log storage to M:\logs. Size limit for a single log file is changed to 30 MB. It is mostly a cosmetic change, which controls the number of log files – the greater the limit, the less csv are created every day. The max directory size (before the oldest files are overwritten) is set to 2.5GB, and the log files are kept for 365 days. Setting the –MessageTrackingLogMaxAge to 00:00:00 will let you keep message tracking logs for an indefinite period. Or at least before the directory size is reached. But who needs to save space in Exchange, right?
What is in the message tracking logs
There are a few things you need to know about how message tracking logs store their entries.
- Each message usually generates more than a single entry in the message tracking log.
- Headers in the logs are not the same as their corresponding PowerShell attributes. For example, Event-id in the log files is EventId in PowerShell. Recipient-address in logs equals recipients in PowerShell. When you are in doubt on how to search using a particular attribute, use
Get-MessageTrackingLog –ResultSize 1 | FL * or Get-MessageTrackingLog | Get-Member
. Those cmdlets will give you a full list of attributes. - Some fields are often empty in the message tracking logs. Some might not include information which you may find important or relevant.
The most important fields in message tracking logs
- Sender, Recipient, MessageSubject – pretty self-explanatory, shows who sent a message to whom and what was the subject
- TotalBytes – shows the size of a message
- Timestamp – gives info on when the event took place
- EventID – one of the most important fields in message tracking logs. It is the primary source of information on what happened to the message. The most common values are Receive, Send, Submit, and Fail (This Microsoft documentation describes all message event types.)
- MessageInfo and RecipientStatus give the detailed information on what has happened to the message.
- MessageLatency shows you how much time the server needed to process the email.
The most important part is how to use PowerShell to get the right data from the logs.
Using the Get-MessageTrackingLog cmdlet
Get-MessageTrackingLog lets you search through all the message tracking logs. If you use the cmdlet without any additional attributes, it will return up to 1000 entries, most of which will probably be connected to the Health Mailboxes activity. If you want to include more than 1000 entries with a single Get-MessageTrackingLog cmdlet, add the -ResultSize unlimited attribute. Still, I am quite sure you do not plan to use the cmdlet to monitor Health Mailboxes activity. The right filtering is the key to a success. Below, I present a few techniques which you can use to filter the results.
How to get general information on mail flow in Exchange Server
If you are aiming at getting a very general idea of the recent mail flow in your organization, use the syntax described below:
Get-MessageTrackingLog -Start (Get-Date).AddDays(-14) -ResultSize Unlimited | Where -Property Recipients -NotLike "*HealthMailbox*" | ConvertTo-Html > "C:\mtl.html"
The cmdlet above goes through the last 14 days of message tracking logs. You might wonder why to use the Where-Object –Property Recipients –NotLike “HealthMailbox*” part. This filter deletes all entries dedicated to Health Mailboxes. If you are curious, you can compare results with and without the Where-Object filter. Finally, the last cmdlet in the pipeline exports the results to the mtl.html file. You can also export the results to a CSV file, using the ConvertTo-Csv cmdlet.
The problem is, when you convert the results to an HTML or a CSV file, fields containing info on recipients will not be displayed correctly. Instead of the right values, the fields will contain System.String[] expressions. To fix this, you might need to pipeline the results to an additional Select-Object cmdlet. While you are at it, why not limit the output so that it contains only the most important fields?
Get-MessageTrackingLog -Start (Get-Date).AddDays(-7) -ResultSize Unlimited | Where -Property Recipients -NotLike "*HealthMailbox*" | Select-Object sender,@{Name="Recipients";Expression={$_.recipients}},@{Name="RecipientStatus";Expression={$_.recipientstatus}},messagesubject,totalbytes,eventid,messageinfo,messagelatency | ConvertTo-Html > "C:\mtlx.html"
If you want to register all failed deliveries and register them into a file, use the cmdlet below.
Get-MessageTrackingLog -Start (Get-Date).AddHours(-24) -ResultSize Unlimited –EventId Fail | Where -Property Recipients -NotLike “HealthMailbox*” >> “C:\failed deliveries.csv”
The best part is that the >> sign adds new values to the failed.deliveries.csv file, so that you can run the cmdlet periodically to log all Fail Events.
How to gather statistics using Get-MessageTracking Log
If you want to perform some more complicated operations on your message-tracking log operations, save them to a variable.
$mtl Get-MessageTrackingLog -Start (Get-Date).AddDays(-2) –eventId Send -ResultSize Unlimited | Where -Property Recipients -NotLike "*HealthMailbox*"
The cmdlet above stores information on all messages sent over the last two days. To measure how many emails your users have sent in general, simply type:
$mtl | measure
For more detailed information, you can use some additional cmdlets to group, sort and display the results. For example, you can display email count for specific users, sorted in descending order:
$mtl | group-object -property sender | Select-Object name,count | Sort-Object count -desc
Using the Group-Object, Select-Object and Sort-Object trio, together with the Get-MessageTrackingLog cmdlet lets you easily get any mail flow statistics you want.
How to trace specific messages using Get-MessageTrackingLog
Finally, if you want to check what happened to a particular undelivered message, you can quickly show all the most important information by pumping your search to a Format-List cmdlet:
… | FL –Property Sender, Recipients, MessageSubject, RecipientStatus
In the example above, you can easily see that the message was not delivered because of a transport rule. Here, it turned out that at some point, someone has launched a mail flow rule which blocks all messages which have an attachment and the keyword Kitten in the subject.
Let’s suppose that some classified data has leaked out of the company. Message tracking logs can help you with pinpointing users who have sent emails outside of your company, for example to a particular competitive company.
Get-MessageTrackingLog –ResultSize Unlimited | Where -Property Recipients -Like “*@competitive-company.com”
The search lets you find the suspects. Of course, you might need to broaden or tighten the search criteria, but it depends on how much data you have. What you do with the results is not a discussion for the admin’s blog.
Further Reading:
It is great explanation. I just had one query. We have 2 exchange 2016 servers setup in a DAG arrangement. When we pull message tracking logs for a user it always duplicates entries as it gets saved on both the servers. How can we limit it to display only the original e-mail not the one whihc is passed in the background to the second server.
Hi Venkatesh,
Such copies should have the HARECEIVE event name. If that’s the case in your environment, excluding those emails should solve the issue.
the best blog for exchange so far I found
Thank you really nice script could you please help me changing the timestamp to yyyy/MM/DD
Hi Zeeshan,
If you push the date to a variable, you can use the following function:
$date = $date.ToShortDateString();