To check outbound spam policies in Exchange Online, read the policies with Get-HostedOutboundSpamFilterPolicy and the rules that say who each custom policy covers with Get-HostedOutboundSpamFilterRule. Look first at the automatic forwarding setting: Automatic can mean On or Off depending on the organisation, so Microsoft advises setting On or Off instead.
| Method | Best fit |
|---|---|
| PowerShell | A CSV of every policy with its scope, forwarding mode and sending limits. |
| Admin centre | Reading 1 policy's protection settings in the Defender portal. |
| Altivane | Recommended for security reviews, with forwarding and alert-only limits rated in a workbook. |
Before you start
Use an account that can read the policies. Microsoft lists Global Reader, Security Reader and View-Only Organization Management for read-only access; Organization Management and Security Administrator can also change them.
Know how they apply. The default policy covers every sender and can't be turned off. A custom policy applies to the users, groups or domains its rule names, in priority order, and the first policy that applies to a sender is the only one used. A sending limit of 0 means the service default. The examples read and export; they change no policy or rule.
Option 1
Check outbound spam policies with PowerShell
Install the module once, then connect and export each policy with the rule that scopes it.
# Install once, if the module is not already installed.
Install-Module ExchangeOnlineManagement -Scope CurrentUser$ErrorActionPreference = 'Stop'
Connect-ExchangeOnline -ShowBanner:$false
try {
$rules = @{}
foreach ($rule in Get-HostedOutboundSpamFilterRule) {
$rules["$($rule.HostedOutboundSpamFilterPolicy)"] = $rule
}
$report = @(foreach ($policy in Get-HostedOutboundSpamFilterPolicy) {
$rule = $rules["$($policy.Name)"]
$scope = @()
$state = 'No rule'
if ($policy.IsDefault) {
$scope = @('Everyone')
$state = 'Always on'
} elseif ($rule) {
$scope = @($rule.From) + @($rule.FromMemberOf) + @($rule.SenderDomainIs)
$state = $rule.State
}
[pscustomobject]@{
Policy = $policy.Name
Default = $policy.IsDefault
State = $state
Priority = if ($rule) { $rule.Priority } elseif ($policy.IsDefault) { 'Lowest' }
AppliesTo = ($scope -ne $null) -join '; '
AutoForwarding = $policy.AutoForwardingMode
ExternalPerHour = $policy.RecipientLimitExternalPerHour
InternalPerHour = $policy.RecipientLimitInternalPerHour
PerDay = $policy.RecipientLimitPerDay
WhenLimitReached = $policy.ActionWhenThresholdReached
}
})
$report | Sort-Object Default, Priority |
Export-Csv -Path './outbound-spam-policies.csv' -NoTypeInformation -Encoding utf8
Write-Output "$($report.Count) outbound spam policies exported."
} finally {
Disconnect-ExchangeOnline -Confirm:$false
}The CSV has 1 row for each policy, custom policies in priority order and the default last. Look for AutoForwarding set to On or Automatic, and for WhenLimitReached set to Alert, which only notifies when a mailbox reaches its limit; BlockUserForToday is the default and BlockUser is Microsoft's recommended setting. A custom policy with No rule applies to no one. The tenant always has the default policy, so the list is never empty.
Check the exceptions of 1 custom policy
Reconnect with Connect-ExchangeOnline, then read the rule's conditions and exceptions.
# Run while connected to Exchange Online. Replace the example policy name.
Get-HostedOutboundSpamFilterRule -Identity 'Contoso Executives' |
Select-Object Name, State, Priority, From, FromMemberOf, SenderDomainIs, ExceptIfFromOption 2
Review outbound spam policies in the Defender portal
- Sign in to the Microsoft Defender portal for the correct tenant.
- Go to Email & collaboration > Policies & rules > Threat policies > Anti-spam. The list shows each policy's Status, Priority and Type; outbound ones are Anti-spam outbound policy (Default) and those of type Custom outbound spam policy.
- Select a policy's row, away from its check box, to open its details.
- Read the message limits, the restriction on users who reach a limit and Automatic forwarding rules, then close the pane without choosing Edit.
This suits checking 1 or 2 policies. It does not suit a record you keep or compare month to month, since each policy's settings are in its own pane.
Option 3 ยท Recommended for security reviews
Run Altivane's Outbound Spam Policies report
- Open Altivane and choose the tenant.
- Run the Outbound Spam Policies report for Exchange Online.
- Open the Excel workbook and read the table of the same name, in the order the policies apply: Automatic Forwarding, Applies to, Exceptions, Priority, Rule State, the 3 recipient limits, When Limit Reached, Notify and Copy Suspicious Mail to, each with a Status and Reason.
- Run the Remote Domains report next, since a remote domain can block forwarding too.
Altivane rates only the policies that apply to someone. Forwarding On in the default policy is a Warning, because every mailbox can then forward automatically to external addresses; On in a custom policy, Automatic, and limits that only alert are marked Review. Applies to names the users, groups and domains of each rule as addresses, and the default policy reads as everyone not covered by another.
Contact usCommon questions
Why is forwarding blocked when the policy says On?
When one setting allows external forwarding and another blocks it, Microsoft says the block typically wins. A remote domain or a mail flow rule can still stop it. To read those settings, see how to check remote domain settings in Exchange Online.
What does the sender see when forwarding is off?
A non-delivery report with the code 5.7.520, saying the organisation does not allow external forwarding. Forwarding between people inside the organisation is not affected by these policies.
Who is told when someone is blocked for sending spam?
Microsoft's default alert policies notify Global Administrators. Microsoft is retiring the policy's own notify setting and recommends the alert policy User restricted from sending email instead.
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.