# SPF PermError: How to Fix the 10 DNS Lookup Limit Without Breaking Mail

Canonical: https://vulnify.app/blog/spf-permerror-10-dns-lookup-limit-fix

Fix SPF PermError by tracing nested includes, removing stale senders, staying under the 10-DNS-lookup limit, and validating the published policy.

An SPF record can be syntactically valid and still fail in production. One of the most common reasons is the DNS lookup limit. A company adds Microsoft 365, a helpdesk, a marketing platform, a CRM, and a transactional mail provider. The record still looks readable, but nested include: statements push SPF evaluation beyond the protocol limit and receivers return permerror . This is not a cosmetic warning. RFC 7208 requires SPF implementations to limit DNS-query-causing terms to 10 during evaluation. If the limit is exceeded, evaluation must return a permanent error. The right fix is not to randomly delete providers or flatten the record without understanding what sends mail. The right fix is to inventory authorized senders, count lookup-causing mechanisms, remove stale dependencies, and validate the resulting record. What counts as an SPF DNS lookup? The SPF limit applies to terms that can cause DNS queries during evaluation. RFC 7208 identifies include , a , mx , ptr , exists , and the redirect modifier. Mechanisms such as ip4 , ip6 , and all do not consume that lookup budget in the same way. A simple record may be well within the limit: v=spf1 include:_spf.example-mail.com ip4:203.0.113.24 ~all The visible record appears to have one lookup-causing include. The catch is that the included record may itself contain several includes, MX lookups, or redirects. SPF evaluation follows that tree. Counting only the terms in your top-level TXT record can therefore give a false sense of safety. How nested includes create PermError Imagine this top-level policy: v=spf1 include:spf.protection.example include:_spf.crm.example include:mail.helpdesk.example include:spf.marketing.example include:send.transactional.example ~all Five visible includes do not necessarily mean five DNS lookups. If one provider's SPF record expands into three more includes and another uses an MX mechanism, the effective evaluation cost can pass 10. Different branches may also change over time because SaaS providers update their own SPF records. This is why SPF debugging should be based on the current DNS tree, not on a screenshot taken months ago. First, find every legitimate sender Do not start by editing DNS. Start by identifying who is actually authorized to send mail using your domain. Primary mailbox provider. Transactional application mail. CRM and sales automation. Marketing newsletters. Support or ticketing systems. Billing and invoicing platforms. Monitoring or alerting services. Legacy services that may still send password resets or notifications. Ask each service owner whether the platform still sends mail using the domain in the envelope sender or another SPF-relevant identity. A provider that was cancelled six months ago should not keep a permanent place in the SPF tree. This inventory step prevents the worst kind of SPF "fix": deleting an include that still protects legitimate mail. Count lookups before changing the record Vulnify's SPF Record Builder is designed to help with this drafting stage. The builder warns when the lookup count exceeds 10 and also warns when the record grows beyond 255 characters. It starts with ~all by default and does not publish DNS for you. Use the builder as a planning aid, not as a substitute for understanding the live record. Then use the DNS Record Lookup and Email Security Checker to examine what is actually published. A useful worksheet looks like this: Provider: Primary mail SPF term: include:spf.protection.example Still in use: yes Nested lookup estimate: 3 Provider: Old newsletter platform SPF term: include:oldmailer.example Still in use: no Action: remove Provider: Transactional mail SPF term: include:send.transactional.example Still in use: yes Nested lookup estimate: 2 The objective is not to reach a fashionable number. The objective is to stay within the protocol limit with only the senders the organization actually authorizes. Safe ways to reduce SPF lookups Remove stale providers This is usually the cleanest improvement. Organizations accumulate includes because each new service is added but old services are rarely removed. Confirm ownership, stop the old sending path, and then delete its authorization. Prefer direct IP mechanisms only when the addresses are genuinely stable ip4 and ip6 mechanisms do not consume the 10-term DNS lookup budget. That does not mean you should copy a SaaS provider's current IP addresses into your SPF record. If the provider expects customers to use an include because its sending infrastructure changes, hard-coding addresses creates a future delivery failure. Use direct IP mechanisms for infrastructure you control or for providers that explicitly document stable, customer-managed ranges. Avoid ptr The ptr mechanism is discouraged and creates additional DNS work and operational uncertainty. If an old record still contains it, treat that as a reason to review the policy rather than preserve it automatically. Do not split SPF into multiple records Publishing multiple SPF TXT records for the same identity is not a workaround for the lookup limit. SPF expects one policy record. Splitting a long policy into two independent v=spf1 records creates a different error condition rather than increasing the budget. Be careful with SPF flattening SPF flattening converts provider includes into IP mechanisms so the receiver performs fewer DNS lookups. It can be useful in tightly managed environments, but it transfers maintenance responsibility to you. If the provider changes its outbound addresses and your flattened record is stale, legitimate mail can fail SPF. If you use flattening, it should be automated, monitored, and tied to provider documentation. A one-time manual flatten is fragile. The apparent simplicity in DNS can hide a maintenance obligation that did not exist before. Record length is a separate problem The lookup budget and the TXT record's presentation length are related operational concerns but they are not the same rule. A policy can be under 10 lookups and still become unwieldy. Vulnify's SPF Record Builder warns when the generated text exceeds 255 characters so you can catch an obvious deployment concern before publishing. DNS providers may display or store long TXT data in quoted chunks while still returning the intended logical string. Test the published result after the change instead of trusting the control-panel representation. Publish and verify in stages A safe SPF change should be boring. Record the old value, lower DNS TTL in advance when appropriate, prepare the replacement, schedule the change during a period when mail owners are available, and verify authoritative DNS after publication. Then send test messages through every legitimate platform you kept in the policy. Inspect authentication results at a mailbox that exposes them. Do not declare success just because one message from the primary mailbox provider passes. For the public DNS side, use Vulnify's Email Security Checker after the change. It reviews SPF, DKIM, and DMARC maturity together, which matters because SPF is only one part of domain-based email authentication. SPF pass is not the same as DMARC pass DMARC requires alignment. A message can pass SPF for a provider-controlled envelope-sender domain while the visible From address uses your domain. If those identifiers are not aligned under your DMARC policy, SPF does not contribute a DMARC pass. That is why fixing an SPF PermError should not end with "SPF now says pass." Check DKIM and DMARC behavior for each sending platform as well. If a provider supports aligned DKIM using your domain, that is often an important part of a resilient DMARC deployment. Practical troubleshooting checklist Confirm there is only one SPF policy record for the identity. Inventory every service still authorized to send mail. Expand nested includes and count DNS-query-causing terms. Remove obsolete providers before trying more complex fixes. Avoid replacing provider includes with hard-coded IPs unless that design is supported. Do not treat manual flattening as maintenance-free. Check record length as well as lookup count. Publish the change and query authoritative DNS. Test mail from every remaining sender. Review DKIM and DMARC alignment after SPF is healthy. Provider SPF records can change without your DNS changing An SPF policy that is under the limit today can move closer to the limit later because an included SaaS provider controls its own record. Your top-level TXT value may be identical while the nested lookup tree changes. That is another reason not to treat the first successful deployment as permanent. Keep a simple record of which business service owns each include. When a provider is removed, make SPF cleanup part of the offboarding checklist. When a provider changes its documented SPF requirements, recalculate the effective lookup path rather than assuming the existing include still has the same cost. Also distinguish a protocol error from a transient DNS failure. permerror describes a policy problem that cannot be repaired by retrying the same evaluation later. Temporary DNS failures can produce different outcomes. That distinction matters during incident response because repeatedly sending test messages will not fix a record that structurally exceeds the lookup budget. Use Vulnify to draft and verify, not inventory senders The SPF Record Builder can help draft a cleaner record and warns about the 10-lookup threshold before publication. The DNS Record Lookup helps inspect the public TXT data, and the Email Security Checker provides the broader SPF, DKIM, and DMARC view. None of those tools can know which SaaS vendors your business still authorizes. That inventory remains an organizational task. The best SPF record is not the longest record that includes every system the company has ever used. It is the smallest accurate policy that authorizes the current sending infrastructure and stays inside the protocol's evaluation limits.
