Skip to the content.

Exchange Online Powershell

https://learn.microsoft.com/en-us/powershell/exchange/exchange-online-powershell?view=exchange-ps
Other Exchange PowerShells
https://aka.ms/exov3-module

Setup

Install

Install-Module ExchangeOnlineManagement
# OR
Install-Module ExchangeOnlineManagement -Scope CurrentUser

Update:

Update-Module ExchangeOnlineManagement

If you get Module 'ExchangeOnlineManagement' was not installed by using Install-Module, so it cannot be updated.:

Import and connect

# First time ever you need to install the module
Import-Module ExchangeOnlineManagement

# Normally you just need to type
Connect-ExchangeOnline
# You should get modern prompt that will deal with mfa

# When you are finished you should disconnect by typing:
disconnect-exchangeonline

https://docs.microsoft.com/en-au/powershell/exchange/connect-to-exchange-online-powershell?view=exchange-ps

Removing OWA Signatures from Email

# check signature settings
Get-MailboxMessageConfiguration -id john.doe@domain.com | select *sig*

# Blank out signature value
Set-MailboxMessageConfiguration -id john.doe@domain.com -SignatureHtml $null -SignatureText $null

# set values to use signature to none
Set-MailboxMessageConfiguration -id john.doe@domain.com -AutoAddSignature $false -AutoAddSignatureOnMobile $false -AutoAddSignatureOnReply $false -UseDefaultSignatureOnMobile $false

Mail tracing

NB: Sometimes this is easier in mail trace in EAC

# get messages sent to john from joe, from exactly 1 day ago until this very second
Get-MessageTrace -RecipientAddress john.doe@domain.com -StartDate ((get-date).AddDays(-1)) -EndDate (get-date) -SenderAddress joe.blogs@domain.com
# If the above only returns one result
Get-MessageTrace -RecipientAddress john.doe@domain.com -StartDate ((get-date).AddDays(-1)) -EndDate (get-date) -SenderAddress joe.blogs@domain.com | fl
# if it returns many results, you can adjust filter further or browse objects by using one of the below
Get-MessageTrace -RecipientAddress john.doe@domain.com -StartDate ((get-date).AddDays(-1)) -EndDate (get-date) -SenderAddress joe.blogs@domain.com | out-gridview -passthrough | fl

#To get the trace details
Get-MessageTrace -RecipientAddress john.doe@domain.com -StartDate ((get-date).AddDays(-1)) -EndDate (get-date) -SenderAddress joe.blogs@domain.com | get-messagetracedetail
#To expand the trace details
Get-MessageTrace -RecipientAddress john.doe@domain.com -StartDate ((get-date).AddDays(-1)) -EndDate (get-date) -SenderAddress joe.blogs@domain.com | get-messagetracedetail | fl

Searches:

# See previous searches (larger traces)
Get-HistoricalSearch
Get-HistoricalSearch | fl

# Start a new searches
Start-HistoricalSearch
     -EndDate <DateTime>
     -ReportTitle <String>
     -ReportType <HistoricalSearchReportType>
     -StartDate <DateTime>
     [-BlockStatus <String>]
     [-CompressFile <Boolean>]
     [-ConnectorType <String>]
     [-DeliveryStatus <String>]
     [-Direction <MessageDirection>]
     [-DLPPolicy <MultiValuedProperty>]
     [-EncryptionTemplate <String>]
     [-EncryptionType <String>]
     [-Locale <CultureInfo>]
     [-MessageID <MultiValuedProperty>]
     [-NetworkMessageID <MultiValuedProperty>]
     [-NotifyAddress <MultiValuedProperty>]
     [-OriginalClientIP <String>]
     [-RecipientAddress <MultiValuedProperty>]
     [-SenderAddress <MultiValuedProperty>]
     [-SmtpSecurityError <String>]
     [-TLSUsed <String>]
     [-TransportRule <MultiValuedProperty>]
     [-Url <String>]
     [<CommonParameters>]

# Example
Start-HistoricalSearch -ReportTitle "Fabrikam Search" -StartDate 1/1/2023 -EndDate 1/7/2023 -ReportType MessageTrace -SenderAddress michelle@fabrikam.com -NotifyAddress chris@contoso.com

# Stop
Stop-HistoricalSearch -JobId <<GUID>>

https://learn.microsoft.com/en-us/powershell/module/exchange/start-historicalsearch?view=exchange-ps

Temporarily increase mailbox size

ASSUMPTION!

This assumes you never give users their full mailbox in the first place.

Commands to increase space:

Set-Mailbox -id <<email@domain.com>> -ProhibitSendQuota <<Value>> -ProhibitSendReceiveQuota <<Value>>

# All our mailboxes are by default 40GB, so to increase to 45:
Set-Mailbox <<email@domain.com>> -ProhibitSendQuota 43GB -ProhibitSendReceiveQuota 45GB


# set mailbox sizses back to defaults afterwards:
Set-Mailbox -id <<email@domain.com>> -ProhibitSendReceiveQuota 40GB -ProhibitSendQuota 39GB -IssueWarningQuota 36GB

Make sure to lower mailbox sizes afterwards back to defaults

Archive Mailbox

enable archive mailbox

Enable-Mailbox -Identity mailbox -Archive

Turn on auto expanding archive (only use if licensed for exchange archive)

Enable-Mailbox -Identity user -AutoExpandingArchive

force older content to move to archive mailbox once available

Start-ManagedFolderAssistant -Identity <<email@domain.com>>

# Consider the below if doing in bulk. Use -whatif and -confirm to check (make sure you know how this works before doing it)
$Mailboxes = Get-Mailbox -ResultSize Unlimited -Filter {RecipientTypeDetails -eq "UserMailbox"}
$Mailboxes.Identity | Start-ManagedFolderAssistant

Make sure to lower mailbox sizes afterwards back to defaults

Mailbox Access Checks

Search what permissions are on a particular mailbox

# Search what permissions are on a particular mailbox
Get-MailboxPermission -Identity john.doe@domain.com

Queries against all mailboxes

The below queries, unless filtered run across all mailboxes. These queries may take some time to run.

Search if a particular personal has access to any mailboxes

# Search if a particular personal has access to any mailboxes
Get-Mailbox -ResultSize Unlimited | Get-MailboxFolderPermission -User john.doe@domain.com | ft User,Identity,AccessRights

Mailbox Access

From and More info: https://learn.microsoft.com/en-us/exchange/recipients-in-exchange-online/manage-permissions-for-recipients

Full Access

Add-MailboxPermission -Identity <MailboxIdentity> -User <DelegateIdentity> -AccessRights FullAccess -InheritanceType All
Remove-MailboxPermission -Identity <MailboxIdentity> -User <DelegateIdentity> -AccessRights FullAccess -InheritanceType All
# Remember: Only 1 <DelegateIdentity> at a time

# This example assigns the delegate Raymond Sam the Full Access permission to the mailbox of Terry Adams.
Add-MailboxPermission -Identity "Terry Adams" -User raymonds -AccessRights FullAccess -InheritanceType All

# This does the same but *without* Automapping
Add-MailboxPermission -Identity "Terry Adams" -User raymonds -AccessRights FullAccess -InheritanceType All -AutoMapping $false
# There is no way to adjust automapping. To change it you need to remove the mailbox permission then re-add it with the new setting

# To test it worked
Get-MailboxPermission <MailboxIdentity> | where {$_.AccessRights -like 'Full*'} | Format-Table User,Deny,IsInherited,AccessRights -Auto

https://learn.microsoft.com/en-au/powershell/module/exchangepowershell/add-mailboxpermission?view=exchange-ps
https://learn.microsoft.com/en-au/powershell/module/exchangepowershell/remove-mailboxpermission?view=exchange-ps
https://learn.microsoft.com/en-au/powershell/module/exchangepowershell/get-mailboxpermission?view=exchange-ps
https://learn.microsoft.com/en-us/troubleshoot/outlook/profiles-and-accounts/full-access-mailbox-not-automapped-outlook-profile

Send as

# This example assigns the Send As permission to the Printer Support group on the shared mailbox named Contoso Printer Support.
Add-RecipientPermission -Identity "Contoso Printer Support" -Trustee "Printer Support" -AccessRights SendAs

# the same as above but doesn't confirm - use with caution
Add-RecipientPermission -Identity "Contoso Printer Support" -Trustee "Printer Support" -AccessRights SendAs -confirm:$false

# To test it worked:
Get-RecipientPermission -Identity <MailboxIdentity> -Trustee <DelegateIdentity>

https://learn.microsoft.com/en-au/powershell/module/exchangepowershell/add-recipientpermission?view=exchange-ps
https://learn.microsoft.com/en-au/powershell/module/exchangepowershell/get-recipientpermission?view=exchange-ps

Send be behalf

# <Cmdlet> -Identity <MailboxOrGroupIdentity> -GrantSendOnBehalfTo <Delegates>
# This will reset whoever had the ability to send on behalf of Sean and only grant it to Holly
Set-Mailbox -Identity seanc@contoso.com -GrantSendOnBehalfTo hollyh

# This will add tempassistants to whoever can already send on behalf of Exec's shared mailbox
Set-Mailbox "Contoso Executives" -GrantSendOnBehalfTo @{Add="tempassistants@contoso.com"}

# This will reset whoever had the ability to send on behalf of PrinterSupport and only grant it to sarad
Set-DistributionGroup -Identity printersupport@contoso.com -GrantSendOnBehalfTo sarad

# This will only remove administrator
Set-DynamicDistributionGroup "All Employees" -GrantSendOnBehalfTo @{Remove="Administrator"}

More https://learn.microsoft.com/en-au/powershell/module/exchange/set-mailbox?view=exchange-ps

Shared Mailbox Sent Items settings

From https://www.slipstick.com/exchange/save-items-shared-mailbox-exchange-server-cmdlet/#:~:text=Cmdlet%20for%20Exchange%202013%20CU9%20and%20Office%20365

# To enable copying for emails sent as the shared mailbox:
Set-Mailbox <sharedmailboxname> -MessageCopyForSentAsEnabled $True

# To enable copying for emails sent on behalf of the shared mailbox:
Set-Mailbox <sharedmailboxname> -MessageCopyForSendOnBehalfEnabled $True

More https://learn.microsoft.com/en-us/powershell/module/exchange/set-mailbox?view=exchange-ps

Group stuff

AD Controlled Groups

Most of these commands don’t work for groups that are “directory backed” aka synced from on prem ad. This is mostly for Distribution Groups, Security Groups and Mail Enabled Security Groups.

Unified Groups (aka Microsoft 365 Groups)

https://learn.microsoft.com/en-au/powershell/module/exchangepowershell/add-unifiedgrouplinks?view=exchange-ps

Get-UnifiedGroup
Get-UnifiedGroupLinks
New-UnifiedGroup
Remove-UnifiedGroup
Remove-UnifiedGroupLinks
Set-UnifiedGroup
Undo-SoftDeletedUnifiedGroup\

Add-UnifiedGroupLinks -Identity "Legal Department" -LinkType Members -Links chris@contoso.com,michelle@contoso.com

MORE TBC

Distribution Groups

TBC

Mail Enabled Security Groups

TBC

Dynamic Groups

TBC

Searching for Exchange Transport Rule Changes

Not Inbox Rules

This more not looking for Inbox Rules. Transport rules are different to Inbox rules. Have a look into Get-InboxRule

Search-UnifiedAuditLog -StartDate 25/11/2024 -EndDate 27/11/2024 -Operations New-TransportRule, Set-TransportRule, Enable-TransportRule, Disable-TransportRule, Remove-TransportRule | Format-Table

Searching for Exchange Transport Connector Changes

Not Inbox Rules

This more not looking for Inbox Rules. Transport rules are different to Inbox rules. Have a look into Get-InboxRule

Search-UnifiedAuditLog -StartDate -StartDate 25/11/2024 -EndDate 27/11/2024 -Operations "New-InboundConnector","Set-InboundConnector","Remove-InboundConnector

Eseutil

TBC

Other References

PowerShell Commands
Microsoft365 Tips

  1. https://www.reddit.com/r/PowerShell/comments/yf07e3/comment/iu1bmh2/