Home Guides Email AuthenticationSPF Permerror: What Causes It, How to Diagnose It, and How to Fix It
Email Authentication9 minUpdated 2026-03-01

SPF Permerror: What Causes It, How to Diagnose It, and How to Fix It

When a receiving mail server evaluates your SPF record and hits an error that cannot be retried — not a temporary DNS failure, but a permanent structural problem — it returns `permerror`. In the vast majority of cases, **SPF permerror** has exactly one cause: your SPF record requires more than 10 DNS lookups to fully evaluate, violating the hard limit defined in [RFC 7208](https://datatracker.ietf.org/doc/html/rfc7208). The result is that your legitimate outbound mail fails SPF authentication as definitively as a forged message would. This guide covers what permerror means, why the 10-lookup limit exists, how to trace and count your own lookups step by step, and all three realistic fix approaches — from the simple to the operationally demanding.

What SPF Permerror Means

SPF defines several possible evaluation results. permerror (permanent error) means the receiving server encountered a condition that makes the SPF record unparseable or unevaluable in a way that cannot be resolved by retrying. It is distinct from temperror (temporary error), which indicates a transient DNS failure that might succeed on a retry.

The most common permerror triggers, per RFC 7208:

  • Exceeding 10 DNS-querying mechanisms — the lookup count limit is reached during evaluation
  • More than one SPF record published at the same domain — two TXT records both starting with v=spf1 produce an instant permerror
  • Exceeding 2 void lookups — mechanisms that return zero addresses (e.g., an a: mechanism pointing to a domain with no A record) count as void lookups; more than 2 is a permerror
  • Syntax errors — a malformed record that cannot be parsed

The lookup limit is by far the most common cause. When a receiving server hits this during evaluation, it treats the SPF check as a permanent failure — meaning the sending IP receives no SPF authentication benefit from your record. Depending on the receiver's policy and your DMARC configuration, this can result in mail being quarantined or rejected.

⚠️ Warning: SPF permerror is a silent failure for many senders. Some receiving servers return neutral rather than treating permerror as a hard fail — meaning your mail may still be delivered, but without SPF passing. Under DMARC, an SPF permerror counts as a non-pass, and if DKIM also fails to align, the DMARC check fails. Check your DMARC aggregate reports to see how many messages are failing SPF due to permerror.

Why the 10-Lookup Limit Exists (RFC 7208)

RFC 7208 — the specification that defines SPF — imposes a hard limit of 10 DNS lookups per SPF evaluation. The rationale is resource protection: SPF evaluation happens on every inbound SMTP connection at receiving mail servers. If SPF records could require arbitrary numbers of DNS lookups, a single malicious or poorly configured SPF record could cause a receiving server to perform hundreds of DNS queries per incoming message, creating a denial-of-service vector.

The 10-lookup limit counts only mechanisms that require DNS resolution to evaluate:

MechanismLookup Cost
include:domain1 (plus all lookups required by the included record, recursively)
a or a:domain1
mx or mx:domain1 per MX hostname that must be resolved (can be multiple)
ptr:domain1 per PTR lookup (deprecated — avoid)
exists:domain1
redirect=domain1 (replaces the entire record)
ip4:x.x.x.x0 — no DNS lookup needed
ip6:x::x0 — no DNS lookup needed
all0 — no DNS lookup needed

The critical detail: include: lookups are recursive. include:_spf.google.com costs 1 lookup for the initial fetch, plus however many lookups Google's own SPF record requires. Google's SPF record itself includes further sub-records, each requiring additional lookups. A single include:_spf.google.com may consume 3–4 of your 10-lookup budget depending on how Google's record resolves at the time of evaluation.

How to Count Your Current SPF Lookups

This is the diagnosis step. You need to trace every include: recursively and count the total DNS lookups the full evaluation requires.

Step 1: Retrieve your SPF record

Code
# Fetch your current SPF record
dig TXT example.com +short | grep "v=spf1"

# Example output:
# "v=spf1 include:_spf.google.com include:spf.protection.outlook.com include:sendgrid.net include:mail.zendesk.com ~all"

Step 2: List every DNS-querying mechanism

From the example record above, the top-level mechanisms that require DNS lookups are:

  1. include:_spf.google.com → 1 lookup + sub-lookups
  2. include:spf.protection.outlook.com → 1 lookup + sub-lookups
  3. include:sendgrid.net → 1 lookup + sub-lookups
  4. include:mail.zendesk.com → 1 lookup + sub-lookups

That's already 4 lookups before any sub-records are examined.

Step 3: Resolve each included record and count its lookups

Code
# Resolve each included domain
dig TXT _spf.google.com +short
dig TXT spf.protection.outlook.com +short
dig TXT sendgrid.net +short
dig TXT mail.zendesk.com +short

Each of these may contain further include: directives of their own. Trace every one recursively until you reach only ip4:, ip6:, or all mechanisms — those cost 0 lookups.

Common ESP lookup costs

Email Service ProviderTop-level include:Typical total lookup cost
Google Workspaceinclude:_spf.google.com3–4 lookups
Microsoft 365include:spf.protection.outlook.com2–3 lookups
SendGridinclude:sendgrid.net2 lookups
Mailchimp / Mandrillinclude:servers.mcsv.net1–2 lookups
Mailguninclude:mailgun.org2 lookups
Salesforce / Pardotinclude:_spf.salesforce.com3–4 lookups
Zendeskinclude:mail.zendesk.com2 lookups
HubSpotinclude:_spf.hubspot.com2 lookups
Postmarkinclude:spf.mtasv.net1–2 lookups
Amazon SESinclude:amazonses.com2–3 lookups

A record containing Google Workspace + Microsoft 365 + SendGrid + Zendesk already totals approximately 9–13 lookups — easily over the limit. Adding any further service pushes most organisations well past 10.

Use the SPF Checker for automated counting

Rather than tracing every sub-record manually, use our SPF Checker to automatically count the total lookup depth for your domain. It recursively resolves every include: and flags records that are at or over the 10-lookup limit.

You can also retrieve the raw TXT record for any domain using DNS Lookup to inspect included records one layer at a time.

Fix Option 1 — Remove Redundant include: Directives

This is always the first step — and often sufficient on its own. Before reaching for flattening or macros, audit every include: in your record against your actual sending infrastructure.

Questions to ask for each include: directive:

  • Does this service still send email on behalf of this domain?
  • When was the last time we sent through this provider?
  • Is this a test/staging service that shouldn't be in the production SPF record?
  • Do we have a duplicate — e.g., two different include: directives that cover the same sending IPs?

Common redundant entries found in audits:

  • Former email marketing platforms the organisation switched away from 2+ years ago
  • Transactional email services replaced by a different provider
  • include: directives for services that now send via a shared platform already covered by another include:
  • Development or staging environments incorrectly added to production SPF
Code
# Check each included domain — when did you last use this service?
dig TXT _spf.outgoingdomain.com +short

# If you're uncertain, check mail logs for sends through that provider
# Remove any include: for services you're not actively using

After removing all genuinely unused include: directives, re-count your lookups. If you're back under 10, you're done — no flattening needed.

Fix Option 2 — SPF Flattening (Replacing include: with IP Ranges)

If removing redundant entries doesn't bring you under 10 lookups, the next approach is SPF flattening: resolving every include: down to its constituent IP ranges and replacing the include: directives with explicit ip4: and ip6: mechanisms.

Since ip4: and ip6: cost 0 lookups, a fully flattened SPF record requires only 0 DNS lookups regardless of how many IP ranges it contains.

Flattening process:

  1. For each include:domain in your record, recursively resolve it to its full list of IP ranges
Code
# Example: resolve Google's SPF to IP ranges
dig TXT _spf.google.com +short
# Returns sub-includes, e.g. include:_netblocks.google.com

dig TXT _netblocks.google.com +short
# Returns ip4: ranges — these are the actual IPs
  1. Replace the include: directives with the resolved IP ranges:
Code
# Before (with includes — many lookups):
v=spf1 include:_spf.google.com include:sendgrid.net ~all

# After (flattened — 0 lookups):
v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20
       ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16
       ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17
       ip4:216.58.192.0/19 ip4:216.239.32.0/19
       ip4:167.89.0.0/17 ip4:192.254.112.0/24 ip4:198.21.86.0/23
       ~all

⚠️ Warning: Flattened IP lists go stale when ESPs change their sending ranges. Google, SendGrid, Mailchimp, and others update their IP ranges periodically without notice. A flattened record that was correct today may fail in 3–6 months when a provider adds or rotates IP ranges. Any email sent from a new provider IP not in your flattened record will fail SPF. Flattening requires ongoing maintenance — it is not a set-and-forget solution.

Fix Option 3 — Macro-Based SPF (for Large Senders)

SPF macros are a mechanism defined in RFC 7208 that allows dynamic SPF evaluation based on the SMTP envelope sender and other variables. They are complex to implement correctly but can completely eliminate the lookup limit problem for organisations that send from a large number of domains or third-party services.

The most common macro-based approach replaces your full include: chain with a single exists: mechanism that performs a lookup against a custom DNS zone you control:

Code
v=spf1 exists:%{i}._spf.example.com ~all

This single exists: mechanism performs one DNS lookup using the sending IP address as a variable (%{i}). Your custom _spf.example.com zone returns an A record if the IP is authorised, or NXDOMAIN if it isn't. This approach uses exactly 1 lookup regardless of how many sending IPs you have.

When to use macros:

  • Your organisation sends from hundreds of third-party services and flattening is unmanageable
  • You have a dedicated DNS team capable of maintaining the macro zone
  • You're willing to invest in the implementation and testing overhead

For most organisations, macro-based SPF is overkill. Fix Option 1 (remove redundant entries) or Fix Option 2 (flatten) will be sufficient. Macros are worth considering only if your sending infrastructure is genuinely too complex for either simpler approach.

Why SPF Flattening Breaks Over Time

This deserves its own section because it's the most common failure mode after an initial permerror fix. Organisations flatten their SPF record, the problem disappears, and then 4 months later permerror returns — or worse, legitimate mail silently fails SPF without permerror (because the sending IP isn't in the flattened list anymore).

The root cause: Major ESPs regularly update their sending infrastructure. They add new IP ranges to handle growth, retire old ranges, and shift traffic between data centres. When they do, they update their own SPF records — but your flattened record, which bypasses those canonical records in favour of a static IP list, has no way to automatically pick up the change.

Documented examples of IP range changes:

  • SendGrid has updated its sending IP ranges multiple times as it has expanded
  • Google Workspace adds IPv6 ranges periodically
  • Mailchimp's IP ranges vary significantly by account sending volume tier

Mitigation strategies for flattened SPF records:

  1. Schedule a quarterly audit. Every 90 days, re-resolve each provider's SPF record and compare against your flattened list. Update any ranges that have changed.

  2. Set calendar reminders. After flattening, set a recurring calendar event to audit the record. Treat it like certificate expiry monitoring — boring until it's urgent.

  3. Monitor SPF pass rates in DMARC reports. If a provider changes their IPs and your flattened record falls behind, you'll see SPF failures appearing in DMARC aggregate reports before users start complaining about mail rejection. Check DMARC reports monthly using our Email Deliverability Report.

  4. Consider automated flattening services. Services like AutoSPF, dmarcian, and others offer managed SPF flattening that automatically re-resolves and updates your record when provider IP ranges change. For organisations with many providers, the management overhead justifies the cost.

Testing Your Fixed SPF Record

After making any change to your SPF record, validate it before considering the fix complete.

Retrieve and inspect the updated record

Code
# Confirm the updated record is live on your authoritative nameserver
dig TXT example.com @ns1.yourprovider.com +short | grep "v=spf1"

# Confirm it's propagated to public resolvers
dig TXT example.com @8.8.8.8 +short | grep "v=spf1"
dig TXT example.com @1.1.1.1 +short | grep "v=spf1"

Verify the lookup count

Use our SPF Checker to re-count the lookup depth after your fix. Confirm the total is 9 or fewer (leaving at least 1 lookup as headroom for future additions).

Send a test message and inspect authentication headers

Send a test email from each of your sending platforms to a Gmail address. In Gmail, open the message, click the three-dot menu, and select "Show original." Look for the Authentication-Results: header:

Code
Authentication-Results: mx.google.com;
   spf=pass (google.com: domain of sender@example.com designates 209.85.128.0 as permitted sender)
       smtp.mailfrom=sender@example.com;

spf=pass confirms the fix is working. spf=permerror means the record still has a problem. spf=neutral or spf=softfail indicates the sending IP isn't covered by the record.

Check your DMARC aggregate reports

After 24–48 hours, review DMARC aggregate reports for your domain. The SPF pass rate should have improved. Use the Email Deliverability Report to get an at-a-glance view of your authentication health across SPF, DKIM, and DMARC.

For context on what DMARC aggregate reports contain and how to interpret them, see our DMARC Policy Enforcement guide.

Frequently Asked Questions

Q: My SPF record has only 5 include: directives — why am I getting permerror?

Because lookups are counted recursively. Each include: you add at the top level requires 1 lookup, plus however many lookups the included domain's own SPF record requires. A single include:_spf.google.com may consume 3–4 lookups on its own. Five include: directives pointing to providers with multi-level sub-includes can easily exceed 10 total lookups. Use our SPF Checker to count your recursive total.

Q: Can I split my SPF record into multiple TXT records to avoid the limit?

No. Publishing multiple TXT records starting with v=spf1 on the same domain is itself a permerror — the receiving server cannot determine which record to evaluate. All your SPF mechanisms must exist in a single TXT record. The 10-lookup limit applies to the entire evaluation of that single record.

Q: Does the all mechanism count as a lookup?

No. The all mechanism matches everything without performing a DNS lookup. It costs 0 lookups. Similarly, ip4: and ip6: mechanisms cost 0 lookups. Only mechanisms that require DNS resolution to evaluate count against the limit.

Q: I removed several include: directives but still have permerror — what else could it be?

Check for a second v=spf1 TXT record at your domain — this is an instant permerror regardless of lookup count. Also check for void lookups — mechanisms that resolve to zero results (an a: pointing to a non-existent domain, for example). RFC 7208 limits void lookups to 2 before triggering permerror.

Q: How do I handle a service that doesn't publish an SPF record for their sending IPs?

If a provider doesn't publish their own SPF record, you can't use include: to reference it. You'll need to obtain their sending IP ranges directly from their documentation or support team and add them as ip4: or ip6: mechanisms. This is effectively manual flattening for that provider.

Q: Will fixing SPF permerror automatically fix my DMARC failures?

It depends on your DMARC configuration. If SPF was your only passing authentication signal and DKIM wasn't configured, fixing SPF permerror should restore DMARC pass. If you also have DKIM configured and aligned, DMARC may have been passing via DKIM even while SPF was in permerror — in which case fixing permerror improves your redundancy but may not visibly change DMARC pass rates. Review your DMARC aggregate reports to understand your current authentication picture.

Next Steps

After resolving permerror, the next priority is ensuring your full email authentication stack is solid. Verify that DKIM is configured and signing outbound messages, and that your DMARC record is published and aligned — these are the three pillars that meet Google and Yahoo's bulk sender requirements.

For a full reference on SPF record syntax, mechanisms, qualifiers, and the complete setup process, see our SPF Record Explained guide.

Run an Email Deliverability Report to see your overall authentication health, and use the SPF Checker to confirm your fixed record is valid and under the lookup limit.

Browse all email authentication guides on DNSnexus for the full picture.