Find Email Addresses in Office 365 with PowerShell

Sometimes you need to find the user or a mailbox that is using a particular email address. Especially aliases are sometimes hard to find, and you don’t want to open each mailbox to check if it’s using the email address that you need.

You can add email addresses to users or groups in different locations, but they all come together in your Exchange Online server. So that is the place where we are going to search.

We are going to use the new Exchange Online PowerShell Module for this, if you haven’t used it before, then you can follow this short guide to install it and connect to Exchange Online. The advantage of the new module is that you can easily connect to different tenants and it supports MFA.

Finding Emailaddresses with PowerShell

All the email addresses of a mailbox are listed in the EmailAddresses property of the EXOMailbox cmdlet. We can search for any email address by applying a filter on the EmailAddresses. The advantage of the filter is that we can also use wildcards.

Finding Emailaddresses with PowerShell

Let’s start simple and search for a specific email address. In the example, we are going to look up who is using the exchange-support@domain.com email address.

# Make sure you are connected to Exchange Online
Connect-ExchangeOnline

# Search for the emailaddress
# -eq stands for equels, so the emailaddress must be exactly the same as the given string
Get-EXOMailbox -filter {EmailAddresses -eq "exchange-support@lazydev.onmicrosoft.com"}

The result is one mailbox that contains the email address that we are looking for.

Find user with email address powershell office 365

Using wildcards

Wildcards allow you to search on a part of the email address. In PowerShell, you can use the * as a wildcard token, which can be placed anywhere in the string.

Let’s say we want to find all mailboxes that have an email address that contains the word support. We will be using a wildcard in front and after the word Support. Note that we are not using the -eq operator but the -like operator.

When you expect multiple results it is most useful to format the output in a table with the ft cmdlet

# Get all mailboxes that contain the word support
Get-EXOMailbox -Filter {EmailAddresses -like "*support*"} | ft
find email address powershell exchange online

One downside of the format-table output (ft) is that not all properties will fit on your screen. To solve this you can select only the fields that you need, autosize the table and wrap the lines.

Get-EXOMailbox -Filter {EmailAddresses -like "*support*"} | 
ft -Property DisplayName,RecipientType,Identity,EmailAddresses -AutoSize -Wrap
find email address powershell office 365

Search in Distribution Lists

The PowerShell commands above search through all mailboxes for the mail address. But email addresses can also be used in Distribution lists or Office 365 Groups.

To search through the distributions lists we will need to use the Get-DistributionGroup cmdlet from the Exchange Online module.

There are two email fields in the distribution list, the PrimarySMTPAddress, and EmailAddresses. We are going to use the latter because this will also contain all aliases from the Distribution list.

Get-DistributionGroup -Filter {EmailAddresses -like "*support*"} | 
ft -Property DisplayName,RecipientType,Identity,EmailAddresses -AutoSize -Wrap

Search Email Address in Office 365 Groups

The last place where you might want to search for an email address is in the Office 365 Groups. The groups have the same structure as the distribution groups, so we are going to search in the emailaddresses field.

Get-UnifiedGroup -Filter {EmailAddresses -like "*support*"} | 
ft -Property DisplayName,RecipientType,Identity,EmailAddresses -AutoSize -Wrap

Powershell List all Email Addresses and Aliases

Using this principle we can also get a list with all email addresses and aliases and export it to a CSV file for example.

Getting the list with email addresses is a bit more difficult because the EmailAddresses field also contains the SPO (used for SharePoint Online features) and SIP addresses. So we need to filter those out.

By using an expression we can filter the EmailAddresses field and select only the SMTP address. The operator -clike is a case-sensitive like operator.

Get-EXOMailbox | 
Select-Object DisplayName,RecipientType,PrimarySmtpAddress, @{Name="Aliases";Expression={$_.EmailAddresses | Where-Object {$_ -clike "smtp:*"}}}
Export Emailaddresses office 365 powershell

As you can see in the results, the aliases contain the prefix smtp:. We want to remove those as well before we export the results to a csv file. The -join operator joins multiple aliases together with a comma between them.

Get-EXOMailbox | 
Select-Object DisplayName,RecipientType,PrimarySmtpAddress, @{Name="Aliases";Expression={($_.EmailAddresses | Where-Object {$_ -clike "smtp:*"} | 
ForEach-Object {$_ -replace "smtp:",""}) -join "," }}
Powershell List all Email Addresses and Aliases

If you want to export the results to excel, then you only need to add Export-Csv c:\path\filename.csv behind it:

Get-EXOMailbox |
Select-Object DisplayName,RecipientType,PrimarySmtpAddress, @{Name="Aliases";Expression={($_.EmailAddresses | Where-Object {$_ -clike "smtp:*"} |
ForEach-Object {$_ -replace "smtp:",""}) -join "," }} | 
Export-Csv c:\temp\emailaddresses.csv

Return more then 1000 results

By default, the results are limited to 1000 records. If you have more than 1000 mailboxes then add -ResultSize unlimited after Get-ExoMailbox cmdlet:

Get-EXOMailbox -ResultSize unlimited

Search Email Address in all Office 365 locations

I have created a small script that will search in all three locations for the use of an email address. You can also search on a part of the email address. Results are outputted or can be exported to CSV if you like with the Export-CSV cmdlet.

You can download the complete script here from my Github repository.

param(
  [Parameter(
    Mandatory = $true,
    HelpMessage = "Enter the Exchange Online or Global admin username"
  )]
  [string]$adminUPN,

  [Parameter(
    Mandatory = $true,
    HelpMessage = "Emailaddress or part of it to find"
  )]
  [string]$emailAddress
)

Function ConnectTo-EXO {
  <#
    .SYNOPSIS
        Connects to EXO when no connection exists. Checks for EXO v2 module
  #>
  
  process {
    # Check if EXO is installed and connect if no connection exists
    if ((Get-Module -ListAvailable -Name ExchangeOnlineManagement) -eq $null)
    {
      Write-Host "Exchange Online PowerShell v2 module is requied, do you want to install it?" -ForegroundColor Yellow
      
      $install = Read-Host Do you want to install module? [Y] Yes [N] No 
      if($install -match "[yY]") 
      { 
        Write-Host "Installing Exchange Online PowerShell v2 module" -ForegroundColor Cyan
        Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force
      } 
      else
      {
	      Write-Error "Please install EXO v2 module."
      }
    }


    if ((Get-Module -ListAvailable -Name ExchangeOnlineManagement) -ne $null) 
    {
	    # Check if there is a active EXO sessions
	    $psSessions = Get-PSSession | Select-Object -Property State, Name
	    If (((@($psSessions) -like '@{State=Opened; Name=ExchangeOnlineInternalSession*').Count -gt 0) -ne $true) {
		    Connect-ExchangeOnline -UserPrincipalName $adminUPN
	    }
    }
    else{
      Write-Error "Please install EXO v2 module."
    }
  }
}

Function Search-Mailboxes {
  <#
  .SYNOPSIS
    Search for email address in the mailboxes
  #>
  process {
    Write-Host "Searching in mailboxes for $emailAddress" -ForegroundColor Cyan
    Get-EXOMailbox -filter "EmailAddresses -like '*$emailAddress*'"
  }
}

Function Search-Distributionlists {
  <#
  .SYNOPSIS
    Search for email address in the distributionlists
  #>
  process {
    Write-Host "Searching in distributionlists for $emailAddress" -ForegroundColor Cyan
    Get-DistributionGroup -Filter "EmailAddresses -like '*$emailAddress*'"
  }
}

Function Search-Groups {
  <#
  .SYNOPSIS
    Search for email address in the mailboxes
  #>
  process {
    Write-Host "Searching in groups for $emailAddress" -ForegroundColor Cyan
    Get-UnifiedGroup -Filter "EmailAddresses -like '*$emailAddress*'"
  }
}

Function Search-DynamicDistributionlists {
  <#
  .SYNOPSIS
    Search for email address in the distributionlists
  #>
  process {
    Write-Host "Searching in dynamic distributionlists for $emailAddress" -ForegroundColor Cyan
    Get-DynamicDistributionGroup -Filter "EmailAddresses -like '*$emailAddress*'"
  }
}

Function Find-EmailAddress{
  <#
    .SYNOPSIS
      Get all AD users
  #>
  process {
    $result = @()

    $result += Search-Mailboxes
    $result += Search-Distributionlists
    $result += Search-Groups
    $result += Search-DynamicDistributionlists

    $result | ForEach {
        [pscustomobject]@{
          "DisplayName" = $_.DisplayName
          "RecipientType" = $_.RecipientType
          "Identity" = $_.identity
          "EmailAddresses" = $_.EmailAddresses
        }
    }
  }
}

# Connect to Exchange Online
ConnectTo-EXO

Find-EmailAddress | Sort-Object DisplayName 

Wrapping up

I hope you found this article useful. If you have any questions, just drop a comment below. You may also like the following related articles:

12 thoughts on “Find Email Addresses in Office 365 with PowerShell”

  1. I have tweaked your script (thanks so much for the head start!) to allow one to pass “like” or “notlike” as a parameter to use the search that way. In our case we had numerous domains from many acquisitions and we wanted to know what things did/did not contain certain domains in their addressing.
    Also I modified it to check for public folders as those can be mail enabled and if your intent is to search for email addresses, you may need to include those.
    If I knew how to upload to Github I would be happy to send it to you for review.

  2. Hi Rudy, I love the site and your work has been super helpful for me, Thanks.

    I noticed after doing the export to CSV that its pulling in all user mailboxes even for every disabled account in AD which makes the output very large. Is there a way to filter those out?

    • Filtering out disabled users would make the result set incomplete. If an email address is assigned to a disabled account, and you are looking for who is using that address, then you will need the disabled accounts also in the export.

  3. Thanks for sharing this info. Was very useful to me. However I was looking for which email address uses a certain alias. When I try to create a shared mailbox with marketing@ I got a warning that this is already in use. However running your script looking for alias marketing@ didn’t reveal any result?

    • That is strange, the script should get it. What happens when your run the code below, it should list all aliases


      Get-EXOMailbox |
      Select-Object DisplayName,RecipientType,PrimarySmtpAddress, @{Name="Aliases";Expression={$_.EmailAddresses | Where-Object {$_ -clike "smtp:*"}}}

  4. Here’s a curly one. We couldn’t create a new Guest in AAD. The error was – email address being used elsewhere. This was an external address. We used your script to search for the address (thanks by the way) but it didn’t show up.

    Quite by chance we stumbled on a MailUser in AAD, and under the Contact Info, the Email field was set to the external address. Not the PUA, the Contact Info section on AAD > USERS > USER_NAME

    So there are email address locations in the system that ‘hide’ from available powershell/graph queries?

  5. Hey Ruud! I love your site, saved me a ton of time as I’m just getting my feet wet in the world of powershell and scripting.

    In my org. we use quite a lot of dynamic distributiongroups. Often a better option than the static ones that are hard to maintain and keep updated. Would it be possible to add a few lines in the script to widen the scope to include dynamic distributiongroups as well?

    Get-DynamicDistributionGroup -Filter “EmailAddresses -like ‘*$emailAddress*'”

    I’ll fiddle with the script myself, just thought it would be useful for others as well, including you. Thanks for all the great work!

  6. This is a good answer, but its not complete, it does not include eail addresses assigned to groups and distribution lists…

Leave a Comment

0 Shares
Tweet
Pin
Share
Share