SPF Record Errors for Microsoft 365 Business Email: The Admin Fix Guide (2026 Updated Guide)
Quick answer
Most SPF problems with Microsoft 365 come down to five things: the include:spf.protection.outlook.com mechanism is missing, you have multiple SPF records on the same domain (which breaks the protocol), you’ve accumulated so many third-party include: mechanisms that you’ve blown past the 10-DNS-lookup limit, you’re running hybrid Exchange and forgot to add your on-prem mail server’s IP, or you’re using ~all (soft fail) when you should be using -all (hard fail). The fixes are straightforward, but the diagnosis isn’t intuitive — SPF failures rarely show up as obvious errors. They show up as your email going to spam at the recipient and you having no idea why.
Before you start
You’ll need access to your DNS provider’s management console — wherever your domain’s DNS records are hosted. That might be your domain registrar (GoDaddy, Namecheap, Cloudflare, etc.), or a separate DNS hosting provider. You don’t make SPF changes in Microsoft 365; SPF lives entirely in DNS.
You’ll also need to know every system that sends email as your domain. Not just Microsoft 365 — also any marketing platform (Mailchimp, HubSpot, Brevo), any transactional email service (SendGrid, Postmark, AWS SES), your CRM, your accounting software if it sends invoices, your support ticket system, your payroll provider, and any internal scripts or copiers that send mail. Anything that puts your domain in the From address needs to be in your SPF record. If it isn’t, mail from that source will fail SPF and end up in spam (or be rejected outright at strict providers).
You don’t need any Microsoft 365 admin role to read SPF state — you just need DNS lookup tools. To make changes you need access to DNS, plus the willingness to wait an hour for propagation before declaring the change “done”.
What SPF actually is, briefly
SPF (Sender Policy Framework) is a DNS TXT record that lists the IP addresses and hostnames authorised to send email as your domain. When a recipient mail server gets an email claiming to be from you@yourdomain.com, it can look up your domain’s SPF record, check the sending server’s IP against the list, and decide whether to accept the message.
Two important details that catch people out:
-
SPF checks the envelope sender (the “Return-Path” or “MAIL FROM” address), not the visible From header. A spoofer can pass SPF by sending from their own domain with their domain’s SPF record while putting your domain in the visible From. SPF alone doesn’t stop From-header spoofing — that’s what DMARC is for.
-
SPF lives in a single DNS TXT record at your domain root. You can have only one. Multiple SPF records on the same domain cause a permanent error (
PermError) and break authentication entirely.
These two facts are the source of more than half of all real SPF problems.
How to read your current SPF record
From any command line:
nslookup -type=txt yourdomain.com
Or use a web tool like MXToolbox’s SPF lookup. You’re looking for a TXT record that starts with v=spf1 and ends with some variant of all.
A typical Microsoft 365-only record looks like this:
v=spf1 include:spf.protection.outlook.com -all
If you don’t see one at all, that’s your problem and the fix is to add one. If you see two records both starting with v=spf1, that’s also your problem and the fix is to merge them into a single record.
The five real causes of SPF errors
Cause 1: The Microsoft 365 include is missing
If you’re sending mail through Exchange Online but your SPF record doesn’t include spf.protection.outlook.com, your outgoing Microsoft 365 email will fail SPF at every recipient. The mechanic is precisely as described: Microsoft sends from a large pool of shared IPs that change over time. Listing those IPs directly is unmaintainable, so Microsoft publishes a list via the include mechanism. Your record points at theirs.
The minimum SPF record for a domain that sends only through Microsoft 365 is:
v=spf1 include:spf.protection.outlook.com -all
If your record is missing the include, add it. If your record exists but doesn’t include Outlook’s spf.protection mechanism, the simple fix is to add it inside the existing record (don’t create a second record). If you genuinely don’t send any email through Microsoft 365, you don’t need this — but if Outlook in Microsoft 365 is sending mail as your domain, you do.
Cause 2: Multiple SPF records on the same domain
This is the silent killer. SPF doesn’t allow multiple TXT records starting with v=spf1 on the same hostname. If you have two — say, one that came pre-loaded by your domain registrar with a generic v=spf1 ~all, and one you added later for Microsoft 365 — recipient mail servers will see the second record, get confused, and return a PermError. PermError doesn’t mean “no SPF”; it means “broken SPF”, which on most mail providers is treated as authentication failure.
The fix is to consolidate into a single record. Take all the include: mechanisms from both records, plus any direct ip4: or ip6: mechanisms, and combine them into one. Example:
v=spf1 include:spf.protection.outlook.com include:_spf.google.com include:servers.mcsv.net -all
Then delete the duplicate record from your DNS.
Cause 3: You’ve exceeded the 10-DNS-lookup limit
Each include: mechanism in your SPF record causes a recursive DNS lookup. The SPF specification (RFC 7208) caps the total number of lookups at 10 per evaluation. If your record requires more than 10 lookups, you hit PermError again — and most mail providers treat PermError as authentication failure.
Real-world example: a tenant with Microsoft 365 (1 lookup, but spf.protection.outlook.com itself includes others, so effectively 3-4), Mailchimp (1), HubSpot (3), DocuSign (1), Salesforce (2), and Zendesk (2) — already over 10 lookups, even though the record looks reasonable.
The diagnostic tool you want is MXToolbox’s SPF lookup, which counts the recursive lookups and tells you when you’re over. Most other SPF checkers show the count too.
The fixes, in order of preference:
- Drop senders you no longer use. Old marketing platforms accumulate. Audit. Anything that hasn’t sent mail in 12 months can probably go.
- Use SPF flattening. This means resolving the recursive includes into raw IP4/IP6 mechanisms inside your own record. It avoids the 10-lookup limit. The cost is that when a third-party provider changes their IPs, your record breaks until you flatten again. Several services automate this (PowerDMARC, EasyDMARC, Valimail) — they monitor the upstream IPs and update your record dynamically. Flattening manually is doable but maintenance-heavy.
- Use a subdomain split. Marketing platforms send as
mail.yourdomain.com, transactional platforms astx.yourdomain.com, the main domain stays clean for human Microsoft 365 mail. Each subdomain has its own SPF record with its own 10-lookup budget. This is the architecturally correct answer for organisations with serious volume from many senders.
Cause 4: Hybrid Exchange and the on-prem IP
If you’re running a hybrid Exchange setup (on-prem Exchange plus Exchange Online), and you have on-prem mail servers that send mail as your domain through Exchange Online Protection, those on-prem IPs need to be in your SPF record. The Microsoft 365 include alone covers Exchange Online’s outbound IPs but not your on-prem hand-off if mail leaves directly from on-prem.
Add the on-prem server’s public IP explicitly:
v=spf1 ip4:203.0.113.42 include:spf.protection.outlook.com -all
Cloud-only tenants don’t have this issue. It’s specifically a hybrid problem.
Cause 5: Soft fail (~all) versus hard fail (-all)
This is the position-taking part. Your SPF record ends with one of two qualifiers:
~all(soft fail) — “any sender not listed in this record probably isn’t authorised; mark the message as suspicious but don’t reject it”-all(hard fail) — “any sender not listed in this record is definitely not authorised; reject the message outright”
Microsoft’s Defender for Office 365 documentation explicitly recommends -all once you have your sender inventory accurate, with DKIM signing in place, and with DMARC configured. The argument goes: SPF soft-fail is “training wheels” — useful while you’re discovering all your legitimate senders, dangerous to leave on permanently. With major mailbox providers tightening sender authentication requirements, a domain still publishing ~all is publishing a weaker signal than its competitors who use -all.
The counter-argument is that ~all gives you a softer landing if you’ve forgotten a legitimate sender — a missed sender’s mail goes to spam rather than getting rejected. That’s true but it’s a self-defeating reason to stay on ~all indefinitely. If you don’t trust your sender inventory enough to use -all, you don’t trust your sender inventory, and the answer is to fix your inventory rather than weaken your policy.
The position: Start a new domain at ~all for the first 30 days while you watch DMARC reports for unauthorised sources. After 30 days of clean reports, switch to -all. Domains that have been live for years with stable senders should be on -all. The “compensating control” argument from rating agencies — that DMARC at p=quarantine or p=reject mitigates the risk of ~all — is valid but operational, not an excuse to skip the upgrade.
Note: DMARC treats both ~all and -all as SPF failures for evaluation purposes. The difference is what individual receivers do with messages that fail. With DMARC at p=reject, the difference largely disappears at receivers that honour DMARC; with no DMARC, the difference is meaningful.
How to diagnose SPF failures from message headers
When a specific email goes to spam or gets rejected, the diagnostic information is in the message headers. The Authentication-Results header tells you what happened:
Authentication-Results: spf=fail (sender IP is 203.0.113.42)
smtp.mailfrom=yourdomain.com;
dkim=none;
dmarc=fail (p=reject)
The relevant fields:
spf=pass/spf=fail/spf=softfail/spf=neutral/spf=permerror/spf=temperrorsmtp.mailfrom=— the envelope sender domain that was checked
permerror means your SPF record is broken (multiple records, exceeded lookup limit, syntax error). Fix the record. temperror means the lookup itself failed (DNS server unreachable). Usually transient. fail means the sending IP genuinely isn’t in your record. softfail means the same but with a softer recommendation (you’re using ~all).
In Microsoft 365 specifically, you can run an Exchange message trace: Exchange admin centre → Mail flow → Message trace, find the message, and view the original headers. The same Authentication-Results header is there.
The right SPF record for the most common scenarios
Cloud-only Microsoft 365, no third-party senders:
v=spf1 include:spf.protection.outlook.com -all
Microsoft 365 plus one major third-party (e.g. Mailchimp):
v=spf1 include:spf.protection.outlook.com include:servers.mcsv.net -all
Hybrid Exchange with on-prem at 203.0.113.42:
v=spf1 ip4:203.0.113.42 include:spf.protection.outlook.com -all
Microsoft 365 plus several senders, but staying under 10 lookups:
v=spf1 include:spf.protection.outlook.com include:_spf.google.com include:sendgrid.net -all
These are templates. The right record for your tenant depends on your actual sender list. When in doubt, audit.
What to do when SPF passes but mail still goes to spam
SPF passing isn’t the same as deliverability. Even with valid SPF, your mail can land in spam if:
- DKIM isn’t configured (most major recipients now require DKIM in addition to SPF)
- DMARC isn’t published (or is published at p=none with no reporting endpoint)
- Your domain has a weak reputation
- Your message content trips spam filters
- You’re sending from a shared IP pool with bad neighbours
SPF is necessary but not sufficient. Once SPF is solid, the next steps are DKIM signing for your domain and a DMARC record. Both are best practice, both are increasingly being treated as required by major recipients (Gmail and Yahoo enforced this in 2024 for bulk senders), and both deserve their own configuration guides — which we’ll cover in dedicated articles.
Related errors
- (DKIM and DMARC articles linked here when published in Phase 2)
- Shared mailbox not showing in Outlook — sometimes presents as deliverability issues that look SPF-related but aren’t
Official references
- Microsoft Learn: Set up SPF to identify valid email sources for your Microsoft 365 domain
- Microsoft Learn: Email authentication in Microsoft Defender for Office 365
- RFC 7208: Sender Policy Framework (SPF) for Authorizing Use of Domains in Email
FAQ
Can I have more than one SPF record on my domain?
No. Multiple TXT records that start with v=spf1 cause SPF evaluation to return PermError, which most receivers treat as authentication failure. You must consolidate into a single record.
How long does an SPF change take to propagate?
DNS propagation is typically 15 minutes to a few hours, depending on the TTL set on the existing record and on how aggressively recipient mail servers cache. Plan for an hour minimum and check propagation with a tool like MXToolbox before declaring the change live.
My SPF record uses ?all (neutral). Is that fine?
It’s allowed but not recommended. ?all tells receivers “I have no opinion about senders not in this list”, which is functionally close to having no SPF at all and is treated as a weak signal by reputation systems. Move to ~all or -all.
I exceeded the 10-DNS-lookup limit. Will any of my mail be delivered?
Some, but unpredictably. Receivers that handle PermError as a hard fail will reject your mail. Receivers that ignore SPF or treat PermError as neutral will accept it. The result is variable deliverability, which is worse than a clear pass or clear fail because you can’t tell which messages are getting through.
Should I include my own server IP in SPF if I send through Exchange Online?
No, unless you have on-prem servers that send mail as your domain. Microsoft 365 outbound is covered by include:spf.protection.outlook.com. Adding individual user device IPs or your office static IP doesn’t help because Microsoft 365 doesn’t send from those IPs.
Will SPF alone stop someone spoofing my domain?
No. SPF protects the envelope sender (Return-Path), not the visible From header. A spoofer can pass SPF by sending from their own domain with their own SPF record while putting your domain in the visible From. DMARC closes this gap by checking that the From and Return-Path align. SPF without DMARC is incomplete.
My SPF record uses mx (the mx mechanism). Is that bad?
Not necessarily. mx includes the IPs of your domain’s MX records (your inbound mail servers), which is reasonable if those servers also send outbound mail. For a Microsoft 365-only tenant where Exchange Online handles outbound, mx is unnecessary — the Microsoft include covers it — and mx adds an extra DNS lookup against your 10-lookup budget. Drop it unless you specifically need it.
Can I test SPF before deploying it?
Yes. Add the new record, but keep the old one alongside under a different test subdomain (e.g. _spftest.yourdomain.com). Or use the SPF qualifier ? (neutral) on the all mechanism for a few days while you watch DMARC reports for unauthorised sources. Switch to -all once you’re confident.