Why Your SPF Record is Failing
Fix SPF failures, PermErrors, and DNS lookup limits. Practical troubleshooting for IT admins who need their email to work.
Your emails are bouncing, landing in spam, or showing SPF failures in your DMARC reports. You know SPF is the problem. You just need to figure out why.
This guide covers the most common SPF failures, how to diagnose them, and how to fix them. No theory, just solutions.
How SPF Works (30-Second Version)
When someone receives an email claiming to be from your domain, their mail server checks your SPF record to see if the sending server was authorized.
The check works like this:
- Receiver looks up the TXT record at your domain
- Receiver finds your SPF record (starts with
v=spf1) - Receiver checks if the sending IP is listed or included
- Receiver returns a result: pass, fail, softfail, neutral, or error
If the check fails, your email might get rejected or flagged as spam. If the check errors out entirely (PermError), most receivers treat it as a fail.
The 10 DNS Lookup Limit
This is the number one cause of SPF failures. Your SPF record is allowed a maximum of 10 DNS lookups. Go over, and you get a PermError.
What Counts as a Lookup
| Mechanism | Counts? | Why |
|---|---|---|
include: | Yes | Requires DNS query to fetch the included record |
a | Yes | Requires DNS query for A record |
mx | Yes | Requires DNS query for MX records |
redirect= | Yes | Requires DNS query to follow redirect |
ip4: | No | IP address is right there, no lookup needed |
ip6: | No | Same as ip4 |
all | No | Not a lookup, just a default result |
The Hidden Problem: Nested Includes
Here’s where people get burned. When you add include:_spf.google.com, that’s one lookup. But Google’s SPF record includes other records, and those count against your limit too.
A typical Google Workspace SPF adds 3-4 lookups. Microsoft 365 adds 2-3. SendGrid adds 1-2. Stack a few services together and you’re over 10 before you know it.
How to Check Your Lookup Count
Option 1: MXToolbox
Go to mxtoolbox.com/spf.aspx, enter your domain, and look for the DNS lookup count in the results.
Option 2: Command Line
dig +short TXT yourdomain.com | grep spf
Then manually trace each include. Tedious, but thorough.
Option 3: Automated Monitoring
Verkh monitors your SPF record hourly and tracks your lookup count over time. You’ll get an alert before you hit the limit, not after your emails start bouncing.
How to Fix It
Remove services you no longer use. That old marketing platform you cancelled six months ago? Its include is still eating a lookup.
Use IP addresses instead of includes. If a service has stable IPs, you can replace include:service.com with ip4:xxx.xxx.xxx.xxx. This trades flexibility for lookup budget.
SPF flattening. Tools exist that resolve all your includes into IP addresses and generate a flat record. The downside: you need to update it when providers change their IPs. Services like AutoSPF or SPF Flattener handle this automatically.
Use subdomains. Send marketing email from mail.yourdomain.com with its own SPF record. Transactional email from notifications.yourdomain.com. Each subdomain gets its own 10-lookup budget.
Syntax Errors
SPF is picky about formatting. Small mistakes break everything.
Missing v=spf1
Every SPF record must start with v=spf1. No exceptions. This tells receivers it’s an SPF record and not just random text.
Wrong:
include:_spf.google.com ~all
Right:
v=spf1 include:_spf.google.com ~all
Multiple SPF Records
You can only have one SPF record per domain. If you have two, most receivers return a PermError.
This happens when:
- You add a new service and create a new record instead of updating the existing one
- Different team members add records without coordinating
- You migrate DNS providers and both old and new records exist
Check for duplicates:
dig +short TXT yourdomain.com | grep spf
If you see two lines starting with v=spf1, that’s your problem. Merge them into one record.
Invalid Mechanisms
Typos happen. These will break your SPF:
| Invalid | Valid |
|---|---|
include:sendgrid.com | include:sendgrid.net |
include: _spf.google.com (space) | include:_spf.google.com |
incude:service.com (typo) | include:service.com |
ip4: 192.168.1.1 (space) | ip4:192.168.1.1 |
Wrong Record Type
SPF records are TXT records. Some old documentation mentions SPF record types, but those are deprecated. Always use TXT.
~all vs -all
The mechanism at the end of your SPF record determines what happens when an IP isn’t explicitly authorized.
| Qualifier | Meaning | Receiver Action |
|---|---|---|
-all | Hard fail | Reject or spam folder |
~all | Soft fail | Accept but mark suspicious |
?all | Neutral | No opinion |
+all | Pass all | Everyone is authorized (never use this) |
Which Should You Use?
Use -all when:
- You’ve identified all your legitimate sending sources
- You’re confident your SPF record is complete
- You’re running DMARC at enforcement (quarantine or reject)
Use ~all when:
- You’re still setting up email authentication
- You’re not sure if you’ve captured all sending sources
- You want to monitor before enforcing
For DMARC to protect you properly, you want -all. Soft fail gives receivers wiggle room, which spoofers can exploit.
Provider-Specific Issues
Each email service has its own SPF requirements. Here are the most common problems and their fixes.
Google Workspace
Correct include:
include:_spf.google.com
Common mistakes:
- Using
include:google.com(wrong domain) - Using
include:gmail.com(that’s for Gmail, not Workspace) - Forgetting to add it after enabling Google Workspace
Full Google Workspace setup guide
Microsoft 365
Correct include:
include:spf.protection.outlook.com
Common mistakes:
- Using
include:outlook.com(wrong) - Using
include:microsoft.com(wrong) - Having both Exchange on-premises and M365 includes when you’ve fully migrated
Full Microsoft 365 setup guide
SendGrid
Correct include:
include:sendgrid.net
Common mistakes:
- Using
include:sendgrid.com(wrong TLD) - Not waiting for DNS propagation after adding the record
Mailchimp
Correct include:
include:servers.mcsv.net
Common mistakes:
- Using
include:mailchimp.com(wrong domain) - Forgetting that Mailchimp acquired Mandrill, which has different SPF
SPF Passes But DMARC Fails
This confuses people. SPF passed. Why did DMARC fail?
The answer is alignment. DMARC doesn’t just check whether SPF passed. It checks whether the domain that passed SPF matches the From header domain.
Example:
- Email From header:
[email protected] - Envelope sender (Return-Path):
[email protected] - SPF check: Passes for sendgrid.net
- DMARC alignment: Fails because sendgrid.net ≠ yourcompany.com
To fix this, you need to configure your sending service to use your domain in the envelope sender. Most ESPs call this “custom return path” or “branded return path.”
Alternatively, set up DKIM signing with your domain. If DKIM passes and aligns, DMARC passes even if SPF doesn’t align.
Debugging Your SPF Record
Step 1: Check the Record Exists
dig +short TXT yourdomain.com | grep spf
You should see exactly one line starting with v=spf1.
Step 2: Count Lookups
Use MXToolbox or a similar tool. If you’re at 10 or over, that’s your problem.
Step 3: Verify Syntax
Look for:
- Record starts with
v=spf1 - No spaces after colons in mechanisms
- All include domains are spelled correctly
- Record ends with
~allor-all
Step 4: Test with Real Email
Send a test email to a Gmail account. Open the email, click the three dots, and select “Show original.” Look for the SPF result in the Authentication-Results header.
Step 5: Check DMARC Reports
DMARC aggregate reports tell you exactly which IPs are failing SPF and why. They’re XML files, which isn’t fun to read manually.
Verkh parses these reports automatically and shows you which sources are failing SPF, whether they’re legitimate services that need to be added to your record, or unauthorized senders you should ignore.
Common Scenarios
”I added the include but SPF still fails”
DNS propagation. Changes can take up to 48 hours to propagate globally. Check with a tool that queries multiple DNS servers worldwide.
Caching. Your local DNS resolver might have the old record cached. Try flushing your DNS cache or testing from a different network.
Wrong domain. Double-check you added the record to the right domain. If your email is [email protected], the SPF record goes on mail.company.com, not company.com.
”SPF passed yesterday but fails today”
Provider changed their IPs. If you hardcoded IP addresses instead of using includes, the provider might have added new sending IPs.
Someone modified the record. Check your DNS change history. Another team member might have edited the record.
You added a new service. That new service pushed you over the 10-lookup limit.
”Different results from different receivers”
DNS propagation in progress. Not all receivers have the updated record yet.
Record too long. Some DNS providers truncate TXT records over 255 characters. The record needs to be split into multiple strings within a single TXT record.
Receiver-specific quirks. Some receivers are stricter than others about SPF evaluation.
Ongoing Monitoring
SPF isn’t set-and-forget. Your record can break when:
- You add a new email service
- A provider changes their infrastructure
- Someone on your team edits DNS without understanding the impact
- A nested include adds more lookups
Checking manually every week gets old. Verkh monitors your SPF record continuously and alerts you when something changes or breaks. You’ll know about problems before your customers start complaining about missing emails.
Check your SPF record now with Verkh — free for one domain.
Quick Reference
Valid SPF Record Template
v=spf1 include:_spf.google.com include:sendgrid.net include:servers.mcsv.net -all
SPF Results
| Result | Meaning |
|---|---|
| Pass | Sender is authorized |
| Fail | Sender is not authorized |
| SoftFail | Sender is probably not authorized |
| Neutral | No statement about sender |
| PermError | Record is broken, can’t evaluate |
| TempError | Temporary DNS issue, try again |
Lookup Costs by Provider
| Provider | Typical Lookups |
|---|---|
| Google Workspace | 3-4 |
| Microsoft 365 | 2-3 |
| SendGrid | 1-2 |
| Mailchimp | 2-3 |
| Amazon SES | 1 |
| Salesforce | 2-3 |
Add yours up. Stay under 10.
Ready to implement this?
Verkh helps you monitor DMARC, identify issues, and reach enforcement. Start free.
Start Free