https://security.microsoft.com/reportsubmission
This builds an exchange rule to take the names out the defender impersonation list and creates a rule
<#
.SYNOPSIS
Builds/updates an Exchange Online mail flow (transport) rule that quarantines
external mail impersonating your organization's "protected" VIP display names,
using the TargetedUsersToProtect list from your Defender for Office 365
Anti-Phishing policies.
.DESCRIPTION
This is a backstop for Defender's built-in impersonation protection: it
quarantines any external message whose 'From' header display name exactly
matches one of your protected VIPs' names, unless the message genuinely
came from that person's real mailbox address.
Logic:
1. Connects to Exchange Online (if not already connected).
2. Reads every ENABLED Anti-Phish policy and pulls its TargetedUsersToProtect
list (format: "Display Name;[email protected]", comma-separated entries).
3. Merges and de-duplicates the display names and email addresses across
all enabled policies.
4. Creates the transport rule if it doesn't exist, or updates it in place
if a rule with the same name already exists (conditions/exceptions are
refreshed to match the current protected-user list; other settings such
as Mode are left untouched on update unless you pass -Force).
5. The rule is created/left in AUDIT mode (Exchange calls this "Test" mode
under the hood; the admin center displays it as "Audit"). No mail is
actually quarantined while in this mode - only match events are logged.
Pass -Enforce to switch it to enforce mode instead.
.PARAMETER RuleName
Name of the transport rule to create/update.
Default: "Quarantine - External Sender Impersonating Protected Names"
.PARAMETER Enforce
Switch. If specified, sets the rule to Enforce mode instead of Audit/Test mode.
Omit this to keep the rule safely in audit-only mode.
.PARAMETER Priority
Rule priority (lower number = higher priority). Default: 3, matching the
example rule this script is modeled on. Adjust to fit your existing rule set.
.PARAMETER WhatIf
Preview the protected names/addresses and the rule that would be
created/updated, without making any changes in Exchange Online.
.EXAMPLE
.\New-ImpersonationQuarantineRule.ps1 -WhatIf
Shows what would happen without changing anything.
.EXAMPLE
.\New-ImpersonationQuarantineRule.ps1
Creates or updates the rule in Audit mode.
.EXAMPLE
.\New-ImpersonationQuarantineRule.ps1 -Enforce
Creates or updates the rule and sets it to Enforce mode (will actually quarantine mail).
.NOTES
Requires the ExchangeOnlineManagement module and an account with Exchange
Online / Security & Compliance admin permissions (e.g. Organization
Management or Security Administrator role).
Review the -WhatIf output before running for real, and review the rule in
the Exchange admin center after creation. Audit mode is intentionally the
default so you can check for false positives (e.g. legitimate external
senders who happen to share a display name with a protected VIP) before
switching to Enforce.
#>
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[string]$RuleName = "Quarantine - External Sender Impersonating Protected Names",
[switch]$Enforce,
[int]$Priority = 3
)
$ErrorActionPreference = "Stop"
function Ensure-ExchangeOnlineConnection {
$connected = $false
try {
$null = Get-ConnectionInformation -ErrorAction Stop
$connected = $true
} catch {
$connected = $false
}
if (-not $connected) {
Write-Host "Connecting to Exchange Online..." -ForegroundColor Cyan
if (-not (Get-Module -ListAvailable -Name ExchangeOnlineManagement)) {
throw "The ExchangeOnlineManagement module is not installed. Install it first with: Install-Module ExchangeOnlineManagement -Scope CurrentUser"
}
Import-Module ExchangeOnlineManagement -ErrorAction Stop
Connect-ExchangeOnline -ShowBanner:$false
} else {
Write-Host "Already connected to Exchange Online." -ForegroundColor DarkGray
}
}
function Get-ProtectedNamesAndAddresses {
<#
Pulls TargetedUsersToProtect from every ENABLED Anti-Phish policy and
returns a de-duplicated list of [pscustomobject]@{ DisplayName; Email }
#>
Write-Host "Retrieving enabled Anti-Phish policies..." -ForegroundColor Cyan
$policies = Get-AntiPhishPolicy | Where-Object { $_.Enabled -eq $true }
if (-not $policies -or $policies.Count -eq 0) {
Write-Warning "No enabled Anti-Phish policies were found. Nothing to build the rule from."
return @()
}
$protected = New-Object System.Collections.Generic.List[object]
foreach ($policy in $policies) {
Write-Host " Policy: $($policy.Identity)" -ForegroundColor DarkGray
$entries = $policy.TargetedUsersToProtect
if (-not $entries) { continue }
foreach ($entry in $entries) {
# Each entry is typically formatted as "Display Name;[email protected]"
$parts = $entry -split ';'
if ($parts.Count -ge 2) {
$name = $parts[0].Trim()
$email = $parts[1].Trim()
} else {
# Fallback: some tenants store just the display name or just the address
$name = $entry.Trim()
$email = $null
}
if ([string]::IsNullOrWhiteSpace($name)) { continue }
$protected.Add([pscustomobject]@{
DisplayName = $name
Email = $email
})
}
}
# De-duplicate by DisplayName+Email pair (case-insensitive)
$unique = $protected |
Group-Object { "$($_.DisplayName.ToLower())|$($_.Email.ToLower())" } |
ForEach-Object { $_.Group[0] }
return $unique
}
# --- Main ---
Ensure-ExchangeOnlineConnection
$protectedUsers = Get-ProtectedNamesAndAddresses
if ($protectedUsers.Count -eq 0) {
Write-Warning "No protected users found across enabled Anti-Phish policies. Exiting without changes."
return
}
$displayNames = $protectedUsers |
Select-Object -ExpandProperty DisplayName -Unique |
Where-Object { $_ }
$emailAddresses = $protectedUsers |
Select-Object -ExpandProperty Email -Unique |
Where-Object { $_ }
Write-Host "`nFound $($displayNames.Count) unique protected display name(s) and $($emailAddresses.Count) associated address(es):" -ForegroundColor Green
$protectedUsers | Sort-Object DisplayName | Format-Table DisplayName, Email -AutoSize
$modeDescription = if ($Enforce) { "Enforce (will actually quarantine matching mail)" } else { "Audit/Test (logs matches only, no mail is quarantined)" }
Write-Host "`nRule to be created/updated:" -ForegroundColor Green
Write-Host " Name : $RuleName"
Write-Host " Priority : $Priority"
Write-Host " Mode : $modeDescription"
Write-Host " Condition : 'From' header contains one of the protected display names"
Write-Host " AND sender is from outside the organization"
Write-Host " Exception : sender's address contains one of the protected users' real addresses"
Write-Host " Action : Deliver the message to the hosted quarantine"
if ($WhatIfPreference) {
Write-Host "`n-WhatIf specified: no changes were made in Exchange Online." -ForegroundColor Yellow
return
}
$existingRule = $null
try {
$existingRule = Get-TransportRule -Identity $RuleName -ErrorAction Stop
} catch {
$existingRule = $null
}
$ruleMode = if ($Enforce) { "Enforce" } else { "Test" } # "Test" mode = "Audit" in the admin center UI
$ruleParams = @{
Name = $RuleName
HeaderContainsMessageHeader = "From"
HeaderContainsWords = $displayNames
FromScope = "NotInOrganization"
ExceptIfFromAddressContainsWords = $emailAddresses
Quarantine = $true
Mode = $ruleMode
Priority = $Priority
RuleErrorAction = "Ignore"
Comments = "Backstop for Defender impersonation protection: quarantines external mail whose display name exactly matches a protected VIP name, even when Defender's own confidence scoring lets it through. Auto-generated/updated by New-ImpersonationQuarantineRule.ps1 from enabled Anti-Phish policies' TargetedUsersToProtect lists on $(Get-Date -Format 'yyyy-MM-dd')."
}
if ($existingRule) {
Write-Host "`nExisting rule '$RuleName' found - updating it in place." -ForegroundColor Cyan
if ($PSCmdlet.ShouldProcess($RuleName, "Update transport rule")) {
Set-TransportRule @ruleParams
Write-Host "Rule updated successfully." -ForegroundColor Green
}
} else {
Write-Host "`nNo existing rule named '$RuleName' - creating a new one." -ForegroundColor Cyan
if ($PSCmdlet.ShouldProcess($RuleName, "Create transport rule")) {
New-TransportRule @ruleParams
Write-Host "Rule created successfully." -ForegroundColor Green
}
}
Write-Host "`nDone. Review the rule in the Exchange admin center (Mail flow > Rules) before relying on it," -ForegroundColor Yellow
Write-Host "and keep it in Audit mode until you've confirmed there are no false positives." -ForegroundColor Yellow