SPF too many DNS lookups errors happen when an email receiver must make more DNS queries than SPF permits to evaluate whether your sending server is authorized. The fix is not to keep retrying a message: it is to simplify, consolidate, or redesign the SPF policy that applies to the message’s envelope sender domain.

What an SPF too many DNS lookups error means

Sender Policy Framework (SPF) is a DNS-based authorization system for email. A domain owner publishes an SPF policy as a TXT record, and a receiving mail server evaluates that policy against the IP address that connected to it and the message’s SMTP envelope sender.

A basic SPF record might look like this:

example.com. IN TXT "v=spf1 ip4:192.0.2.44 -all"

That policy says that 192.0.2.44 is allowed to send mail using an envelope sender at example.com; other sources should fail SPF. In real deployments, though, mail may be sent by a transactional email API, an SMTP relay, Google Workspace or Microsoft 365, a help desk, a billing system, a CRM, and an ecommerce platform. Each service often asks you to add an include: mechanism to your SPF record.

That is where the problem starts. SPF limits the number of DNS-querying mechanisms and modifiers evaluated during one check. If the evaluator exceeds the limit, the result is permerror, meaning a permanent SPF error. RFC 7208 sets the relevant limit at ten DNS-querying terms and also limits void DNS lookups. (datatracker.ietf.org)

You may see the issue in several forms:

  • An email authentication report shows spf=permerror.
  • A deliverability test flags “SPF Too Many DNS Lookups.”
  • A recipient server rejects a message with a 550 5.7.x SMTP response.
  • A message is accepted by your API or SMTP relay but later bounces when the relay attempts delivery.
  • A DMARC report shows SPF failing or producing an error for a domain that previously passed.

The exact SMTP response varies by recipient. 550 denotes a permanent SMTP failure, while the enhanced status code and text are receiver-specific. For example, 550 5.7.23 is commonly associated with an SPF validation failure in Exchange Online environments, but an SPF lookup-limit failure can also be reported under a different 5.7.x code or only in authentication results. (learn.microsoft.com)

Why SPF has a 10-lookup limit

The lookup cap is a safety limit, not a recommendation. SPF records can reference other domains, and those referenced domains can reference more domains. Without a firm boundary, a receiving server could be induced to make a long chain of DNS requests for every incoming email.

The limit helps reduce DNS load, avoid unbounded recursive policies, and make SPF evaluation predictable. It also means an SPF record that appears short can still be broken. This record contains only three terms after v=spf1:

v=spf1 include:spf.mail.example include:spf.support.example include:spf.billing.example -all

But each included policy may contain more include:, a, mx, exists, or redirect= references. The receiving server evaluates the chain, not just the top-level record you can see in your DNS control panel.

For example:

example.com
└── include:spf.mail.example
    ├── include:region1.mail.example
    ├── include:region2.mail.example
    └── include:shared.mail.example

One top-level include can consume several lookup opportunities. Add a second provider with a similarly layered policy and the SPF budget can disappear quickly.

A crucial operational point is that DNS caching does not give you permission to exceed the SPF limit. The standard defines a limit on evaluation, not merely a count of network packets observed by a particular resolver. A record may appear to work in one test environment and still fail at another receiver if its chain is close to or over the permitted evaluation budget.

Which SPF mechanisms count as DNS lookups

The SPF syntax is compact, but not all terms have the same operational cost. The terms most relevant to lookup-limit troubleshooting are below.

Terms that consume the SPF lookup budget

These mechanisms or modifiers can require DNS lookups and must be counted during SPF evaluation:

  • include:<domain>
  • a and a:<domain>
  • mx and mx:<domain>
  • ptr and ptr:<domain>
  • exists:<domain-spec>
  • redirect=<domain>

Nested policies count too. If include:spf.vendor.example causes the receiver to retrieve and process another SPF record containing additional lookup-causing terms, those downstream terms count against the same message evaluation.

The mx and ptr mechanisms deserve extra caution. Their evaluation can entail more DNS activity than a simple include chain, and SPF places additional constraints around address-record processing. In modern outbound email configurations, mx is rarely the clearest way to authorize mail sources, and ptr is generally best avoided entirely.

Terms that do not consume the lookup budget

These common mechanisms do not themselves require a DNS lookup:

  • ip4:<IPv4-address-or-CIDR>
  • ip6:<IPv6-address-or-CIDR>
  • all

For example, this record has no DNS-querying mechanisms after the initial SPF policy retrieval:

v=spf1 ip4:192.0.2.0/24 ip4:198.51.100.17 ip6:2001:db8:1234::/48 -all

This is one reason static IP authorization is attractive from a lookup-budget perspective. It is not automatically the right solution, however. Third-party sending platforms may change, add, or retire sending ranges. If a provider gives you an SPF include domain, replacing it with copied IP ranges can create a maintenance and deliverability risk.

Qualifiers do not change lookup cost

SPF qualifiers control the result when a mechanism matches:

  • + — pass; this is the default when no qualifier is written.
  • - — fail.
  • ~ — softfail.
  • ? — neutral.

They do not alter whether a mechanism triggers DNS resolution. These two terms have the same lookup behavior:

include:spf.sender.example
~include:spf.sender.example

Changing include: to ~include: will not solve a lookup-limit problem. Likewise, moving -all to ~all might change policy semantics but cannot reduce the number of lookups already made earlier in the record.

How SPF evaluation actually reaches PermError

SPF mechanisms are processed from left to right. Evaluation stops when a mechanism yields a definitive match, but the full chain must be considered when diagnosing because the actual path depends on the connecting IP address and the logic in nested records.

Consider this policy:

v=spf1 ip4:192.0.2.10 include:spf.transactional.example include:spf.workspace.example -all

A message sent from 192.0.2.10 matches immediately, so the receiver does not need to process either include. A message sent through the transactional provider might not match the first IP term, then enters spf.transactional.example, where it may consume several lookups. A message sent through the workspace provider could follow a different route through the policy.

This creates an important testing rule: do not validate SPF only against one successful sending path. Test the actual envelope sender and source IP used by every platform that sends mail for the domain.

Include is not a simple text import

An include: mechanism asks the receiver to evaluate the named domain’s SPF policy. The include matches only if that included policy returns SPF Pass. If it returns Fail, SoftFail, Neutral, or None, the include itself does not match and processing continues with the next term. A downstream PermError or TempError can affect the overall evaluation result.

That distinction matters when simplifying records. You cannot always replace a chain of includes with arbitrary text copied from each provider’s record. SPF has ordering, qualifiers, evaluation rules, macros, and provider-managed infrastructure changes to consider.

Redirect is different from include

The redirect= modifier delegates policy evaluation when no earlier mechanism matches. It is commonly used to make one domain inherit another domain’s policy:

v=spf1 redirect=_spf.example.com

Unlike include:, redirect= is a modifier, not a match mechanism. It is evaluated only after the mechanisms before it fail to match. It still consumes lookup budget and should not be used as a way to hide an already over-complex policy.

Do not place an all mechanism before redirect=. Since all always matches, a record such as this makes the redirect unreachable:

v=spf1 -all redirect=_spf.example.com

Audit your SPF record before changing it

The safest remediation begins with an inventory. Do not delete includes merely because nobody recognizes the vendor name. A forgotten service may still send password resets, invoices, support transcripts, monitoring alerts, or legally required notices.

Start by retrieving the published TXT record:

dig +short TXT example.com

On Windows PowerShell, you can use:

Resolve-DnsName -Type TXT example.com

You are looking for the TXT string beginning with v=spf1. There must be only one SPF record for a given domain. Multiple TXT records are normal for other services, but publishing multiple records that each begin with v=spf1 causes SPF permerror independently of the lookup-limit issue.

Build a sender inventory

Create a table before editing DNS. Include every legitimate path that can originate mail with an envelope sender in the affected domain.

Sending sourceTypical purposeEnvelope sender domainAuthorization methodStill needed?
Transactional API or SMTP relayReceipts, password resets, alertsbounce.example.com or example.comProvider include or dedicated IPYes/No
Workspace mailEmployee mailexample.comWorkspace includeYes/No
Support platformTickets and repliessupport.example.comSeparate subdomain SPFYes/No
Billing toolInvoices and payment noticesbilling.example.comSeparate subdomain SPFYes/No
Legacy newsletter serviceMarketing mailexample.comOld includeYes/No

Check SMTP logs, application configuration, message headers, vendor account settings, and DMARC aggregate reports. The visible From: address alone is not enough. SPF checks the SMTP MAIL FROM identity, often shown in delivered messages as the Return-Path, or falls back to the SMTP HELO/EHLO domain when the envelope sender is empty.

Expand every lookup-causing term

For each top-level include:, retrieve the target domain’s TXT record and repeat the process. Continue until you reach only IP mechanisms, all, or terms that do not delegate further.

A manual audit can look like this:

example.com
v=spf1 include:_spf.tx.example include:_spf.office.example include:_spf.legacy.example -all

_spf.tx.example
v=spf1 include:_spf.shared1.example include:_spf.shared2.example -all

_spf.office.example
v=spf1 include:_spf.region.example -all

_spf.legacy.example
v=spf1 include:_spf.old-a.example include:_spf.old-b.example include:_spf.old-c.example -all

Even before resolving every branch, this record is a warning sign. The top-level policy has three includes. The transactional path adds two more, the office path adds one, and the legacy platform adds three. Depending on the sending path and nested contents, the policy can exceed the limit.

Tools such as MXToolbox, DMARCian’s SPF survey tools, and mail-tester.com can help identify a lookup problem quickly. Treat their output as an audit aid rather than a substitute for understanding your sender inventory. Check the exact record and expansion chain yourself before making a production DNS change.

The fastest safe fixes for too many SPF lookups

There is no receiver-side setting that can increase the ten-lookup cap for your domain. The durable solution is to remove unnecessary evaluation paths or move senders to a better domain design.

1. Remove stale services and duplicate authorizations

This is usually the lowest-risk improvement. A domain can accumulate SPF entries years after a team stopped using the corresponding service.

Common cleanup opportunities include:

  1. A retired marketing provider whose include remains in DNS.
  2. Two includes for the same provider after a migration.
  3. A legacy workspace include left behind after moving email hosting.
  4. A support, billing, or CRM integration that now sends from a different subdomain.
  5. A copied record that has both a provider include and static IPs for the same infrastructure.

After confirming a sender is no longer used, remove its authorization, publish the updated single SPF TXT record, and test the remaining senders. Keep a rollback copy of the prior record and note its DNS TTL before deployment.

2. Use subdomains to separate sending roles

Subdomains are often the cleanest long-term solution. Instead of authorizing every service under the organizational domain, assign each category of mail its own envelope sender domain.

For example:

example.com.        IN TXT "v=spf1 include:_spf.workspace.example -all"
bounce.example.com. IN TXT "v=spf1 include:_spf.transactional.example -all"
news.example.com.   IN TXT "v=spf1 include:_spf.marketing.example -all"
support.example.com.IN TXT "v=spf1 include:_spf.helpdesk.example -all"

The human-visible address can still be From: Team <hello@example.com> where appropriate, but the underlying envelope sender must be configured deliberately. For DMARC, SPF must also align with the visible From: domain if SPF is the authentication mechanism expected to provide DMARC alignment. An aligned DKIM signature can independently support DMARC, which is why properly configured DKIM remains essential. The current DMARC standard describes the need for both authentication and identifier alignment. (rfc-editor.org)

Subdomain separation reduces SPF complexity because each sender type has a smaller policy. It also improves operational ownership: the team responsible for marketing does not need to edit the same record that authorizes application password resets.

3. Consolidate services where it makes architectural sense

If three applications use three separate email vendors only for basic transactional mail, consolidating them behind one approved SMTP relay or one email API can reduce SPF includes and improve observability.

This is not an argument to centralize every mailing system blindly. A billing provider or support platform may need its own direct sending integration. But when your own applications can use one controlled outbound path, a shared relay gives you one place to manage authentication, bounce handling, suppression, rate limits, and logging.

For applications that need a common sending path, use your provider’s documented SMTP relay or REST integration rather than copying a provider’s DNS logic into application code. The relevant setup details should come from the provider’s email API reference and setup guides, because the correct envelope sender, DKIM configuration, and provider include domain vary by service.

4. Replace stable infrastructure with explicit IP ranges only when appropriate

If you operate mail servers with stable, documented egress IP ranges, ip4: and ip6: mechanisms can replace DNS-dependent mechanisms.

For example, this:

v=spf1 a mx -all

may be better expressed as this when the organization deliberately sends only from known outbound gateways:

v=spf1 ip4:198.51.100.20 ip4:198.51.100.21 ip6:2001:db8:100::20 -all

This approach is appropriate only when you own the change process for those addresses. Do not flatten a provider’s network into IP entries unless you have a reliable automated update process and understand the provider’s failover model. A stale SPF record can cause legitimate mail to fail as surely as an excessive lookup chain.

SPF flattening: useful, but not maintenance-free

SPF flattening replaces some indirect DNS-based authorization with direct IP address mechanisms. It can substantially reduce DNS lookups, but it trades lookup complexity for operational maintenance.

A conceptual example:

Before:
v=spf1 include:spf.provider.example -all

After:
v=spf1 ip4:198.51.100.0/24 ip4:203.0.113.18 ip6:2001:db8:55::/48 -all

The flattened version no longer needs to traverse the provider’s SPF policy. However, it is correct only while those addresses remain authorized for your account and service. If the provider changes its outbound ranges, introduces regional capacity, or uses a new failover block, your manually flattened policy becomes outdated.

When flattening can be reasonable

Flattening may be a defensible option when all of the following are true:

  • You cannot remove enough includes or separate enough senders onto subdomains.
  • The source policy is stable and its IP data can be refreshed automatically.
  • You have monitoring that detects record drift and SPF failures.
  • The DNS record remains within TXT record length and DNS-provider constraints.
  • A responsible team owns the automation and rollback procedure.

When flattening is risky

Avoid manual flattening when you do not control the upstream provider’s IP changes, when you have no monitoring, or when you are using it to preserve an unnecessarily crowded root-domain SPF record. It is especially risky for large multitenant sending platforms that may use different infrastructure by region, product, account type, or traffic class.

If you choose a managed flattening service or build an internal job, treat it as production infrastructure. Review changes, retain historical versions, alert on failed refreshes, and test the refreshed record from multiple resolvers.

Avoid common SPF fixes that do not work

SPF errors often trigger rushed changes. The following responses are common, but they do not address the real problem or can create a worse one.

Adding another SPF TXT record

Do not publish a second record such as:

example.com. IN TXT "v=spf1 include:spf.vendor-a.example -all"
example.com. IN TXT "v=spf1 include:spf.vendor-b.example -all"

SPF expects one policy record. Multiple v=spf1 TXT records produce permerror; they do not merge into a combined authorization list. Combine legitimate mechanisms into one syntactically valid SPF policy, then reduce its lookup cost.

Changing -all to ~all

The all mechanism is reached only after prior mechanisms fail to match. Changing the ending from hard fail to softfail does not reduce lookup use. It can also weaken your policy and make troubleshooting harder.

Deleting includes without checking actual envelope senders

Removing a provider include can appear successful in a basic DNS validator but silently break an application that sends only a few messages each month. Review real headers and service configuration first. Pay attention to scheduled reports, error alerts, staging environments, regional applications, and automated systems owned by other teams.

Using ptr as a shortcut

The ptr mechanism is complicated, can create extra DNS work, and is not a modern shortcut for “allow hosts whose reverse DNS ends in my domain.” Use explicit IP ranges, a provider-supported include, or a clean subdomain policy instead.

Assuming DMARC makes SPF irrelevant

DMARC can pass through aligned DKIM even when SPF fails, but that does not make a broken SPF record harmless. Some receivers use SPF in their broader spam and policy decisions, forwarding scenarios can differ, and a permerror is a permanent configuration defect. Maintain valid SPF and DKIM independently.

Test the fix from DNS to delivery

Publishing a shorter record is only the middle of the process. You must verify syntax, lookup count, actual authorization, and resulting mail authentication.

A practical test checklist

  1. Query the published TXT record with dig or Resolve-DnsName and confirm there is exactly one v=spf1 policy.
  2. Run an SPF lookup analysis tool and inspect the expanded include path, not just the pass/fail summary.
  3. Confirm every active sender in your inventory has a valid authorization path.
  4. Send test messages through each sending source: application API, SMTP relay, workspace system, help desk, billing tool, and marketing platform.
  5. Inspect the received message headers for Authentication-Results.
  6. Confirm the result is spf=pass for the intended envelope domain and review DKIM and DMARC results too.
  7. Watch delivery logs, bounce events, and DMARC aggregate reports after the DNS change propagates.

A successful header often contains a line similar to this:

Authentication-Results: recipient.example;
  spf=pass smtp.mailfrom=bounce.example.com;
  dkim=pass header.d=example.com;
  dmarc=pass header.from=example.com

The exact formatting differs by receiver, but the important details are the SPF result, the domain checked after smtp.mailfrom=, the DKIM signing domain, and the visible header.from= domain.

Test more than one recipient mailbox

A message delivered to one mailbox is encouraging, not conclusive. Large mailbox providers, enterprise gateways, and secure email filters can apply different policies and disclose different diagnostics. Test accounts at more than one provider when possible, especially if the original problem appeared only for a particular recipient organization.

mail-tester.com can provide an accessible test report for a message sent to its generated address. MXToolbox and similar DNS tools are useful for checking published records and lookup chains. For deeper production verification, combine those tests with your own outbound event logs and DMARC aggregate reporting.

DNS publishing details that can derail a correct SPF policy

Even a well-designed policy can fail if it is published incorrectly.

Keep the record syntactically intact

Your DNS provider may display a long TXT record as multiple quoted chunks. That is valid DNS presentation if the chunks form one TXT value. Do not accidentally publish separate SPF policies while trying to split a long value.

The policy itself should begin with v=spf1, use spaces between terms, and contain no comma-separated list. For example:

v=spf1 ip4:192.0.2.10 include:_spf.service.example -all

This is not valid SPF syntax:

v=spf1, ip4:192.0.2.10, include:_spf.service.example, -all

Respect DNS propagation and TTLs

Resolvers can continue returning an older policy until cached data expires. Before changing a record, note its TTL and plan a verification window that accounts for cached responses. Avoid repeatedly changing the record during that window; frequent edits make it difficult to distinguish propagation from a syntax or authorization problem.

Watch for void lookups too

The headline issue is usually the ten-lookup limit, but SPF also limits void lookups. A void lookup occurs when a DNS request returns no usable answer of the requested type or an NXDOMAIN result. Broken include targets, missing macro-generated names, and stale redirect targets can therefore create SPF permerror even if the visible policy has fewer than ten lookup-causing terms.

A resolver error or timeout can produce temperror instead of permerror. Treat those differently: temperror is transient and may succeed on retry, while permerror requires a DNS or policy correction.

A durable SPF design for transactional email

Transactional email is especially sensitive to SPF mistakes because it includes account verification, password resets, receipts, alerts, and security notifications. These messages are time-sensitive, and a policy failure can become a user-access incident rather than a marketing deliverability issue.

A robust design usually follows these principles:

  • Use a dedicated envelope-sender subdomain for application mail, such as bounce.example.com.
  • Keep the root domain’s SPF policy focused on employee or primary-domain mail, if it needs SPF at all.
  • Configure DKIM for every sending platform, not only SPF.
  • Use one controlled API or SMTP relay for first-party application mail where practical.
  • Remove integrations from DNS during decommissioning, not months later.
  • Re-audit SPF after adding a new sender, acquiring a company, changing email providers, or launching a new business unit.
  • Alert when lookup count approaches the limit rather than waiting for a permerror.

Separating email streams also makes incident response easier. If a marketing provider changes its SPF chain, it should not jeopardize password-reset mail. If an old support integration needs to be retired, its policy can be changed without touching your application relay.

Conclusion

An SPF too many DNS lookups error is a design signal: too many independent authorization paths have been accumulated under one SPF policy. The immediate goal is to bring the evaluated chain under the SPF limit, but the better outcome is a simpler email architecture with clear sender ownership.

Begin with an inventory of every legitimate envelope sender, expand the actual include chains, remove stale providers, and move independent mail streams onto dedicated subdomains. Use flattening only with a reliable maintenance process. Then validate the published DNS record and test real messages from every outbound system.

A shorter SPF record is valuable, but a maintainable one is better. The safest policy is the one your team can explain, monitor, and update before a new sender turns a routine DNS change into a delivery outage.

FAQ

How many DNS lookups are allowed in an SPF record?

SPF evaluation permits up to ten DNS-querying mechanisms or modifiers. include, a, mx, ptr, exists, and redirect can consume that budget, including terms reached through nested includes. Going beyond the limit produces SPF permerror.

Does each include count as only one lookup?

No. The include: term itself consumes lookup budget, and the included SPF policy can contain its own lookup-causing terms. Always count the complete expansion chain for the sender path being tested.

Can I create multiple SPF records to avoid the limit?

No. A domain must publish one SPF policy record beginning with v=spf1. Multiple SPF TXT records cause a permanent SPF error rather than combining their authorizations.

Is SPF flattening the best fix?

Not always. Flattening can reduce lookup count, but it makes you responsible for keeping IP ranges current. First remove unused services and use subdomains to separate sending roles. Flatten only when you can automate updates and monitor the result.

Why did my email API accept the send but the recipient still rejected it?

An email API or SMTP relay can accept your submission before it attempts delivery. The recipient server performs its own authentication checks later, so an SPF permerror may appear as a delayed bounce or delivery event rather than an immediate API error.