To export mail contacts in Exchange Online, read them with Get-MailContact -ResultSize Unlimited and keep the external address each one delivers to. The cmdlet returns 1000 contacts unless told otherwise. Mail users and guests have external addresses too, but they are read with Get-MailUser.
| Method | Best fit |
|---|---|
| PowerShell | A CSV of every mail contact with its external address, domain and address list setting. |
| Admin centre | A quick download of the contacts list with names, addresses and types. |
| Altivane | Recommended for regular directory clean-ups, with contacts, mail users and guests in 1 table and duplicates marked. |
Before you start
Use an account in a role group that can read recipients, such as View-Only Organization Management or Recipient Management. Microsoft lists the permissions for contacts under Recipients in its feature permissions for Exchange Online. The example uses the ExchangeOnlineManagement module and asks for no Microsoft Graph permission.
Know which recipient is which. A mail contact holds the details of someone outside your organisation, with an external email address. A mail user also has an external address, but it has sign-in credentials in your Microsoft 365 organisation and can reach its resources. The examples read and export; they create, change or remove no contact.
Option 1
Export mail contacts with PowerShell
Install the module once, then connect and export 1 row for each mail contact.
# Install once, if the module is not already installed.
Install-Module ExchangeOnlineManagement -Scope CurrentUser$ErrorActionPreference = 'Stop'
Connect-ExchangeOnline
try {
$contacts = @(Get-MailContact -ResultSize Unlimited)
$report = @(foreach ($contact in $contacts) {
$external = "$($contact.ExternalEmailAddress)" -replace '^SMTP:', ''
[pscustomobject]@{
Name = $contact.DisplayName
ExternalAddress = $external
ExternalDomain = ($external -split '@')[-1]
PrimaryAddress = $contact.PrimarySmtpAddress
Alias = $contact.Alias
HiddenFromAddressLists = $contact.HiddenFromAddressListsEnabled
Type = $contact.RecipientTypeDetails
}
})
if ($report.Count -eq 0) {
Write-Output 'The tenant has no mail contacts.'
} else {
$report | Sort-Object ExternalDomain, Name |
Export-Csv -Path './mail-contacts.csv' -NoTypeInformation -Encoding utf8
Write-Output "$($report.Count) mail contacts exported."
}
} finally {
Disconnect-ExchangeOnline -Confirm:$false
}The CSV has 1 row per contact, sorted by the domain of its external address, so the contacts for each outside organisation sit together. The script takes the SMTP: prefix off the external address. Type is MailContact or MailForestContact, the 2 subtypes Get-MailContact returns. To keep only the contacts people can see in the address book, add -Filter 'HiddenFromAddressListsEnabled -eq $false'.
Add mail users and guests
Reconnect with Connect-ExchangeOnline, then read the mail users, guests included. The export above disconnects when it finishes.
# Run while connected to Exchange Online.
Get-MailUser -ResultSize Unlimited |
Select-Object DisplayName, ExternalEmailAddress, PrimarySmtpAddress, RecipientTypeDetailsOption 2
Download the contacts list in the admin centre
- Sign in to the Exchange admin centre for the correct tenant.
- Go to Recipients > Contacts. The list shows Display name, Email address and Contact type for each entry.
- Select Filter and choose Mail contacts to leave out mail users and guests.
- Select every entry with the round check box in the column heading, then select Export contacts and Export contacts in current list.
- Open Contacts.csv from your Downloads folder.
This suits a quick list of names and addresses. For more of each contact's settings, such as whether it is hidden from address lists or synced from on-premises, use PowerShell or a report.
Option 3 ยท Recommended for regular directory clean-ups
Run Altivane's Contacts and Mail Users report
- Open Altivane and choose the tenant.
- Run the Contacts and Mail Users report for Exchange Online.
- Open the Excel workbook and read the table of the same name: each contact, mail user and guest with its Type, External Address, External Domain, Primary Address, Hidden From Address Lists, Synced From On-Premises and Created.
- Filter Status for Review, and read Reason for why.
Altivane reads mail contacts and mail users together, so guests and mail users sit beside contacts in 1 table. It marks Review on a recipient with no external address, on an external address used by more than 1 contact or mail user, and on a contact whose external address is in 1 of your organisation's own domains.
Contact usCommon questions
Why does my export stop at 1000 contacts?
Get-MailContact returns 1000 results by default. Add -ResultSize Unlimited, as the script does, to read every contact.
Why is a guest missing from the export?
A guest is a mail user, not a mail contact, so Get-MailContact leaves it out. Read guests with Get-MailUser, as in the second block. In the admin centre, the Contacts list has its own Guest mail users filter.
Which groups is a contact in?
A contact can be a member of distribution groups, so outside people receive the group's mail. To list every member of every group, contacts included, see how to export distribution group members in Exchange Online.
Microsoft references
Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.