This post is part of the Email Security Foundations series on MSDigest.net.
The mistakes that break SPF quietly
SPF usually does not fail in loud or obvious ways.
Mail does not bounce with a helpful error message. It just gets filtered, delayed, or rejected somewhere else. You only find out when someone eventually asks, “Did you get my email?”
These are the mistakes I see most often, and how to fix them.
Multiple SPF records
You can only have one SPF record per domain.
If you have two DNS TXT records starting with v=spf1, receiving servers return a PermError and treat SPF as a failure.
This happens more often than you would expect. Typically someone adds a new SPF record without checking whether one already exists.
You can check like this:
$domain = "yourdomain.com"
Resolve-DnsName -Name $domain -Type TXT |
Where-Object { $_.Strings -match "v=spf1" }If you get more than one result, you need to merge everything into a single SPF record.
Missing third‑party senders
Every service that sends email on behalf of your domain must be listed in your SPF record.
That includes marketing platforms, helpdesk systems, CRM tools, HR systems, and anything else that sends mail using your domain.
If a service is missing, its mail will fail SPF at the receiving end.
The fix is simple but sometimes tedious. Get the SPF include statement from each provider and add it to your record. Most vendors document this clearly. If they do not, ask their support team directly.
Using ~all instead of -all
~allis a soft fail.- The message is accepted but marked.
-allis a hard fail.- The message is rejected.
Many guides recommend starting with ~all, which is fine during initial setup. But leaving it there long term means SPF is not enforcing anything.
Once you are confident your SPF record covers all legitimate senders, switch to -all.
Validating SPF results in a message header
When troubleshooting SPF, pull the message header and look at the authentication results.
In Exchange Online, you can use message tracing to identify the message first:
Connect-ExchangeOnline
$trace = Get-MessageTrace `
-SenderAddress "[email protected]" `
-RecipientAddress "[email protected]" `
-StartDate (Get-Date).AddDays(-2) `
-EndDate (Get-Date)
Get-MessageTraceDetail `
-MessageTraceId $trace[0].MessageTraceId `
-RecipientAddress $trace[0].RecipientAddress |
Where-Object { $_.Event -eq "Receive" }
```
In the header look for a line like:
```
spf=fail (sender IP is 192.168.1.1) smtp.mailfrom=yourdomain.comIn the message header itself, look for a line like this:
spf=fail (sender IP is 192.168.1.1) smtp.mailfrom=yourdomain.comThe sender IP tells you exactly which server sent the message. Compare that IP to your SPF record to see why it failed.
A quick SPF health check
This script checks for the most common SPF issues and confirms that Exchange Online is covered:
$domain = "yourdomain.com"
$spf = Resolve-DnsName -Name $domain -Type TXT |
Where-Object { $_.Strings -match "v=spf1" }
if (-not $spf) {
Write-Host "No SPF record found" -ForegroundColor Red
}
elseif ($spf.Count -gt 1) {
Write-Host "Multiple SPF records found. This will cause a PermError." -ForegroundColor Red
}
else {
$record = $spf.Strings
Write-Host "SPF record: $record" -ForegroundColor Green
if ($record -match "spf.protection.outlook.com") {
Write-Host "Exchange Online include present" -ForegroundColor Green
}
else {
Write-Host "Exchange Online include missing" -ForegroundColor Yellow
}
if ($record -match "\-all") {
Write-Host "Hard fail (-all) configured" -ForegroundColor Green
}
elseif ($record -match "~all") {
Write-Host "Soft fail (~all). Consider switching to -all." -ForegroundColor Yellow
}
}Conclusion: SPF is simple until it breaks
Most SPF problems are not caused by complex attacks or advanced techniques. They are caused by small configuration mistakes that go unnoticed.
When SPF is broken, mail does not fail loudly. It just becomes unreliable. Some messages arrive, some do not, and troubleshooting turns into guesswork.
Getting SPF right is not about perfection. It is about consistency. One record, all legitimate senders included, lookup limits respected, and real enforcement in place.
A clean SPF setup gives you predictable behavior and reliable signals. Without that, everything built on top of it becomes harder to trust.
Fix the basics here, and you remove an entire class of avoidable problems before they ever turn into incidents.
Next up
Email Security Foundations #05: DKIM deep dive. Signing, selectors, and how verification actually works
Questions or edge cases from your own environment? Drop them in the comments.
1 thought on “Email Security Foundations #04: SPF mistakes, troubleshooting, and validation”
Comments are closed.