Overview
Email remains the primary attack vector for enterprise compromises, with over 90% of cyberattacks beginning with a phishing email. Exchange Online provides extensive security controls, but many tenants leave critical configurations at default — leaving gaps attackers actively exploit.
Who Should Use This Guide:
- Exchange Online administrators hardening email security
- Security engineers implementing email protection
- MSP technicians configuring client M365 tenants
- Compliance teams ensuring email meets regulatory requirements
Requirements
# Install Exchange Online Management module
Install-Module ExchangeOnlineManagement -Force
# Connect to Exchange Online
Connect-ExchangeOnline -UserPrincipalName admin@example.comPart 1: Domain Authentication (SPF, DKIM, DMARC)
SPF Record
Add to your domain's DNS:
v=spf1 include:spf.protection.outlook.com -all
| Qualifier | Meaning |
|---|---|
-all | Hard fail — reject unauthorized senders (recommended) |
~all | Soft fail — mark as suspicious |
?all | Neutral — no policy |
Enable DKIM
# Get DKIM configuration
Get-DkimSigningConfig -Identity example.com
# Enable DKIM signing
Set-DkimSigningConfig -Identity example.com -Enabled $true
# Get CNAME records to add to DNS
Get-DkimSigningConfig -Identity example.com |
Select-Object Selector1CNAME, Selector2CNAMEAdd the two CNAME records to your DNS as instructed.
DMARC Record
Add to DNS as a TXT record for _dmarc.example.com:
# Start with monitoring (p=none)
v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; pct=100
# After reviewing reports, move to quarantine
v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com; pct=100
# Final state: reject (full enforcement)
v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com; pct=100
Verify Authentication
# Check SPF
Resolve-DnsName example.com -Type TXT | Where-Object { $_.Strings -like "*spf*" }
# Check DMARC
Resolve-DnsName _dmarc.example.com -Type TXT
# Check DKIM
Get-DkimSigningConfig | Select-Object Domain, Enabled, StatusPart 2: Anti-Spam Configuration
Inbound Anti-Spam Policy
# Configure strict anti-spam settings
Set-HostedContentFilterPolicy -Identity Default `
-SpamAction MoveToJmf `
-HighConfidenceSpamAction Quarantine `
-PhishSpamAction Quarantine `
-HighConfidencePhishAction Quarantine `
-BulkSpamAction MoveToJmf `
-BulkThreshold 5 `
-QuarantineRetentionPeriod 30 `
-EnableEndUserSpamNotifications $true `
-EndUserSpamNotificationFrequency 1 `
-MarkAsSpamBulkMail On `
-InlineSafetyTipsEnabled $true `
-TestModeAction NoneOutbound Anti-Spam Policy
# Configure outbound spam filtering
Set-HostedOutboundSpamFilterPolicy -Identity Default `
-RecipientLimitExternalPerHour 500 `
-RecipientLimitInternalPerHour 1000 `
-RecipientLimitPerDay 1000 `
-ActionWhenThresholdReached BlockUser `
-AutoForwardingMode Off `
-NotifyOutboundSpam $true `
-NotifyOutboundSpamRecipients "security@example.com"Part 3: Mail Flow Rules (Transport Rules)
Block External Auto-Forwarding
New-TransportRule -Name "Block External Auto-Forwarding" `
-FromScope InOrganization `
-MessageTypeMatches AutoForward `
-SentToScope NotInOrganization `
-RejectMessageReasonText "External email forwarding is blocked by security policy." `
-RejectMessageEnhancedStatusCode "5.7.1" `
-Priority 0Warn on External Emails
New-TransportRule -Name "External Email Warning Banner" `
-FromScope NotInOrganization `
-SentToScope InOrganization `
-PrependSubject "[EXTERNAL] " `
-ApplyHtmlDisclaimerLocation Prepend `
-ApplyHtmlDisclaimerText "<div style='background:#FFEB3B;padding:10px;margin-bottom:10px;border:1px solid #F57F17'><b>CAUTION:</b> This email originated from outside the organization. Do not click links or open attachments unless you recognize the sender.</div>"Block Executable Attachments
New-TransportRule -Name "Block Dangerous Attachments" `
-AttachmentExtensionMatchesWords @(
"exe","bat","cmd","com","vbs","js","wsf","wsh",
"ps1","psm1","psd1","scr","hta","cpl","reg"
) `
-RejectMessageReasonText "Executable attachments are blocked by security policy." `
-RejectMessageEnhancedStatusCode "5.7.1" `
-Priority 1Prevent Spoofing of Internal Domains
New-TransportRule -Name "Block External Domain Spoofing" `
-FromScope NotInOrganization `
-SenderDomainIs (Get-AcceptedDomain).DomainName `
-RejectMessageReasonText "Email rejected: sender domain spoofing detected." `
-RejectMessageEnhancedStatusCode "5.7.1" `
-Priority 2Part 4: Mailbox Security
Disable POP3 and IMAP (Org-Wide)
# Disable POP3 and IMAP for all mailboxes
Get-CASMailboxPlan | Set-CASMailboxPlan -ImapEnabled $false -PopEnabled $false
# Disable for existing mailboxes
Get-CASMailbox -ResultSize Unlimited |
Set-CASMailbox -ImapEnabled $false -PopEnabled $falseAudit Mailbox Forwarding Rules
# Find all mailbox forwarding rules
Get-Mailbox -ResultSize Unlimited |
Where-Object { $_.ForwardingSmtpAddress -or $_.ForwardingAddress } |
Select-Object DisplayName, ForwardingSmtpAddress, ForwardingAddress,
DeliverToMailboxAndForward
# Find all inbox rules that forward externally
$Mailboxes = Get-Mailbox -ResultSize Unlimited
foreach ($Mailbox in $Mailboxes) {
$Rules = Get-InboxRule -Mailbox $Mailbox.UserPrincipalName -ErrorAction SilentlyContinue
$ForwardRules = $Rules | Where-Object {
$_.ForwardTo -or $_.ForwardAsAttachmentTo -or $_.RedirectTo
}
if ($ForwardRules) {
Write-Host "=== $($Mailbox.DisplayName) ===" -ForegroundColor Yellow
$ForwardRules | Select-Object Name, ForwardTo, RedirectTo
}
}Restrict Mailbox Delegation
# Audit who has Full Access to other mailboxes
Get-Mailbox -ResultSize Unlimited | Get-MailboxPermission |
Where-Object {
$_.IsInherited -eq $false -and
$_.User -ne "NT AUTHORITY\SELF" -and
$_.AccessRights -contains "FullAccess"
} | Select-Object Identity, User, AccessRightsPart 5: Admin Audit and Monitoring
Enable Admin Audit Logging
# Verify admin audit log is enabled
Get-AdminAuditLogConfig | Select-Object AdminAuditLogEnabled, LogLevel
# Enable if not already on
Set-AdminAuditLogConfig -AdminAuditLogEnabled $true -AdminAuditLogAgeLimit 365Monitor High-Risk Activities
Set up alerts in Microsoft 365 Defender for:
| Activity | Why It Matters |
|---|---|
| New inbox forwarding rule | Data exfiltration indicator |
| Mail flow rule creation | Could bypass security controls |
| Mailbox permission changes | Unauthorized access |
| Admin role assignments | Privilege escalation |
| External sharing changes | Data loss risk |
Verification Checklist
- SPF record published with
-all(hard fail) - DKIM enabled and verified for all domains
- DMARC progressing toward
p=reject - Anti-spam policies set to strict configuration
- External auto-forwarding blocked
- External email warning banner active
- Dangerous attachment types blocked
- Domain spoofing transport rule active
- POP3 and IMAP disabled org-wide
- No unauthorized forwarding rules found
- Admin audit logging enabled
- Alert policies configured for high-risk activities