Exchange Online · PowerShell 7.6
Inbox rules that forward or redirect mail
Which inbox rules forward, forward as attachment or redirect mail, and which of them send it to a domain outside your accepted domains? A common sign of a compromised mailbox.
Script
#Requires -Modules ExchangeOnlineManagement
# Inbox rules that forward or redirect mail, with any destination domains outside the accepted domains. Read-only.
param(
[switch]$ExternalOnly
)
Connect-ExchangeOnline -ShowBanner:$false
$acceptedDomains = @(Get-AcceptedDomain | ForEach-Object { $_.DomainName.ToString().ToLowerInvariant() })
$mailboxes = Get-EXOMailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox, SharedMailbox
$rules = foreach ($mailbox in $mailboxes) {
Get-InboxRule -Mailbox $mailbox.UserPrincipalName |
Where-Object { $_.ForwardTo -or $_.ForwardAsAttachmentTo -or $_.RedirectTo } |
ForEach-Object {
$targets = @(@($_.ForwardTo) + @($_.ForwardAsAttachmentTo) + @($_.RedirectTo) | Where-Object { $_ } | ForEach-Object { "$_" })
$externalDomains = @($targets |
ForEach-Object { [regex]::Matches($_, '@([A-Za-z0-9.-]+\.[A-Za-z]{2,})') } |
ForEach-Object { $_.Groups[1].Value.ToLowerInvariant() } |
Where-Object { $acceptedDomains -notcontains $_ } |
Sort-Object -Unique)
[pscustomobject]@{
Mailbox = $mailbox.UserPrincipalName
Rule = $_.Name
Enabled = $_.Enabled
Targets = $targets -join '; '
ExternalDomains = $externalDomains -join ', '
}
}
}
$rules |
Where-Object { -not $ExternalOnly -or $_.ExternalDomains } |
Sort-Object @{ Expression = { [bool]$_.ExternalDomains }; Descending = $true }, Mailbox, Rule
Checked automatically against Microsoft's published cmdlet reference. KBY hasn't run it in your tenant; run it in a test environment first.
Reading the output
- Checks the ForwardTo, ForwardAsAttachmentTo and RedirectTo actions of user and shared mailbox rules. Mailbox-level forwarding is a separate setting; the external forwarding script covers it.
- ExternalDomains lists the domains of SMTP addresses in the rule's targets that aren't exactly an accepted domain. Internal recipients are usually shown by name or Exchange address with no SMTP domain, so they never count as external.
- Pass -ExternalOnly to show only rules with an external target. Hidden rules aren't read.
- Makes one Get-InboxRule call per mailbox, so it takes a while in large organisations.
- ExchangeOnlineManagement 3.10.0 and later require PowerShell 7.6 when run in PowerShell 7 (Windows PowerShell 5.1 is unaffected), per the module release notes.
Sources
The Microsoft reference page for every cmdlet the script calls, plus the API and product pages behind each permission and caveat.
Connect-ExchangeOnline (ExchangePowerShell)Get-AcceptedDomain (ExchangePowerShell)Get-EXOMailbox (ExchangePowerShell)Get-InboxRule (ExchangePowerShell)New-InboxRule: the ForwardTo, ForwardAsAttachmentTo and RedirectTo actionsFind the permissions required to run any Exchange cmdletAbout the Exchange Online PowerShell module: release notesForEach-Object (Microsoft.PowerShell.Core)Where-Object (Microsoft.PowerShell.Core)Sort-Object (Microsoft.PowerShell.Utility)