Use Message Trace Data to Analyze Email Traffic

Analyze Traffic for Inbound and Outbound Domains Over the Last Ten Days

I’ve covered how to use the Exchange Online message trace facility several times in the past to handle tasks like analyzing email sent to external domains. A reader asked if it’s possible to summarize the top inbound and outbound domains using the same data. The answer is that it’s certainly possible to extract this information, but only for the last ten days because that’s how long Exchange Online keeps message trace data online.

Figure 1 shows the output of the script I wrote to demonstrate the principles of the solution. You can download the script from GitHub and make whatever improvements you like.

Top 10 outbound and inbound domains computed from message trace data
Figure 1: Top 10 outbound and inbound domains computed from message trace data

Fetching Message Trace Data

After connecting to Exchange Online, the first task is to retrieve message trace data for analysis. The Get-MessageTrace cmdlet fetches message trace events in pages of up to 5,000 objects. To fetch all available data, the script retrieves information page-by-page until there’s nothing left. This code does the job with a While loop:

[int]$i = 1
$MoreMessages = $True
[array]$Messages = $Null
$StartDate = (Get-Date).AddDays(-10)
$EndDate = (Get-Date).AddDays(1)

Write-Host ("Message trace data will be analyzed between {0} and {1}" -f $StartDate, $EndDate)
While ($MoreMessages -eq $True) {
    Write-Host ("Fetching message trace data to analyze - Page {0}" -f $i)
    [array]$MessagePage = Get-MessageTrace -StartDate $StartDate -EndDate $EndDate -PageSize 1000 -Page $i -Status "Delivered"
    If ($MessagePage)  {
        $i++
        $Messages += $MessagePage
    } Else {
        $MoreMessages = $False
    }
}

My tenant includes public folders. Public folder mailboxes synchronize hierarchy data between each other to make sure that users can connect and access public folders no matter which public folder mailbox they select. The synchronization messages aren’t very interesting, so the script removes them:

# Remove Exchange Online public folder hierarchy synchronization messages
$Messages = $Messages | Where-Object {$_.Subject -NotLike "*HierarchySync*"}

Creating Data to Analyze

Next, the script fetches the set of accepted domains and extracts the domain names into an array. When the script analyzes messages, it uses the domain names to decide if a message is inbound or outbound based on the sender’s email address:

[array]$Domains = Get-AcceptedDomain | Select-Object -ExpandProperty DomainName

The script then loops through the message trace records to create a list with the sender domain extracted and the direction (inbound or outbound) determined:

$Report = [System.Collections.Generic.List[Object]]::new() 

ForEach ($M in $Messages) {
   $Direction = "Inbound"
   $SenderDomain = $M.SenderAddress.Split("@")[1]
   $RecipientDomain = $M.RecipientAddress.Split("@")[1]
   If ($SenderDomain -in $Domains) {
      $Direction = "Outbound" 
   }
   $ReportLine = [PSCustomObject]@{
     TimeStamp       = $M.Received
     Sender          = $M.SenderAddress
     Recipient       = $M.RecipientAddress
     Subject         = $M.Subject
     Status          = $M.Status
     Direction       = $Direction
     SenderDomain    = $SenderDomain
     RecipientDomain = $RecipientDomain
    }
    $Report.Add($ReportLine)

}

After that, it’s simply a matter of splitting the data into separate arrays containing inbound and outbound messages and piping the results to the Group-Object cmdlet to count the number of times domains appear in the set. We then display the top 10 domains for inbound traffic and the same for outbound traffic, which is what you see in Figure 1. For example, here’s the code to display the top ten outbound domains:

$OutboundMessages | Group-Object RecipientDomain -NoElement | Sort-Object Count -Descending | Select-Object -First 10 | Format-Table Name, Count -AutoSize

Traffic Sent to Groups

One thing to be aware of for inbound traffic is that entries for a message delivered to a Microsoft 365 group or distribution list appears in the message trace data for each recipient. This is logical because Exchange Online needs to track the progress of a message to its final destination. However, it does amplify the number of messages that an external domain appears to send to your tenant.

Use PowerShell to Supplement Standard Reports

The Reports section of the Exchange admin center features a top domain mail flow status report with tabs for inbound and outbound traffic. On the surface, these reports seem like they do the same job. They don’t because these reports are focused on different factors (read the documentation for details). Between what Microsoft provide and what you can create using PowerShell, you’ll have a pretty good idea of what’s happening for email traffic to and from your tenant.


Learn how to exploit the data available to Microsoft 365 tenant administrators through the Office 365 for IT Pros eBook. We love figuring out how things work.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.