BookMySpot

Deliverability

SPF "Too Many DNS Lookups" (PermError): How to Fix It

The SPF “too many DNS lookups” error means evaluating your SPF record required more than 10 DNS queries, so receivers stop and return permerror. The limit comes from RFC 7208 section 4.6.4, and it counts every include, a, mx, exists, ptr, and redirect, including the ones nested inside your vendors’ records. To fix it, remove includes you no longer use, move some senders to their own subdomains, and replace a/mx with IP ranges where it’s safe.

Below is how to count your lookups accurately, which fixes are safe, and which create new problems.

What the SPF 10-lookup limit actually says

RFC 7208 puts several caps on SPF evaluation to protect DNS infrastructure from abuse:

LimitValueResult if exceeded
Terms that trigger DNS lookups (include, a, mx, ptr, exists, redirect)10permerror
Address lookups per mx mechanism10permerror
Address lookups per ptr record10extra records ignored
“Void” lookups (empty answer or NXDOMAIN)2 (a SHOULD)permerror

Things that don’t count: ip4, ip6, all, and the exp modifier. Microsoft’s SPF troubleshooting guide lists the same split.

Two subtleties catch people:

  1. Nesting counts. Microsoft’s example: an include that points to a record containing three more includes costs four lookups in total, not one.
  2. Evaluation stops at the first match. Receivers read the record left to right and stop when the sending IP matches. Microsoft notes that a record with more than 10 potential lookups may still pass for some messages if the match comes early. That’s why the error looks intermittent: mail from your first-listed sender passes while mail from your last-listed one fails.

What the error looks like

You’ll see it in a few places:

  • Authentication-Results headers on delivered mail: spf=permerror (google.com: permanent error in processing during lookup of bounce@example.com: ...).
  • DMARC aggregate reports, where SPF results show permerror for a source. Our guide on reading DMARC aggregate reports shows where to look.
  • Bounces. Microsoft says receivers may reject with errors like “The message exceeded the hop count” or “The message required too many lookups.” RFC 7208 section 8.7 suggests a 550 5.5.2 reply when a receiver rejects for a permerror.
  • SPF checker tools that report a lookup count over 10.

Under DMARC, a permerror is treated as an SPF failure. If DKIM is aligned, DMARC still passes. If not, your DMARC policy applies.

How to count your SPF lookups

Do this once by hand so you understand your record. Start with your domain:

dig +short TXT example.com | grep spf1
"v=spf1 include:_spf.google.com include:mail.vendor-a.example.net include:spf.vendor-b.example.net mx a ~all"

Write down each term and its cost:

TermDirect costThen resolve its record and count again
include:_spf.google.com1query it, count its includes
include:mail.vendor-a.example.net1query it
include:spf.vendor-b.example.net1query it
mx1plus up to 10 address lookups (separate limit)
a1
~all0

Then fetch each included record and repeat:

dig +short TXT _spf.google.com
dig +short TXT mail.vendor-a.example.net

Keep going until you hit records with only ip4/ip6 terms. Add everything up. On Windows, Resolve-DnsName -Type TXT <name> does the same job.

Vendors change their records without warning, so a record that counted 9 last quarter may count 11 today. Re-check after adding any service, or use the SPF checker on this site, which does the recursive count for you.

How to fix SPF too many DNS lookups

Work through these in order. The early ones are free and safe; the later ones have trade-offs.

1. Remove includes for services you no longer use

Every old marketing tool, trial signup, and migrated help desk tends to leave its include behind. Check each include against your current vendor list. Dead includes are doubly harmful: if the vendor removed their record, the lookup returns nothing and counts as a void lookup too, and RFC 7208 allows only two of those.

2. Remove includes for services that don’t use your bounce domain

SPF is checked against the envelope sender (Return-Path), not the visible From. Many platforms send with their own bounce domain by default, such as bounces.vendor.example.net. In that case, receivers check the vendor’s SPF record, never yours, and your include for that vendor does nothing.

Look at the Return-Path header on a message each vendor sent. If it’s not under your domain, the include in your root SPF record is dead weight. (For DMARC, that vendor needs aligned DKIM instead, or a custom bounce domain under yours.)

3. Drop mx, a, and ptr where you can

  • ptr is deprecated by RFC 7208 section 5.5 and should never be published. Remove it.
  • mx authorizes your inbound mail servers to send. Unless those same servers send outbound mail, you don’t need it. Mail hosted at Google or Microsoft sends from different IPs than the MX hosts, and is already covered by the include.
  • a authorizes your web server’s IP. Only keep it if the web server really sends mail as your domain; if it does, replace it with that server’s ip4: address.

4. Move senders to subdomains

This is the most durable fix. Each hostname gets its own SPF record and its own budget of 10 lookups. Microsoft recommends it for exactly this reason and for reputation isolation:

example.com.         TXT "v=spf1 include:_spf.google.com ~all"
news.example.com.    TXT "v=spf1 include:mail.vendor-a.example.net ~all"
billing.example.com. TXT "v=spf1 include:spf.vendor-b.example.net ~all"

With relaxed DMARC alignment (the default), mail with a bounce domain of news.example.com still aligns with a From address of @example.com. See DMARC alignment: strict vs relaxed. The existing post on sending from subdomains instead of your root domain covers the reputation side.

5. Use custom bounce domains your vendors manage

Many platforms (Amazon SES calls it a custom MAIL FROM domain) let you point a subdomain like bounce.example.com at them. The SPF record for that subdomain contains only that vendor’s include, so it never touches your root record’s budget.

6. Replace an include with IP ranges (carefully)

If a vendor publishes a small, stable, documented IP list, you can swap their include for ip4: entries. Microsoft’s guidance says this is reasonable for vendors with stable ranges, but explicitly not for Microsoft 365 itself, whose sending IPs change frequently. If you do it, document what you replaced and review it at least quarterly, as Microsoft recommends.

Automated “SPF flattening” services do this continuously. They solve the count but create a new dependency: if the flattener lags behind a vendor’s IP change, your legitimate mail fails SPF. Our existing post explains why SPF flattening creates a worse problem than it solves for most senders. Use it as a last resort.

7. Lean on DKIM

You don’t need every sender in SPF to pass DMARC. If a service signs with aligned DKIM using your domain, DMARC passes even when SPF doesn’t apply. That’s often the cleanest way to drop a vendor from SPF entirely. See DKIM explained.

A worked example

Before (12 lookups by recursive count, permerror for senders matched late):

v=spf1 a mx include:_spf.google.com include:spf.crm.example.net
       include:mail.oldtool.example.net include:spf.helpdesk.example.net
       include:servers.newsletter.example.net ~all

Changes:

  1. a and mx: web server doesn’t send; inbound MX is Google. Removed (saves 2).
  2. oldtool: cancelled last year; its record now returns NXDOMAIN. Removed (saves 1 lookup and 1 void lookup).
  3. newsletter: moved to news.example.com with its own record (saves at least 1, plus its nested includes).
  4. helpdesk: uses its own Return-Path domain and signs with aligned DKIM. Removed.

After:

example.com.       TXT "v=spf1 include:_spf.google.com include:spf.crm.example.net ~all"
news.example.com.  TXT "v=spf1 include:servers.newsletter.example.net ~all"

Both records now sit comfortably under the limit, with room for future tools.

How to keep it from happening again

  • Own the record. One person or team approves every SPF change.
  • Ask before adding. When a new tool says “add our include,” ask whether it can use a subdomain or a custom bounce domain instead.
  • Monitor DMARC reports. A new permerror usually shows up there before customers notice.
  • Re-count quarterly. Vendors change their own records.

Authentication problems and list problems often show up together, especially after a platform migration. While you’re cleaning up DNS, run your contact list through our free email verifier to catch addresses on domains with no MX records, disposable domains, and typos, so the bounce rate doesn’t muddy your diagnosis. It works from syntax and DNS checks and doesn’t connect to mailboxes.

FAQ

Does the 10-lookup limit include nested includes?

Yes. Every DNS-querying term counts wherever it appears in the evaluation chain. An include that contains three more includes costs four lookups.

Does ip4 count toward the SPF lookup limit?

No. ip4, ip6, and all don’t trigger DNS queries, so they don’t count. That’s why replacing includes with IP ranges reduces the count, at the cost of maintenance.

Why do only some of my emails fail with SPF permerror?

Receivers stop evaluating at the first matching mechanism. Mail from senders listed early in the record matches before the 10th lookup and passes; mail from senders listed later triggers the limit and gets permerror.

Can I just create a second SPF record for the extra includes?

No. Two SPF records on the same hostname is itself a permerror under RFC 7208. Use subdomains, each with one record, instead.

Is SPF permerror the same as SPF fail?

No, but DMARC treats both as a failure to pass SPF. fail means the IP isn’t authorized; permerror means the record couldn’t be evaluated at all. If DKIM is aligned and passing, DMARC still passes.

Check your list before you send

Free email verifier: syntax, MX, disposable and role-based addresses, typos. Paste up to 100 at once.

Verify emails free