Report Email Proxy Addresses for Exchange Online Mail-Enabled Objects

List All Email Proxy Addresses for Exchange Online Objects

A reader of the Office 365 for IT Pros eBook asked if there’s an easy way to see a list of all the email addresses used in a tenant. The simple answer is that there’s no out-of-the-box method to see this information. Some work is needed to extract and report a list of all email addresses. It’s not just the primary SMTP address for mailboxes either – such a report must include all the proxy SMTP addresses for all mail-enabled objects.

Proxy Addresses

An Exchange Online mail-enabled object such as a user mailbox can have up to 300 different proxy addresses. Although most inbound email arrives addressed to a mail-enabled object’s primary SMTP address, Exchange Online can deliver messages to any of the proxy addresses (aliases) assigned to a mail-enabled object. Outbound, Exchange Online mailboxes can send email using any proxy address.

Proxy addresses are permanently assigned to a mail-enabled object and stored in the Exchange Online directory. They’re not the same as plus addressing, which individual people can use to create a specific form of a proxy address to receive email from certain senders. Apart from SMTP addresses, the proxy addresses assigned to user mailboxes include SIP and SPO addresses. The first is used for federated chat; the second is used to store SharePoint Online information into user mailboxes. The Microsoft 365 substrate ingests SharePoint Online content into mailboxes to create ‘digital twins’ that are used by cloud processes and services.

Creating a PowerShell Script to Report SMTP Proxy Addresses

Now that we’ve got the definitions out of the way, let’s use PowerShell to answer the question. The steps involved are very straightforward and can be summarized as:

For each type of mail-enabled objects supported by Exchange Online, find the SMTP proxy addresses and report them.

I wrote a script to do the job (you can download the code from GitHub). It breaks processing up into:

  • Mailboxes (user, shared, room, and resource).
  • Group mailboxes (for Microsoft 365 groups).
  • Mail-enabled public folders.
  • Distribution lists.
  • Dynamic distribution lists.

For instance, here’s the code to process mailboxes:

Write-Host "Fetching details of user, shared, equipment, and room mailboxes..."
[array]$Mbx = Get-ExoMailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox, SharedMailbox, RoomMailbox, EquipmentMailbox
Write-Host ("Processing details for {0} mailboxes..." -f $Mbx.count)
ForEach ($M in $Mbx) {
    ForEach ($Address in $M.EMailAddresses) {
        $AddressType = $Address.Split(":")[0]
        $AddressProxy = $Address.Split(":")[1]
        If ($AddressType -eq 'smtp') {
            $ReportLine = [PSCustomObject]@{ 
                ProxyAddress = $AddressProxy
                Name         = $M.DisplayName
                UPN          = $M.userPrincipalName
                ObjectId     = $M.ExternalDirectoryObjectId
                Type         = $M.RecipientTypeDetails

The code examines each proxy address. If its address type is SMTP, the script records the address and some other information. It’s really that simple. Figure 1 shows some of the list of SMTP proxy addresses extracted from my tenant.

Listing of Exchange Online proxy addresses for different objects

Email proxy address
Figure 1: Listing of Exchange Online proxy addresses for different objects

Using the List of Email Proxy Addresses

The next question is how to use such a list? One idea is to load some of the list of proxy addresses into a hash table and use the table to add extra detail to the information provided in message trace logs by resolving email addresses to find the display name for message recipients.

To test the idea, I enhanced some code from the article about using message trace logs to analyze email traffic to add the creation and population of a hash table using data imported from the CSV file output for the list of proxy addresses. For each message in the trace data, I then attempt to find a match in the hash table and include the name of the recipient if found. The added code is in italics.

[array]$EmailProxies = Import-CSV "C:\Temp\EmailProxyAddresses.csv"
$EmailProxyHash = @{}
ForEach ($E in $EmailProxies) {
   $EmailProxyHash.Add($E.ProxyAddress, $E.Name) }

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

ForEach ($M in $Messages) {
   $Direction = "Inbound"
   $DisplayName = $Null
   $SenderDomain = $M.SenderAddress.Split("@")[1]
   $RecipientDomain = $M.RecipientAddress.Split("@")[1]
   If ($SenderDomain -in $Domains) {
      $Direction = "Outbound" 
   $DisplayName = $EmailProxyHash[$M.RecipientAddress] 

   $ReportLine = [PSCustomObject]@{
     TimeStamp       = $M.Received
     Sender          = $M.SenderAddress
     Recipient       = $M.RecipientAddress
     Name            = $DisplayName
     Subject         = $M.Subject
     Status          = $M.Status
     Direction       = $Direction
     SenderDomain    = $SenderDomain
     RecipientDomain = $RecipientDomain

No doubt others will find more creative ways to use the listing of email proxy addresses. If you do, let us know in the comments.

Learn more about how the Office 365 applications really work on an ongoing basis by subscribing to the Office 365 for IT Pros eBook. The monthly updates for the book keep subscribers informed about what’s important across the Office 365 ecosystem.

Leave a Reply

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