Use Message Trace Data to Detect Unused Proxy Addresses

After reading the article about generating a mailbox traffic report from Graph usage data, a reader asked if it is possible to pull data about the proxy addresses for mailboxes to discover which addresses are in active use. Apparently, the organization in question has many accepted domains and they want to cleanup (remove) unused proxy addresses.

My initial reaction was that all of the usage reports generated by Exchange Online and Microsoft 365 feature primary SMTP addresses (usually the same as user principal names), so there’s no off-the-shelf report to highlight unused proxy addresses. Some scripting is required to answer the request.

[This was the first challenge in the PowerShell script-off at the TEC 2025 conference. We had a lot of fun seeing the solutions that script-off competitors came up with.]

Understanding Proxy Addresses and Accepted Domains

Before starting to code, it’s worth discussing why proxy addresses exist. All mail-enabled objects support proxy addresses, which come in various flavors. Originally, Exchange Server used X.400 addresses. Today, Exchange Online mail-enabled objects all have SMTP proxy addresses. All Microsoft 365 tenants should have at least two accepted domains. One is the MOERA (Microsoft Online Exchange Routing Address) domain, the service domain in the onmicrosoft.com domain assigned to the tenant when it’s created. For example, office365itpros.onmicrosoft.com is a MOERA domain.

Microsoft is about to impose sending limits on MOERA domains to stop tenants using these domains sending more to more than 100 external recipients in a 24-hour rolling window. The idea is that spammers often sign up for a test tenant and use the MOERA domain to send spam for as long as they can before a block descends.

Instead of using MOERA domains to send and receive email, tenants should have a “vanity” domain registered as an accepted domain with Exchange Online. Office365itpros.com is an example of a vanity domain. In a tenant with a MOERA and a vanity domain, mailboxes can have two proxy or more proxy addresses belonging to the domains. Each of the proxy addresses is routable, meaning that Exchange Online can deliver email to the mailbox associated with the proxy address, but only one of the addresses is the primary SMTP address.

If you examine the email addresses registered for a mail-enabled object, you’ll usually find multiple proxy addresses. In this example, a mailbox has two SMTP addresses (the primary SMTP address is prefixed with SMTP: in capital letters), and a proxy address for SIP communications (like Teams chat) and SharePoint Online (SPO). Don’t do anything with the SPO proxy. If you do, you’ll affect the ability of SharePoint Online to link to a mailbox.

Get-EXOMailbox -Identity Lotte.Vetler | Select-Object -ExpandProperty EmailAddresses

SIP:lotte.vetler@office365itpros.com
SPO:SPO_ef26ab8e-7b7f-487a-aaaa-5e819b65c314@SPO_b662313f-14fc-43a2-9a7a-d2e27f4f3478
SMTP:Lotte.Vetler@office365itpros.com
smtp:Lotte.Vetler@office365itpros.onmicrosoft.com 

Over time, it’s common for mail-enabled objects to accumulate proxy addresses. A user might change their name because of a life event, or the organization might merge with another company and the SMTP address for mailboxes merged into the domain are retained to allow Exchange to route messages sent to these addresses, or the company might go through a branding change and use a different vanity domain. In the case of the original question, the company has many accepted domains and it’s likely that many mail-enabled objects have proxy addresses from domains that are no longer in active use. The request is to find and remove those addresses.

Keeping a few unused proxy addresses for mail-enabled objects is not a problem and won’t do any harm. This is simply a housekeeping exercise to make sure that objects only have addresses that they actually use.

Using Message Tracing Data

My first thought was to use message trace logs. I had a script that could be adapted from an article about generating an analysis for inbound and outbound traffic that I adapted to do the job (here’s the adapted script). The records in the trace logs store sender and recipient addresses, and by extracting the information into a usable format, it is possible to check the proxy addresses assigned to mailboxes, shared mailboxes, and other mail-enabled objects against the data to identify unused proxy addresses.

The problem with using online message trace data is that the data only goes back 10 days, and that’s not enough to base any decision about mailbox activity. Historical message trace data is available for 90 days, which is a better time window for this kind of analysis, so that became my focus.

Analyzing Historical Message Tracing Data

The article about creating an inbound email traffic report for the last 90 days covers the details of creating requests to download historical message trace data. The first change that I made was to change the direction parameter to download both sent and received messages. Here’s an example of a command I used to submit the request for the historical data:

$Status = Start-HistoricalSearch -RecipientAddress $MailboxAddresses -StartDate $StartDate -EndDate (Get-Date) -ReportType MessageTrace -ReportTitle $ReportName -Direction Received -NotifyAddress Admin@office365itpros.com

When the job completes, you can download the CSV containing the results for processing. The command shown above focuses on recipients (inbound email). You should also submit a job to fetch the data for sender activity. Here’s an example of a command to request historical message trace data based on sender addresses:

$Status = Start-HistoricalSearch -SenderAddress $MailboxAddresses -StartDate $StartDate -EndDate (Get-Date) -ReportType MessageTrace -ReportTitle $ReportName -Direction All -NotifyAddress admin@office365itpros.com

I made sure to include all proxy addresses rather than simply the primary SMTP address in the recipient addresses parameter. The code explaining how to do this is in the article.

Remember that only one hundred recipient addresses can be included in a historical message trace request. To process more than a hundred proxy addresses, you must split the addresses up across multiple jobs and download the data for each job for the script to process.

Code Changes to the Script

I took the code in the script written for the original article to analyze the downloaded CSV files and used it as the basis for the solution. One of the big changes is to generate two arrays called $SenderAddresses and $RecipientAddresses. The arrays contain the unique proxy addresses found for the messages extracted from the historical message tracing data. The entry for a proxy address also includes details about the message where the address was used. Here’s an example of a record in an array:

Timestamp       : 2025-07-07T16:39:24.2373598Z
Sender          : AllArchitectsM365@Office365itpros.com
Subject         : You've joined the System and Engineering Architects (Group) group
Recipient       : ben.james@Office365itpros.com
RecipientDomain : Office365itpros.com
RecipientStatus : ben.james@Office365itpros.com##Receive, Deliver
RecipientInfo   : {@{Recipient=ben.james@Office365itpros.com; Outcome=Receive, Deliver}}
Outcome         : Receive, Deliver
Bytes           : 370080
Message_id      : <DU4PR04MB108861D7DDF790868BE01FA40BE4FA@DU4PR04MB10886.eurprd04.prod.outlook.com>
Sender_Domain   : Office365itpros.com
Client_IP       : 2603:10a6:10:580::18
Direction       : Originating

Checking Proxy Addresses

The next step is to fetch details of the objects to analyze. This example selects user and shared mailboxes:

[array]$Mailboxes = Get-ExoMailbox -ResultSize Unlimited -Properties EmailAddresses -RecipientTypeDetails UserMailbox, SharedMailbox

Now we can loop through the mailboxes to check each proxy address against the arrays generated by the script. If no entry for the proxy address is found in either the sender or recipient arrays, we have an unused proxy address and report the fact. MOERA proxy addresses are excluded from reporting because it’s unlikely that you’ll want to remove these proxies and they shouldn’t be used to send or receive email. However, it’s easy to change the code so that the MOERA proxies are reported.

$UnusedProxyReport = [System.Collections.Generic.List[Object]]::new() 
ForEach ($Mbx in $Mailboxes) {
    $MbxAddresses = $Mbx.EmailAddresses | Where-Object {$_ -like "smtp:*"} 
    ForEach ($Address in $MbxAddresses) {
        $SmtpAddress = $Address.Substring(5)  # Remove the smtp: prefix
        If ($Address.SubString(0,4) -ceq "SMTP") {
            $AddressType = "Primary"
        } Else {
            $AddressType = "Proxy" 
        }
        If ($SmtpAddress -notin $SenderAddresses.Sender -and $SmtpAddress -notlike "*.onmicrosoft.com") {
            $ReportLine = [PSCustomObject]@{
                DisplayName         = $Mbx.DisplayName
                PrimarySmtpAddress  = $Mbx.PrimarySmtpAddress
                Alias               = $Mbx.Alias
                MailboxType         = $Mbx.RecipientTypeDetails
                UnusedProxyAddress  = $SmtpAddress
                AddressType         = $AddressType
                CheckType           = "Sender"
            }
            $UnusedProxyReport.Add($ReportLine)
        }
        If ($SmtpAddress -notin $RecipientAddresses.Recipient  -and $SmtpAddress -notlike "*.onmicrosoft.com") {
            $ReportLine = [PSCustomObject]@{
                DisplayName         = $Mbx.DisplayName
                PrimarySmtpAddress  = $Mbx.PrimarySmtpAddress
                Alias               = $Mbx.Alias
                MailboxType         = $Mbx.RecipientTypeDetails
                UnusedProxyAddress  = $SmtpAddress
                AddressType         = $AddressType
                CheckType           = "Recipient"
            }
            $UnusedProxyReport.Add($ReportLine)
        }
    }
}
$UnusedProxyReport | Select-Object DisplayName, UnusedProxyAddress, AddressType, CheckType, MailboxType, PrimarySmtpAddress | Out-GridView -Title "Unused Proxy Addresses"

Figure 1 shows the results for one mailbox. We can see that the primary SMTP address has not been used as a recipient, and that two proxy addresses have not been used for either sending or receiving email.

Reporting unused proxy addresses for a mailbox.
Figure 1: Reporting unused proxy addresses for a mailbox

The final step in the script is to generate either an Excel worksheet or CSV file, depending on the availability of the ImportExcel module.

You can download the complete script from GitHub. Remember, it’s a proof of concept rather than a complete solution.

The Next Phase

After finding some unused proxy addresses, the next phase is to review and remove any of the addressed deemed to be unnecessary. Apart from generating the output file, the script doesn’t help. You’ll have to conduct the review yourself and then update the mailboxes to remove the unwanted addresses. Or decide to leave well alone and go on to the next administrative challenge.

About the Author

Tony Redmond

Tony Redmond has written thousands of articles about Microsoft technology since 1996. He is the lead author for the Office 365 for IT Pros eBook, the only book covering Office 365 that is updated monthly to keep pace with change in the cloud. Apart from contributing to Practical365.com, Tony also writes at Office365itpros.com to support the development of the eBook. He has been a Microsoft MVP since 2004.

Leave a Reply