SPF PermError: Why the 10-Lookup Limit Breaks Email Authentication and How to Fix It
Adding third-party email services pushes SPF past the 10-lookup limit, causing PermError and DMARC failures. Here's how to count SPF lookups, why the limit is hit so easily, and the three solutions: IP replacement, flattening, and consolidation.
By sadiqbd · June 8, 2026
The 10-lookup SPF limit is one of the most frequently triggered email authentication failures
SPF seems simple: publish a DNS record listing which servers can send email from your domain. But the moment you add a third-party service — Google Workspace, a transactional email provider, a CRM, a marketing platform — each one adds DNS lookups that count against a hard limit of 10. Hit 11 and SPF returns PermError, which causes DMARC to fail SPF alignment, and deliverability suffers.
How SPF works
An SPF record is a TXT DNS record at your domain's root that specifies which IP addresses and mail servers are authorised to send email on your behalf.
A receiving server checks SPF by:
- Looking up the
TXTrecord for the sender's domain (From:header, or more accurately theReturn-Pathor SMTP envelopeMAIL FROMaddress) - Evaluating the SPF record to determine if the sending IP is authorised
- Returning
pass,fail,softfail,neutral, ortemperror/permerror
A basic SPF record:
v=spf1 include:_spf.google.com include:spf.mailgun.org ip4:203.0.113.50 ~all
Mechanisms:
include:domain— include another domain's SPF record (uses a DNS lookup)ip4:/ip6:— directly authorise specific IPs (uses no DNS lookups)a— authorise the domain's A record IP (uses one DNS lookup)mx— authorise the domain's MX servers (uses one lookup + one per MX record)~all— softfail — any sender not matched is unauthorised but still accepted-all— hardfail — any unmatched sender is rejected
The 10-lookup limit
RFC 7208 specifies that SPF evaluation must abort with PermError if it requires more than 10 DNS lookups (excluding the initial TXT record lookup). The mechanisms that count toward this limit: include, a, mx, ptr, exists, and redirect.
ip4: and ip6: mechanisms use zero lookups and are the most efficient way to authorise specific sending IPs.
Why the limit is hit so quickly:
Each include: statement consumes one lookup — plus the lookups required to evaluate the included record. When _spf.google.com itself contains additional include: statements, those count too. Nested includes compound quickly.
A typical multi-platform configuration:
v=spf1 include:_spf.google.com include:spf.mailgun.org include:servers.mcsv.net include:spf.salesforce.com include:sendgrid.net ~all
Counting lookups for this record:
include:_spf.google.com→ 1 lookup + internal lookups → often 3–4 totalinclude:spf.mailgun.org→ 1 + internal → 2–3 totalinclude:servers.mcsv.net(Mailchimp) → 1 + internal → 2–3 totalinclude:spf.salesforce.com→ 1 + internal → 2–3 totalinclude:sendgrid.net→ 1 + internal → 2–3 total
Total: likely 10–15 lookups. Over the limit.
Diagnosing SPF lookup count
Tools for checking lookup count:
- MXToolbox SPF analyzer — shows each mechanism, its lookup depth, and the running total
- The SPF Lookup tool on sadiqbd.com — shows the raw SPF record and evaluation
- Command line:
dig TXT example.comto read the record, then manually trace includes
The error returned when the limit is exceeded:
spf=permerror (too many DNS lookups)
Or in DMARC aggregate reports, SPF results of permerror indicate this specific failure.
Solutions to the lookup limit problem
1. Replace include: with ip4: where possible
If you can identify the specific sending IPs for a service, use ip4: directly instead of the provider's SPF include:
Instead of:
include:spf.mailgun.org
Use:
ip4:143.55.151.0/24 ip4:69.72.43.0/24
The downside: if the provider changes their sending IPs (common during infrastructure changes), your SPF record needs updating. Some providers recommend against this approach for this reason.
2. SPF flattening
SPF flattening resolves all the IP addresses referenced by nested includes and rewrites the SPF record as a list of ip4: directives. The result uses zero DNS lookups.
Before (with includes):
v=spf1 include:_spf.google.com include:spf.mailgun.org include:servers.mcsv.net ~all
After (flattened):
v=spf1 ip4:209.85.128.0/17 ip4:66.102.0.0/20 ip4:69.72.43.0/24 ip4:198.2.130.0/23 [many more IPs] ~all
The problem: flattened SPF records need to be updated whenever any included service changes their IP ranges — which happens without notice. This requires either monitoring for SPF changes and updating your record, or using a managed flattening service.
Managed flattening services (AutoSPF, dmarcian, Validity) maintain the flattened record automatically, handling IP updates from third-party providers. This is the recommended approach for organisations with many sending services.
3. Consolidate sending through a single relay
Route all outbound email through one or two services rather than authorising each service independently. If all marketing, transactional, and CRM email passes through a single ESP, only that ESP's SPF include is needed.
4. Reduce the number of authorised senders
Audit all services in your SPF record. Are all of them actively sending email from your domain? Remove any that aren't currently used or that send from a different address (a subdomain gets its own SPF record and doesn't count against the parent domain's limit).
SPF record syntax: other common mistakes
Multiple SPF records for the same domain.
Only one SPF TXT record is allowed. If two exist, SPF evaluation returns PermError. Combine them into one.
Using ptr mechanism.
The ptr mechanism is explicitly deprecated in RFC 7208 — it's slow, unreliable, and counts toward the lookup limit. Don't use it.
Putting the all mechanism in the middle.
Any mechanisms after all are ignored. all must be the last mechanism.
Overly permissive +all.
+all authorises any server to send as your domain — effectively disabling SPF authentication. Never use +all in a production SPF record. Use ~all (softfail) or -all (hardfail).
SPF and DMARC alignment
For DMARC to pass on SPF alignment, the domain in the SMTP envelope MAIL FROM (Return-Path) must match the From: header domain. When email is sent through a third-party service without configuring custom Return-Path alignment, the Return-Path often contains the provider's domain — breaking SPF alignment.
Most major ESPs allow you to configure a custom Return-Path subdomain (e.g. bounce.example.com), which must be authorised in your SPF record and must align with your From: domain.
How to use the SPF Lookup on sadiqbd.com
- Enter the domain
- Look up — queries the TXT record and shows the SPF record
- Review — check for
include:statements that might push you over the limit - Count lookups — use the result to manually trace or tool-assist the lookup count
Frequently Asked Questions
What's the difference between ~all and -all?
~all (softfail) means unauthorised senders are flagged but typically still delivered. -all (hardfail) means unauthorised senders should be rejected. With DMARC at p=reject, the actual enforcement comes from DMARC, making the distinction between ~all and -all less critical — but -all signals stricter intent.
Does SPF protect against phishing?
SPF only authenticates the MAIL FROM (envelope sender) domain — not the visible From: address. An attacker can craft an email with your domain in the From: header while using a different domain in the envelope sender. DMARC closes this gap by requiring alignment between the envelope sender and the From: header.
Is the SPF Lookup free? Yes — completely free, no sign-up required.
SPF's 10-lookup limit is a real operational constraint that catches teams off guard as they add more email service providers. Monitoring the lookup count and addressing it before it causes failures is straightforward — the hard part is remembering to do it.
Try the SPF Lookup free at sadiqbd.com — check any domain's SPF record, see the raw TXT record, and identify potential lookup count issues instantly.