2 minute read

The Challenge

I needed to create a list of all Primary SMTP addresses for all users on a client’s Exchange Online tenant, to compare with addresses registered in their email filtering system and remove invalid accounts.

Get-Mailbox and Get-Recipient both return an EmailAddresses property for each object, but they are a serialised combination of all types of address registered against every mailbox returned.

I wanted to simply return the Primary SMTP address (which is denoted by the capitalised “SMTP:” before the address.)

How I Did It

First I wanted to see how I could manipulate the EmailAddresses Property contents and filter out exactly what I needed, so first, in order to save time querying the tenant over and over I grabbed the Get-Mailbox results into a variable.

$mailboxes = Get-Mailbox

I quickly realised that I only wanted to work on a single object, so I re-ran the above but selected just the first 1.

$mailboxes = Get-Mailbox | Select-Object -First 1

I took a peek at the EmailAddresses property and got what I was hoping for (edited for privacy):

$mailboxes.EmailAddresses

smtp:email.address@tenant.onmicrosoft.com
SMTP:email.address@ourdomain.com
X500:/o=First Organization/ou=OUName (RANDOMSTRING)/cn=Recipients/cn=RANDOMSTRING
x500:/o=First Organization/ou=OUName (RANDOMSTRING)/cn=Recipients/cn=RANDOMSTRING

I then ran the object through a couple of Where-Object cmdlets to see how I could isolate the SMTP: address:

$emailaddresses = $mailboxes.emailaddress | Where-Object { $_ -like *SMTP* }

smtp:email.address@tenant.onmicrosoft.com
SMTP:email.address@ourdomain.com

Close, but too many results… Because I didn’t consider casing! Solved by simply adding a “c” to the beginning of the comparison operator (-like becomes -clike)…

$emailaddresses = $mailboxes.emailaddress | Where-Object { $_ -clike *SMTP* }

SMTP:email.address@ourdomain.com

Suitably pleased with the result, I then needed to expand this operation to run against all the objects returned from Get-Mailbox - which meant getting my hands dirty in VSCode… Yay!

Building the Function

This started out innocently enough as a simple script, but as you’ll see, it began to evolve into a handy function as I saw potential applications for it with other clients.

I needed to return an object containing just the user name and the primary SMTP address, so I employed a couple of foreach loops:

foreach ($mailbox in $mailboxes) {
    $emailaddresses = $mailbox.EmailAddresses
    foreach ($emailaddress in $emailaddresses) {
        $smtpaddress = $emailaddress | Where-Object { $_ -clike '*SMTP*' }
        [PSCustomObject]@{
            'Name'        = $mailbox.Name
            'SMTPAddress' = $smtpaddress
        }
    } #foreach emailaddress
} #foreach recipient

This returned a list of 400+ objects exactly as desired (edited for privacy and brevity):

Name                                                         SMTPAddress
----                                                         -----------
User.1                                                       SMTP:user.1@domain.com
User.2                                                       SMTP:user.2@domain.com
User.3                                                       SMTP:user.3@domain.com
User.4                                                       SMTP:user.4@domain.com
User.5                                                       SMTP:user.5@domain.com
etc

At this point, it seemed logical to upscale this into a function - so I created the appropriate structure, added a try/catch to deal with the possibility that the user has not connected to Exchange Online / Exchange on-premise, then added an if/else construct to filter out the inevitable blank results due to the nested foreach/where-object process.

The results are in my GitHub repo. The module is now a working work-in-progress and my intentions are noted in the Projects section.

Please feel free to comment and make suggestions - there’s almost certainly something I can do to refine this and I’m always keen to get tips. I’d also love to hear if this has helped anyone in their early steps into scripting and automation with PowerShell :)