SPF Failure Troubleshooting Guide

James Bowers IIJames Bowers II
21 min read

SPF Failure Troubleshooting Guide: Common SPF Errors & Fixes That Actually Work

Meta description (≤155 chars): SPF failing? This troubleshooting guide walks through every common SPF error — multiple records, 10-lookup limit, syntax, forwarding — with step-by-step fixes.

Focus keyphrase: SPF failure troubleshooting

Slug: /information-security-guides/spf-failure-troubleshooting-guide

Suggested featured image alt text: "Technician troubleshooting SPF failures on a DNS console — iO™ SPF Failure Troubleshooting Guide"


If your email is bouncing, landing in spam, or your DMARC reports are lighting up with red spf=fail lines, chances are something in your SPF record is broken. And here's the frustrating part — SPF doesn't tell you why it broke. It just fails.

This guide fixes that. We'll walk through every common SPF failure one by one — what it looks like, why it happens, and exactly how to resolve it. No guessing, no "try this and see," no vague advice. Just the actual fix.

By the time you're done, you'll know how to decode any SPF error message, you'll understand the quirks that trip up almost everyone (yes, even the 10-lookup limit), and you'll have a record that passes — cleanly — across every mailbox provider that matters.

Let's dig in.


Key Takeaways

  • Most SPF failures fall into a handful of predictable buckets — multiple records, too many DNS lookups, syntax errors, missing senders, and forwarding. Knowing which one you're dealing with is half the fix.

  • Only one SPF TXT record is allowed per domain. A second one isn't "extra coverage" — it's an automatic permerror, and everything authenticates as if SPF didn't exist.

  • The 10 DNS lookup limit is real, and it's strict. Nested include: chains blow it up faster than you'd think. SPF flattening or delegation fixes it.

  • A fail in your DMARC report isn't always a spoofer — forwarding, third-party senders you forgot about, and typos cause just as many legitimate failures.

  • Always start monitoring with ~all (SoftFail), then tighten to -all (HardFail) once you've verified every sender. Jumping straight to -all is how good mail gets rejected.

  • Use a checker, not a guess. Our free SPF Checker will show you exactly which mechanism is failing and why — no DNS console gymnastics required.


Table of Contents

  1. First, Confirm It's Actually an SPF Problem

  2. Error 1: Multiple SPF Records on One Domain

  3. Error 2: Too Many DNS Lookups (The 10-Lookup Limit)

  4. Error 3: Syntax Errors and Typos

  5. Error 4: Wrong Qualifier — ~all vs -all vs +all

  6. Error 5: Missing Senders and Forgotten Third-Party Services

  7. Error 6: Email Forwarding Breaks SPF

  8. Error 7: Wrong Record Type (SPF vs TXT)

  9. Error 8: Wrong Host / Wrong Subdomain

  10. Error 9: DNS Propagation Delays

  11. Error 10: permerror vs temperror — What They Actually Mean

  12. Error 11: SoftFail Quietly Hurting Deliverability

  13. Final Validation Checklist

  14. FAQ


First, Confirm It's Actually an SPF Problem

Before you go rewriting DNS records, make sure SPF is actually the thing that's failing. Email authentication has three moving parts — SPF, DKIM, and DMARC — and any of them can cause a delivery issue that feels like SPF.

Open a failing message and look at the full headers. You're hunting for a line like:

Authentication-Results: mx.google.com;
  spf=fail (google.com: domain of ... does not designate ... as permitted sender)
  dkim=pass header.d=yourdomain.com
  dmarc=fail (p=REJECT) header.from=yourdomain.com

If the spf= line says fail, softfail, permerror, temperror, or none, you're in the right place. If it says pass and your problem is somewhere else (DKIM alignment, DMARC policy, blocklisting), SPF isn't your issue — and forcing changes to your record may make things worse.

Not sure what you're looking at? Our companion guide, What Does It Mean if SPF Fails?, breaks down each result code in plain English. And if you're getting a "no SPF record found" message specifically, jump over to the No SPF Record Found Fix Guide — that one's a different animal.

Got a genuine SPF failure? Keep reading.

Suggested image: screenshot of an email header showing spf=fail highlighted — alt: "Email header showing SPF fail result — how to read SPF errors in Gmail source view"


Error 1: Multiple SPF Records on One Domain

What it looks like: Your authentication result returns permerror, or a checker tells you "more than one SPF record found."

Why it happens: SPF (per RFC 7208) allows exactly one SPF record per domain. No exceptions. When a receiving server finds two, it doesn't pick the "better" one — it throws up its hands and returns permerror. Your mail authenticates as if SPF didn't exist at all.

This one is surprisingly common. Someone adds Microsoft 365, a second person adds Google Workspace, a marketer adds Mailchimp — each in their own separate TXT record — and before long the domain has three SPF strings, all trying to be the source of truth.

The fix: Merge every SPF string into a single TXT record.

Broken (two records):

v=spf1 include:spf.protection.outlook.com ~all
v=spf1 include:_spf.google.com include:mailgun.org ~all

Fixed (one record):

v=spf1 include:spf.protection.outlook.com include:_spf.google.com include:mailgun.org ~all

One v=spf1 prefix. One all mechanism at the end. Everything else goes in between.

How to verify: Run your domain through the iO™ SPF Checker — it flags duplicate records instantly. Or query directly:

dig TXT yourdomain.com +short | grep "v=spf1"

If you see more than one line starting with v=spf1, you still have a problem.


Error 2: Too Many DNS Lookups (The 10-Lookup Limit)

What it looks like: permerror again — but this time the diagnostic message mentions "too many DNS lookups," "lookup limit exceeded," or a void lookup limit.

Why it happens: Every include:, a, mx, ptr, exists, and redirect mechanism in your SPF record counts as a DNS lookup. RFC 7208 caps the total at 10 lookups — and that includes nested lookups inside every include: you're pulling in.

Here's the sneaky part. An innocent-looking record like this:

v=spf1 include:spf.protection.outlook.com include:_spf.google.com include:servers.mcsv.net include:mailgun.org include:_spf.salesforce.com include:sendgrid.net ~all

…looks like 6 lookups. It's not. Each of those include: targets resolves to its own SPF record, and some of them chain out to 3 or 4 more lookups each. The total can easily hit 15 or 20.

And when it exceeds 10? permerror. Every message fails SPF, even from your legitimate senders.

The fix — three options, in order of preference:

  1. Remove services you're not actually using. Audit your vendors. If you stopped using Mailchimp two years ago, its include doesn't need to be there.

  2. Use SPF flattening. A flattening service or tool resolves every nested include: once and replaces them with the underlying ip4: / ip6: mechanisms. IPs don't count toward the lookup limit.

  3. Delegate with subdomains. Move a heavy sender (say, your marketing platform) to a subdomain like marketing.yourdomain.com with its own SPF record. Because DMARC alignment is checked against the envelope sender, this works for most campaign email.

A word of caution on flattening: If your upstream provider (say, Microsoft 365) rotates its IPs, your flattened record goes stale. Either use a flattening service that monitors and updates automatically, or recheck your record monthly.

How to verify: Counters in most SPF checkers display the exact lookup count. You want 10 or fewer, with some headroom for future additions.

Suggested image: visual of nested SPF includes blowing past the 10-lookup limit — alt: "SPF 10 DNS lookup limit diagram showing nested include mechanisms"


Error 3: Syntax Errors and Typos

What it looks like: permerror, a diagnostic like "invalid SPF record," or an unexpected mechanism in your checker's output. Sometimes it just silently fails without firing a clear error.

Why it happens: SPF is pickier than it looks. A single stray colon, space, or character will invalidate the whole record. Common culprits include:

  • Missing v=spf1 prefix (or a typo like v=spf 1)

  • Extra spaces inside mechanisms — e.g., include: spf.protection.outlook.com (space after the colon)

  • Using include= instead of include:

  • Wrapping the record in quotes when your DNS provider already adds them (resulting in double-quoted strings)

  • Trailing commas, semicolons, or plus signs from copy-paste

  • Missing all mechanism at the end

  • Using hostnames where IPs are required, or the reverse

The fix: Rewrite the record from scratch using the canonical format:

v=spf1 [mechanisms separated by single spaces] ~all

Example:

v=spf1 ip4:203.0.113.25 include:_spf.google.com include:mailgun.org ~all

One space between each mechanism. No trailing spaces. No quotes (unless your DNS host specifically requires them and then only the ones it asks for). The final mechanism is an all variant.

How to verify: Run the record through a validator — iO™ SPF Checker will parse it the way real receivers do and tell you exactly where it broke. If you're more of a command-line person:

dig TXT yourdomain.com +short

Compare the returned string character-by-character against what you intended. A single rogue character is all it takes.


Error 4: Wrong Qualifier — ~all vs -all vs +all

What it looks like: Email isn't outright bouncing, but your DMARC reports show spf=softfail for legitimate senders, or — worse — spf=pass for senders you didn't authorize.

Why it happens: The last mechanism in an SPF record tells receivers what to do with messages from IPs that aren't explicitly listed. Four qualifiers are possible, and they mean very different things:

QualifierMeaningTypical Use+allPass anythingNever use this. It makes your SPF record meaningless.?allNeutralTesting only. No receiver actually blocks on it.~allSoftFail"Probably not legit, but don't hard-reject." Good for rollout and monitoring.-allHardFail"Reject it." The correct end state for a mature SPF record.

+all is the catastrophic one. It tells receivers every IP on the internet is authorized to send from your domain. Spoofers love it. If you've ever seen a record ending in +all, change it now — that's not a configuration, it's an open invitation.

If you're new to the difference between SoftFail and HardFail, we go deep on it in SPF Hard Fail vs Soft Fail.

The fix:

  • Start with ~all while you're discovering and adding senders. You'll see failures in DMARC reports without those messages getting rejected, which gives you a safe window to spot anything you missed.

  • Move to -all once you've monitored for at least two to four weeks and every legitimate sender authenticates cleanly.

  • Never use +all. No exceptions. No "just for testing." No.

How to verify: Check the last mechanism of your record in a DNS query. Then confirm the behavior matches your policy intent — if your DMARC is set to p=reject but SPF ends in ~all, you're not as strict as you think you are. Well, you are, but only because DMARC is pulling the weight.


Error 5: Missing Senders and Forgotten Third-Party Services

What it looks like: Random SPF failures for mail you know is legitimate — a CRM campaign, a billing notification, a helpdesk reply — all sending From: you@yourdomain.com and failing SPF at the receiver.

Why it happens: You probably have more third-party senders than you realize. Every SaaS tool that sends email on your behalf — Mailchimp, HubSpot, Salesforce, Intercom, Zendesk, QuickBooks, DocuSign, Calendly, your website contact form, your HR platform — needs its sending infrastructure authorized in your SPF record. If it's not listed, the receiver has no way to know the mail is legitimate. It fails.

This is the single most common reason SPF "breaks" after it was previously working: someone onboarded a new tool and nobody updated DNS.

The fix — build a complete sender inventory:

  1. Pull at least two weeks of DMARC aggregate reports. They list every IP sending on your domain's behalf, whether authorized or not. If you're not collecting DMARC reports yet, our iO™ DMARC solution handles the ingestion and decodes them into plain English.

  2. Ask department heads. Sales uses X. Marketing uses Y. Support uses Z. Finance, legal, and ops all have their own tools. Get the full list.

  3. Look up each vendor's recommended SPF include. Most providers publish an official mechanism in their documentation — use theirs, not something you found on a random forum.

  4. Add each one to your single SPF record, mind the 10-lookup limit, and deploy.

Provider quick reference (for the common ones):

ServiceSPF MechanismMicrosoft 365include:spf.protection.outlook.comGoogle Workspaceinclude:_spf.google.comMailguninclude:mailgun.orgSendGridinclude:sendgrid.netMailchimp (Mandrill)include:servers.mcsv.netSalesforceinclude:_spf.salesforce.comHubSpotinclude:_spf.hubspot.comZendeskinclude:mail.zendesk.comAmazon SESinclude:amazonses.com

How to verify: After publishing, send test emails through each service and check the Authentication-Results header on arrival. All should show spf=pass.

Suggested image: checklist of common third-party senders needing SPF authorization — alt: "Third-party email sender inventory for SPF authorization — Mailchimp, HubSpot, Salesforce, SendGrid"


Error 6: Email Forwarding Breaks SPF

What it looks like: Mail you send to a user at one domain gets forwarded to their address at another — and arrives with spf=fail. Same sender, same content, just forwarded once. Now it's failing.

Why it happens: SPF checks the sending IP against the domain of the envelope (return-path) sender. When a mailbox forwards a message without rewriting the return-path, the forwarding server's IP is what the next receiver sees — and that IP is almost certainly not in your SPF record. So SPF fails, legitimately, even though the message is legitimate.

This isn't a bug. It's how SPF was designed. Which is exactly why SPF alone is not enough, and why DKIM + DMARC exist.

The fix — it's a layered one:

  1. Publish DKIM. DKIM signs the message content with a cryptographic key, and the signature survives forwarding. A DMARC policy only needs one of SPF or DKIM to align and pass, so DKIM handles the forwarded cases SPF can't.

  2. Enable SRS (Sender Rewriting Scheme) on your forwarding servers. SRS rewrites the envelope sender so the forwarder takes responsibility for SPF. Most modern mail platforms (Microsoft 365, Google Workspace, iCloud+) do this automatically on forwards. Self-hosted forwarders may need it enabled.

  3. Tune your DMARC policy thoughtfully. If you jump to p=reject without DKIM working cleanly, forwarded legitimate mail gets rejected. Go through p=quarantine first, watch reports, then lock it down.

For the full picture on how these three standards work together, see What is SPF Email, DKIM, and DMARC?.

How to verify: Send a test email to a forwarding address. Inspect headers at the final destination — you want dkim=passand DMARC pass even when SPF shows fail. That's SPF + DKIM working as designed.


Error 7: Wrong Record Type (SPF vs TXT)

What it looks like: You published an SPF record, but checkers report "no SPF record found" or your mail is returning spf=none.

Why it happens: Back in the early SPF days, DNS defined a dedicated record type — simply SPF (RFC 4408). That type was deprecated in 2014. Today, SPF records must be published as TXT records. Some DNS providers still offer an SPFrecord type in their UI, and if you pick it, receivers often won't read the record at all.

The fix: Publish your SPF as a TXT record. The value starts with v=spf1. If your DNS host has an "SPF" record type option, ignore it — it's a relic.

Correct setup:

  • Record type: TXT

  • Host: @ (or your apex domain — see next error for subdomain nuance)

  • Value: v=spf1 include:spf.protection.outlook.com ~all

  • TTL: 3600 (or whatever your default is)

How to verify:

dig TXT yourdomain.com +short

You should see the record returned. If dig TXT returns nothing but dig SPF does, you published the wrong type — fix it.

For more on this specific error path, we cover it step-by-step in No SPF Record Found: Easy Fix Guide.


Error 8: Wrong Host / Wrong Subdomain

What it looks like: Your mail from you@yourdomain.com passes, but mail from you@mail.yourdomain.com or notifications@yourdomain.com (sent via a service using a subdomain) fails with spf=none.

Why it happens: SPF records are per-domain, and subdomains don't inherit from the apex. If you publish an SPF record at yourdomain.com but your actual sending happens from mail.yourdomain.com, receivers query mail.yourdomain.com — find nothing — and return spf=none.

Another common trip point: publishing at the wrong host field. In most DNS UIs, @ means the apex (yourdomain.com) and mail (unqualified) means mail.yourdomain.com. Type the wrong one and your record lands in the wrong place.

The fix:

  1. Identify your actual sending domain. Look at the envelope sender (return-path), not the friendly From:. If you use a subdomain like bounce.yourdomain.com or mail.yourdomain.com, that's where SPF needs to live.

  2. Publish SPF for every sending domain and subdomain. If your marketing platform sends from em.yourdomain.com, publish an SPF record at that subdomain.

  3. Double-check the host field. Enter @ for apex, or the exact subdomain label for anything else. Your DNS provider should show you the full hostname as you edit.

We have a dedicated walk-through on the setup side in How to Setup SPF.

How to verify: Query each sending domain/subdomain independently:

dig TXT yourdomain.com +short
dig TXT mail.yourdomain.com +short

Each should return its own valid SPF record. If one returns nothing, publish it there.


Error 9: DNS Propagation Delays

What it looks like: You made an SPF change an hour ago, but some receivers still see the old record (or no record). Intermittent spf=fail / spf=pass depending on the receiving server.

Why it happens: DNS changes aren't instant. The time it takes for a new record to propagate depends on your record's TTL (Time To Live) — the maximum age recursive resolvers cache the old value for. If your TTL was 86400 (24 hours) when the old record was cached, resolvers may keep serving the stale value for up to a full day after you publish the change.

The fix:

  1. Be patient. Most propagation completes within an hour for short-TTL records and up to 24–48 hours for longer ones.

  2. Lower TTL before you plan to change. If you know a change is coming, reduce TTL to 300 (5 minutes) a day ahead. Then make the edit. Afterwards, you can raise TTL back.

  3. Flush your local resolver cache if you're testing from your own machine. (ipconfig /flushdns on Windows; sudo dscacheutil -flushcache on macOS.)

How to verify: Query from multiple global resolvers to see the actual published value, not your own cached version:

dig TXT yourdomain.com @8.8.8.8 +short    # Google
dig TXT yourdomain.com @1.1.1.1 +short    # Cloudflare
dig TXT yourdomain.com @9.9.9.9 +short    # Quad9

Once all three match your new record, propagation is effectively complete.


Error 10: permerror vs temperror — What They Actually Mean

What it looks like: Your DMARC reports or headers show spf=permerror or spf=temperror.

Why it happens: These are two different failure modes people frequently confuse.

  • permerror (permanent error) = something is wrong with your record. Multiple SPF records, 10-lookup limit exceeded, syntax errors, malformed mechanisms. Until you fix the record, it'll keep erroring every time.

  • temperror (temporary error) = something transient prevented the lookup from completing — DNS timeout, upstream resolver hiccup, transient network issue. It may clear on its own without any change from you.

The fix:

  • If it's permerror: Walk through Errors 1 through 4 above. One of them is your culprit. Fix the record, wait for propagation, re-test.

  • If it's temperror: Wait and re-test after 15–30 minutes. If it persists for hours across multiple checkers and resolvers, suspect your DNS host. Contact them. If it's intermittent, it's usually fine — receivers will retry.

How to verify: Re-run the SPF check from multiple locations (our SPF Checker queries from independent resolvers). Persistent error on all of them = permerror land. Clean on some, erroring on others = temperror land.


Error 11: SoftFail Quietly Hurting Deliverability

What it looks like: Mail isn't being outright rejected, but open rates are slipping, more messages are landing in spam, and DMARC reports show a lot of spf=softfail results on your own legitimate senders.

Why it happens: SoftFail (~all) tells receivers: "This sender probably isn't authorized, but don't hard-reject." Most receivers honor that by quietly routing to spam or applying a reputation penalty. Over time — especially if your domain's reputation is already middling — this compounds.

SoftFail is great during rollout. It's not great as a permanent setting, because it leaves a gray area that spoofers can exploit and that receivers interpret inconsistently.

The fix:

  1. Audit your SoftFails in DMARC reports. If they're all from senders you do recognize, add them to your SPF record.

  2. Once every legitimate sender authenticates with spf=pass, tighten to -all. This converts any unauthorized sender to a hard SPF failure — which, combined with DMARC, gives you real spoofing protection.

  3. Don't skip the monitoring step. Going from a loose record straight to -all without verifying is how you accidentally reject your own payroll notifications.

How to verify: After switching to -all, monitor DMARC aggregate reports for a week. If legitimate mail is still showing spf=pass, you're good. If anything shifts to fail, you missed a sender — add it and retest.


Final Validation Checklist

Before you close this tab, run through the list. If every box checks, your SPF is in good shape.

  • [ ] Exactly one v=spf1 TXT record at each sending domain and subdomain

  • [ ] Total DNS lookups (including nested includes) are 10 or fewer

  • [ ] No syntax errors — single spaces between mechanisms, no stray characters, no quotes unless your DNS host requires them

  • [ ] Last mechanism is ~all (monitoring phase) or -all (enforcement phase) — never +all

  • [ ] Every third-party sender you actively use is included

  • [ ] DKIM is published and aligned for forwarding scenarios

  • [ ] Record is a TXT type (not a deprecated SPF type)

  • [ ] Host field points to the correct apex or subdomain

  • [ ] Propagation verified across at least three public resolvers

  • [ ] DMARC policy and SPF policy are consistent with each other

  • [ ] Monitoring is in place so you'll see future drift before it bites you

A great way to automate most of that monitoring is to ingest DMARC aggregate reports continuously. That's exactly what iO™ DMARC does — it parses the XML reports you'd otherwise have to decode manually and surfaces the exact senders, IPs, and failure reasons in a readable dashboard.


Frequently Asked Questions

1. Why is my SPF record failing even though I set it up correctly? The most common reasons are a second SPF record left over from an earlier setup, a third-party sender you forgot to authorize, or the 10 DNS lookup limit being exceeded. Walk through Errors 1, 2, and 5 above in that order — one of them will almost always be the cause.

2. What's the difference between spf=fail and spf=permerror? spf=fail means SPF processed correctly but the sending IP wasn't authorized. spf=permerror means SPF couldn't even finish processing — your record is broken (usually multiple records, syntax, or lookup limit). fail is a policy outcome; permerror is a configuration bug.

3. Can I have two SPF records if one is for a subdomain? Yes — each domain and subdomain is treated independently. You can (and often should) publish a record at yourdomain.com and a separate one at mail.yourdomain.com. What you can't have is two SPF records at the same hostname.

4. How long does it take for SPF changes to take effect? Most changes propagate within an hour, but the old record can linger in resolver caches up to the TTL you had set before the change — commonly 24 hours. Lower your TTL before you make changes to minimize the window.

5. Does SPF protect me from all email spoofing? No. SPF only validates the envelope sender (return-path). Spoofers can still put your domain in the From: header of a message sent from elsewhere. For real header-level protection, you need SPF and DKIM and DMARC — and DMARC needs to be at p=quarantine or p=reject.

6. Should I use ~all or -all at the end of my SPF record? Use ~all while you're discovering senders and monitoring — typically two to four weeks. Once every legitimate sender is authenticated, tighten to -all. Never +all.

7. Why does my forwarded email fail SPF? Because the forwarding server's IP isn't in your SPF record. This is expected behavior, not a bug. The fix is to deploy DKIM so your message carries a signature that survives forwarding, and rely on DMARC's "SPF or DKIM must align" rule.

8. Do I need to update SPF if I add a new email service? Yes. Any new platform that sends mail on your behalf must be added to your SPF record before receivers will authenticate its messages. Check the vendor's docs for their official include:value.


Still Stuck?

Email authentication is one of those things that's 90% straightforward and 10% infuriating — and the 10% tends to be whatever specific edge case is affecting your domain right now.

If you've worked through this guide and SPF is still misbehaving, try these in order:

  1. Run your domain through the iO™ SPF Checker for an immediate read on what's broken.

  2. Start ingesting DMARC aggregate reports with iO™ DMARC so you can see exactly which senders are failing and why.

  3. If you need hands-on help — or you want an audit of your entire email authentication posture (SPF, DKIM, DMARC, BIMI) — reach out to us at 844-InputOut (467-8868) or drop a message through inputoutput.com.

A clean SPF record is the foundation. Get it right, keep it monitored, and the rest of your email program gets easier from there.

BE BETTER. BE iO.™

James Bowers II

James Bowers II

Chief Security & Compliance Architect

James Bowers II is the founder of Input Output, where he helps businesses make sense of cybersecurity, compliance, and information security without drowning in jargon or generic advice. With a focus on practical security policies, risk assessments, audits, penetration testing, and vCISO support, James works with organizations to build stronger, smarter security programs that protect the business and satisfy real-world compliance requirements.