Skip to main content
Relaymetry

SPF too many DNS lookups: fix the PermError before it silently breaks delivery

SPF allows at most 10 DNS-querying mechanisms per evaluation. When your record or the chains it expands into cross that limit, receivers return a `permerror` result. Most receivers treat `permerror` as a non-pass, which means SPF provides no authentication evidence for those messages, and if DKIM is not configured and aligned, DMARC fails too. The fix is to reduce the number of DNS lookups your record makes. Trimming the visible text length alone is not enough.

Quick answer

SPF allows at most 10 DNS-querying mechanisms per evaluation. When your record or the chains it expands into cross that limit, receivers return a permerror result. Most receivers treat permerror as a non-pass, which means SPF provides no authentication evidence for those messages, and if DKIM is not configured and aligned, DMARC fails too. The fix is to reduce the number of DNS lookups your record makes. Trimming the visible text length alone is not enough.

What the 10-lookup limit means

SPF is defined in RFC 7208. When a receiving mail server evaluates your SPF record, it resolves each mechanism that requires a DNS lookup. Section 4.6.4 of RFC 7208 caps that count at 10 per evaluation. When evaluation crosses 10 lookups, the RFC requires the evaluating server to return a permerror result.

The mechanisms that count toward the limit are: include:, a, mx, ptr, exists, and the redirect= modifier. The mechanisms that do not count, because they require no DNS lookup, are ip4:, ip6:, and all. A record with ten ip4: entries is well within the limit. A record with three include: statements that each expand into three more include: statements is not.

RFC 7208 §4.6.4 also imposes a second, separate cap: void lookups, which are DNS queries that return NXDOMAIN or no usable records, are limited to 2. Exceeding two void lookups is also a permerror. This matters if your record includes references to now-deleted provider subdomains or a provider that changed its SPF infrastructure.

The distinction between permerror and fail matters. A fail result means the sending IP was found and explicitly rejected. A permerror means evaluation could not complete. Receivers handle permerror differently, but the outcome for delivery is the same: SPF does not pass.

Why real domains cross the limit without noticing

Ten sounds like a generous ceiling until you add up what modern sending infrastructure involves. Consider a domain whose outbound mail is split across four systems: Microsoft 365 for internal and transactional mail, a marketing email platform for newsletters, a CRM for automated outreach, and Google Workspace for a small team.

Each of those platforms publishes its own SPF record, and each of those records is itself a chain of include: references. Microsoft 365's SPF entry at include:spf.protection.outlook.com expands into further lookups. Google's entry at include:_spf.google.com does the same. Marketing platforms typically chain through two or three sub-includes. Before you have written a single custom rule yourself, you may already be at or past 10.

The record looks fine when you read it as text. Its length in characters may be well under any limit. The problem is invisible until you recursively expand every include and count the actual resolver calls. That is why a domain can send mail successfully for months and then suddenly start triggering permerror after a platform adds a new intermediate include: to its own SPF chain, a change you did not make and were not notified about.

Vendors add and restructure their SPF chains when they rotate infrastructure, acquire sending partners, or add regional mail relay capacity. Every change they make to their own SPF can change your effective lookup count, even though your DNS record was never touched.

How to diagnose the problem

Start by expanding your SPF record recursively, not just reading the top-level text. The process is:

  1. Fetch the TXT record at your domain root.
  2. For every include:, a, mx, exists, or redirect= mechanism, perform the corresponding DNS lookup.
  3. For every include: that resolves to another SPF record, repeat the expansion recursively.
  4. Count each DNS query. Stop when you either reach 10 or finish all mechanisms.

Doing this by hand for a three-level nested chain is tedious and error-prone. The Relaymetry SPF checker performs recursive expansion automatically and reports the total lookup count for your domain.

If you have access to a bounce message or a delivered test message, check whether the Authentication-Results header reads spf=permerror. That confirms the problem happened in a real delivery event. The bounce text may also include the exact error reason from the receiving server.

One thing a public DNS check alone cannot tell you: the exact lookup count Gmail or another provider reached for a specific message delivery, because that depends on the resolver path and cache state at evaluation time. The recursive expansion gives you the authoritative count from a cold cache, which is the correct number to optimize against.

Why permerror is worse than a clean fail

A clean SPF fail means a receiver positively identified the sending IP as unauthorized for the domain. Many operators who set -all accept that some edge-case sources will fail and choose to handle those sources deliberately.

A permerror is different. It signals that evaluation could not finish. The receiver has no way to know whether the sending IP would have passed or failed if the limit had not been reached. The RFC says the evaluating server returns permerror and stops. That result cannot satisfy a DMARC pass requirement, regardless of what the final answer might have been.

For DMARC, defined in RFC 7489, to pass via the SPF path, SPF must return pass for an identity that aligns with the visible From domain. A permerror is not pass. If your DKIM is in order and aligned, DMARC can still pass through the DKIM path, so the impact may not be visible in every delivery scenario. But it means your SPF record is providing no authentication evidence at all, and any message where DKIM is absent, unsigned, or misaligned will arrive without DMARC coverage.

How to fix the SPF lookup limit

  1. Run the Relaymetry SPF checker on your domain and note the exact lookup count and which mechanisms contribute most.
  2. Identify platforms you no longer send from. Remove their include: entries. A former email platform, a trial CRM, or a transactional provider you stopped using last year may still be in the record.
  3. For any platform that sends from a stable, predictable set of IP addresses, including your own self-hosted mail infrastructure, replace the include: with direct ip4: or ip6: mechanisms. Direct IP mechanisms count zero lookups. Check with the provider whether their IPs are stable before making this substitution; providers that rotate their sending IPs will break your SPF silently if you hardcode IPs and they rotate.
  4. If you cannot reduce lookup count through removal and direct IPs alone, consider delegating distinct mail streams to subdomains. Transactional mail can leave from transact.example.com, marketing mail from mail.example.com, and each subdomain carries its own SPF record scoped only to the relevant sending platform. DMARC with relaxed alignment covers both subdomains under the organizational domain.
  5. Consider SPF flattening only with automation in place. Flattening resolves all include: chains to their terminal IP addresses and records those directly. This gets lookup count to zero or near-zero. The downside is real: when a provider rotates its sending IPs, your flattened record silently goes stale, and SPF starts failing for that provider's new IPs without any visible DNS change on your part. Flattening is appropriate only if you have an automated process that re-flattens the record when upstream changes are detected, or if you audit the record on a fixed schedule.
  6. After making changes, re-run the SPF checker to confirm the new count is below 10 and that every real outbound platform still appears in the resolved mechanism list.
  7. Send a controlled test to a Gmail or Outlook inbox and inspect the Authentication-Results header. Confirm that the SPF result reads pass, not permerror or fail.
  8. Verify that DMARC alignment is preserved for each sending path after the restructure. SPF passing for a return-path domain that does not align with the From domain does not satisfy DMARC; confirm the alignment mode and check a real header end to end.

What this does not prove

The Relaymetry SPF checker expands your SPF record from a cold DNS cache and reports the lookup count. It cannot simulate the exact resolver path or cache state that a specific receiving server used for a delivery attempt you already made. If a bounce shows permerror but the checker reports a count below 10, the discrepancy usually means a transient DNS error was treated as a void lookup at delivery time, the record was different at delivery time, or a mechanism resolved to an unexpected result that the checker's cache also does not reflect.

A lookup count below 10 after restructuring tells you the record is within spec at the time of the check. It does not guarantee inbox placement, does not tell you whether DKIM is passing for the same messages, and does not measure Gmail reputation or recipient engagement signals, none of which are visible from public DNS.

Frequently asked questions

Which SPF mechanisms actually count toward the 10-lookup limit?

The mechanisms that trigger DNS lookups (and count toward the limit) are `include:`, `a`, `mx`, `ptr`, `exists`, and `redirect=`. The `ip4:`, `ip6:`, and `all` mechanisms require no DNS lookup and do not count. If your record is over the limit, replacing `include:` entries for stable-IP providers with direct `ip4:` or `ip6:` entries is often the fastest way to bring the count down.

What is a void lookup and how is it different from the 10-lookup cap?

A void lookup is a DNS query that returns NXDOMAIN (the name does not exist) or contains no usable records. RFC 7208 §4.6.4 caps void lookups at 2 per evaluation; exceeding that limit is also a `permerror`. A record with 8 successful lookups and 3 void lookups returns `permerror` even though it never approached the 10-lookup ceiling. Void lookups are most common when an `include:` points to a domain that was once a valid SPF host but no longer publishes records.

Can I fix SPF permerror by just flattening my record?

Flattening, which replaces all `include:` chains with direct IP addresses, eliminates the lookup problem. But flat records go stale silently. If a provider you flattened rotates their sending IPs, the new IPs are not in your record, and SPF fails for that provider's mail until you re-flatten. Flattening is safe only when you have automation to detect upstream IP changes and update the record promptly, or when you audit the record against provider announcements on a regular schedule.

If SPF returns permerror, will DMARC always fail?

Not necessarily. DMARC can pass through a DKIM path if a valid DKIM signature aligns with the visible From domain. SPF `permerror` means the SPF path cannot contribute a pass, but DMARC passes when either the SPF path or the DKIM path provides an aligned pass result. If DKIM is configured correctly and aligned, DMARC may still pass even while SPF is in `permerror`. That said, the correct response is to fix the SPF record so both paths work. Using DKIM alone as a workaround for broken SPF is not a stable configuration.

My SPF record looks short. Why is the lookup count so high?

The visible text of your SPF record can be short while the resolved lookup count is large because each `include:` expands into the target domain's full SPF record, which may itself contain more `include:` entries. A record with three `include:` statements that each expand into records with three more `include:` statements contributes nine lookups before any of your own `a` or `mx` mechanisms are counted. The lookup count is determined by recursive expansion of the full tree, not by the line count of the top-level record. Use a checker that performs recursive expansion to get an accurate count rather than reading the surface record and guessing.

Other email authentication problems

References