SummaryConfirm the error and sending domain, inspect nested records, and remove only authorisations you have verified are unnecessary. Test the repaired policy for each sending service.
In this guide
Confirm which SPF error you have
Start with a failed message or a bounce, and save its timestamp and authentication details. Look for spf=permerror together with an explanation about too many lookups. A permanent SPF error can also come from multiple SPF records, malformed syntax or a broken reference. Flattening is not the first step for every permerror.
Identify the domain in smtp.mailfrom, or the envelope sender recorded in Return-Path. That is usually the policy you need to investigate. Checking the visible From domain alone can send you to the wrong record. Microsoft’s authentication troubleshooting guide distinguishes lookup failures from other SPF results.
Use the Emailmetry SPF checker to inspect that domain and its dependencies. Its potential lookup total is a record inspection, not a full evaluation for a particular sending IP. Keep the received message as separate evidence. If tools disagree, see why email SPF checkers can report different results.
What the ten-lookup limit actually counts
During an SPF evaluation, at most ten evaluated terms may require DNS lookups. The terms are include, a, mx, ptr, exists and redirect. Nested terms count too. Fetching the initial policy is not an additional term, and cached answers do not remove a term from the budget.
ip4, ip6 and all do not consume that budget. There are also separate limits for address expansion and empty DNS answers, often called void lookups. Those are different problems from exceeding ten terms. See RFC 7208, section 4.6.4.
A worked example: three includes, eleven terms
Imagine the following fictional policy. All .example domains below are placeholders, and the counts are constructed for this explanation. They are not measurements of real providers.
v=spf1 include:mail.example include:news.example include:billing.example -all- 4
include:mail.exampleThe outer include plus three nested includes: running total four. - 4
include:news.exampleThe outer include plus three nested includes: running total eight. - 3
include:billing.exampleThe outer include plus two nested includes would take this path to eleven.
Assume a billing server does not match either earlier provider and requires both nested billing checks. Its evaluation reaches the limit before completing the final path. A mailbox server that matches inside the first include can finish much earlier. That explains why some messages may pass while others encounter an error.
Write out the path for the affected sender. Record the policy at each name, the time of inspection and where the count grows. Providers can change nested records without changing the TXT value at your domain. For a worked example, see how the sending IP changes SPF lookup counts.
Reduce lookups without removing needed senders
- Save a baseline. Export the current DNS value, record name and TTL. Keep a list of the workflows that must still send successfully.
- Map each rule to a service owner. An unfamiliar include might belong to monthly invoices or an infrequently used CRM integration. Confirm its purpose before removing it.
- Verify the sending identity. A provider using its own envelope-sender domain may not need an include in your main domain. Compare account-specific setup instructions with received headers.
- Remove confirmed obsolete authorisations. Check queued mail, scheduled jobs and retirement dates. Document why each removed rule is no longer required.
- Review architecture if the necessary policy remains too complex. A genuinely separate MAIL FROM subdomain or supported managed flattening may help. Each requires its own validation.
For the fictional example, suppose the service owner confirms that the newsletter account is closed, its queue is empty and its authorisation is no longer needed. Removing that include reduces the constructed billing path from eleven terms to seven. That is an example of evidence-based cleanup, not permission to remove a provider solely because it has the largest count.
Open the sender-inventory template to record the service behind each rule. The NCSC also recommends an iterative approach to maintaining SPF authorisations.
Shortcuts that do not fix the underlying problem
Moving the same rules into a helper record and including it adds another term; it does not reset the budget. Creating a second SPF TXT record causes a separate error. Changing -all to ~all does not reduce the number of terms evaluated before it.
Reordering positive includes may let one sender match sooner, but can move another sender’s failure later in the sequence. It is not proof that the whole setup is healthy. Likewise, copying today’s provider IPs into DNS creates a maintenance obligation when those addresses change.
Verify the repair and keep the evidence
Publish one reviewed policy at the correct name. Check the authoritative DNS answer and then a recursive resolver, allowing for the previous TTL. Lowering a TTL does not clear answers already cached under its older value. Cloudflare explains DNS caching and TTLs.
Send new external messages from each active workflow, including the originally failing service. Save the receiving system’s SPF result and evaluated domain, plus DKIM and DMARC results. A historic message will not acquire new authentication results after a DNS edit. Recheck failures before declaring the change complete; successful authentication also does not promise inbox placement.
Where Emailmetry fits
Emailmetry flattens supported SPF references into IP ranges to reduce lookup requirements and keeps those ranges current. A record already over the ten-lookup limit can be flattened when its references resolve successfully. Invalid syntax and broken references need separate correction. Start with the SPF checker, then review SPF record compatibility and the published safeguards to assess whether flattening fits your record.