/cheatsheets/exchange-online/exchange-online-powershell-cheat-sheet
Exchange Online PowerShell cheat sheet (ExchangeOnlineManagement V3)
- tool
- Exchange Online PowerShell
- versions
- ExchangeOnlineManagement 3.10.1
- os
- windows, linux, macos
Commands for the ExchangeOnlineManagement module (EXO V3), grouped by task. Every cmdlet except the connection cmdlets needs Connect-ExchangeOnline first; replace the example addresses with yours.
Install and connect
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Connect-ExchangeOnline -UserPrincipalName admin@contoso.com
Get-ConnectionInformation # open connections
Disconnect-ExchangeOnline -Confirm:$falseThe module itself contains only the connection cmdlets and nine fast Get-EXO* cmdlets; all other Exchange cmdlets are added by the connection. The nine Get-EXO cmdlets, listed offline from module 3.10.1:
Import-Module ExchangeOnlineManagement
Get-Command -Module ExchangeOnlineManagement -Name 'Get-EXO*' | Sort-Object Name | ForEach-Object NameOutput
Get-EXOCasMailbox Get-EXOMailbox Get-EXOMailboxFolderPermission Get-EXOMailboxFolderStatistics Get-EXOMailboxPermission Get-EXOMailboxStatistics Get-EXOMobileDeviceStatistics Get-EXORecipient Get-EXORecipientPermission
Find mailboxes and recipients
| Command | Task |
|---|---|
| Get-EXOMailbox -ResultSize Unlimited | All mailboxes (fast) |
| Get-EXOMailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited | Shared mailboxes only |
| Get-EXORecipient -Identity user@contoso.com | Any recipient by address |
| Get-EXORecipient -Filter "EmailAddresses -eq 'smtp:user@contoso.com'" | Who owns an address |
| Get-EXOMailboxStatistics -Identity user@contoso.com | Mailbox size |
| Get-Mailbox -Identity user@contoso.com | Format-List | All properties of one mailbox |
Permissions
| Command | Task |
|---|---|
| Add-MailboxPermission -Identity sales@contoso.com -User anna@contoso.com -AccessRights FullAccess -InheritanceType All | Full Access |
| Add-RecipientPermission -Identity sales@contoso.com -AccessRights SendAs -Trustee anna@contoso.com -Confirm:$false | Send As |
| Set-Mailbox -Identity sales@contoso.com -GrantSendOnBehalfTo @{Add="anna@contoso.com"} | Send on Behalf |
| Get-EXOMailboxPermission -Identity sales@contoso.com | List Full Access |
| Get-EXORecipientPermission -Identity sales@contoso.com | List Send As |
| Add-MailboxFolderPermission -Identity anna@contoso.com:\Calendar -User bob@contoso.com -AccessRights Editor | Calendar permission |
Mailbox settings
| Command | Task |
|---|---|
| Set-Mailbox -Identity anna@contoso.com -Type Shared | Convert to shared |
| Set-Mailbox -Identity anna@contoso.com -ForwardingSmtpAddress smtp:anna@fabrikam.com -DeliverToMailboxAndForward $true | Forward and keep a copy |
| Set-Mailbox -Identity anna@contoso.com -ForwardingSmtpAddress $null | Remove forwarding |
| Set-Mailbox -Identity anna@contoso.com -EmailAddresses @{Add="smtp:a.smith@contoso.com"} | Add an alias |
| Set-MailboxAutoReplyConfiguration -Identity anna@contoso.com -AutoReplyState Enabled -InternalMessage "Away" -ExternalMessage "Away" | Out of office |
| Set-Mailbox -Identity anna@contoso.com -HiddenFromAddressListsEnabled $true | Hide from address lists |
Distribution groups
| Command | Task |
|---|---|
| New-DistributionGroup -Name "ITDepartment" -Members chris@contoso.com,laura@contoso.com | Create a distribution list |
| New-DistributionGroup -Name "Managers" -Type Security | Create a mail-enabled security group |
| Add-DistributionGroupMember -Identity "Staff" -Member john@contoso.com | Add a member |
| Remove-DistributionGroupMember -Identity "Staff" -Member john@contoso.com -Confirm:$false | Remove a member |
| Get-DistributionGroupMember -Identity "Staff" -ResultSize Unlimited | List members |
| Get-UnifiedGroupLinks -Identity "Sales" -LinkType Members | Microsoft 365 group members |
-Type accepts Distribution (default, cannot be used for permissions) and Security (mail-enabled security group, can hold permissions).
Mail flow
| Command | Task |
|---|---|
| Get-MessageTraceV2 -SenderAddress anna@contoso.com -StartDate (Get-Date).AddDays(-2) -EndDate (Get-Date) | Trace by sender |
| Get-MessageTraceV2 -RecipientAddress anna@contoso.com -Status Failed | Failed messages to a recipient |
| Get-MessageTraceDetailV2 -MessageTraceId GUID -RecipientAddress anna@contoso.com | Events of one message |
How to read this cheat sheet
Each table pairs a command you can paste with the task it performs. Three rules explain most surprises:
- Two kinds of cmdlets. The
Get-EXO*cmdlets ship inside the module and exist as soon as you import it; everything else (Get-Mailbox,Set-Mailbox,New-DistributionGroup,Get-MessageTraceV2) is created byConnect-ExchangeOnlinefor the session. Before you connect, the first kind fails with You must call Connect-ExchangeOnline and the second kind is "not recognized". - Result size. Most
Get-cmdlets stop at 1000 objects. Add-ResultSize Unlimitedwhenever you report on a whole tenant, or the export silently misses objects. - Fast versus complete.
Get-EXOMailboxreturns a minimal property set unless you add-Propertiesor-PropertySets;Get-Mailboxreturns every property but is slower. The comparison page lists the differences.
Permissions you need
Exchange Online uses role-based access control. Reading recipients needs a role such as View-Only Recipients; changing mailboxes, permissions and groups needs Recipient Management or Organization Management; message trace needs a role that includes the trace cmdlets. Role changes apply to new sessions only, so run Disconnect-ExchangeOnline and connect again after an administrator assigns a role. For unattended scripts, use certificate-based app-only authentication instead of a user account.
Errors you will meet
| Message | What it means |
|---|---|
| You must call Connect-ExchangeOnline before calling any other cmdlet. | A Get-EXO cmdlet ran before the session was opened; connect first. |
| The term 'Get-Mailbox' is not recognized | No connection yet, or your roles do not include the cmdlet. |
| The operation couldn't be performed because object '...' couldn't be found | The identity does not match any recipient; check the address or use the GUID. |
| The proxy address "SMTP:..." is already being used by the proxy addresses or LegacyExchangeDN | Another recipient already owns the alias you tried to add. |
Details and fixes: object couldn't be found, proxy address already being used, Get-Mailbox not recognized.
FAQ
Why does Get-Mailbox work for a colleague but is not recognized for me?
Connect-ExchangeOnline imports only the cmdlets your RBAC roles allow. If your account lacks a role that contains Get-Mailbox or Set-Mailbox, the cmdlet is simply not created in your session.
Should I use Get-EXOMailbox or Get-Mailbox in scripts?
Use Get-EXOMailbox for bulk reads: it is part of the module and returns only the property sets you request. Use Get-Mailbox when you need a property or parameter that the EXO cmdlet does not expose.
Does the module work in PowerShell 7 on Linux and macOS?
Yes. ExchangeOnlineManagement 3.x runs in Windows PowerShell 5.1 and in PowerShell 7 on Windows, Linux and macOS, because V3 uses REST instead of remote PowerShell sessions.
Sources
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell-v2
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/exchange/connect-to-exchange-online-powershell
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/module/exchangepowershell/new-distributiongroup
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/module/exchangepowershell/add-distributiongroupmember
- learn.microsoft.comlearn.microsoft.com/en-us/powershell/module/exchangepowershell/get-distributiongroupmember