Skip to main content
Microsoft 365intermediate

SPF PermError: Too Many DNS Lookups - How to Fix

Fix the SPF PermError caused by too many DNS lookups. SPF allows only 10 lookups; learn what counts, how to count yours, and how to get under the limit safely.

8 min readUpdated August 2026

Mail failing with SPF PermError and a message about too many DNS lookups? Your SPF record needs more than the 10 DNS lookups the standard permits. The record itself is syntactically fine — it is simply too expensive to evaluate.

The Error

Depending on which system reports it, you will see one of these:

Received-SPF: permerror (protection.outlook.com: domain of example.com used an
 invalid SPF record)

spf=permerror (sender IP is 203.0.113.10) smtp.mailfrom=example.com;
 SPF permanent error: too many DNS lookups

550 5.7.24 SPF validation error

RFC 7372 assigns 5.7.24 ("SPF validation error") to exactly this situation — it is used in place of the older 5.5.2 for the permerror case. Do not confuse it with 5.7.23 ("SPF validation failed"), which means SPF was evaluated successfully and the sender was not authorised. A permerror means the record could not be evaluated at all.

And in a Microsoft 365 non-delivery report:

The message required too many lookups.

Microsoft documents the alternative wording "The message exceeded the hop count" for the same cause, which is misleading — it sounds like a mail loop but is the SPF lookup limit.


Why This Happens

RFC 7208 §4.6.4 is explicit:

SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS. If this limit is exceeded, the implementation MUST return "permerror".

The trap is that lookups are counted recursively. When you publish include:_spf.example-vendor.com, that costs one lookup — plus every lookup inside that record, plus everything inside those. A record with five of your own include: mechanisms routinely resolves to fifteen or more real lookups.

What counts, and what does not

Costs a lookupFree
include:ip4:
aip6:
mxall
ptr (deprecated — avoid)exp=
exists:
redirect=

Two further limits from the same section catch people out:

  • Evaluating a single mx mechanism must not query more than 10 address records, or that mechanism alone returns permerror.
  • Void lookups — queries returning an empty answer or NXDOMAIN — "SHOULD" be limited to two. Exceeding that also produces permerror. A stale include: pointing at a decommissioned vendor is a void lookup, so removing dead includes fixes two problems at once.

A second, unrelated cause of permerror is worth ruling out first: publishing two SPF records. A domain must have exactly one. Two produces permerror regardless of lookup count.


Fix 1: Count Your Actual Lookups

Do not guess from the number of include: mechanisms you can see. Resolve the whole tree:

# Your record
dig +short TXT example.com | grep spf1

# Then resolve every include it references
dig +short TXT _spf.google.com
dig +short TXT spf.protection.outlook.com

# ...and anything those records include, recursively

Our DNS lookup tool will resolve the TXT records for you if you do not have dig to hand. Count every include, a, mx, ptr, exists and redirect found anywhere in the tree. If the total is 11 or more, that is your bug.

Note one subtlety that makes this intermittent: receivers evaluate mechanisms left to right and stop as soon as the sending IP matches. A record that would exceed 10 lookups if fully evaluated may still pass for senders listed early in the record. That is why "it works from our mail server but fails from the CRM" is such a common symptom.


Fix 2: Remove Services That No Longer Send

Almost every overweight SPF record contains includes for a vendor the business stopped using two years ago. Go through the record mechanism by mechanism and ask whether that service still sends mail as your domain. Deleting one dead include: that itself contained three nested includes recovers four lookups instantly.

This is the safest fix, so do it before anything clever.


Advertisement

Fix 3: Move Third-Party Senders to Subdomains

Each domain and subdomain gets its own independent 10-lookup budget. This is the structural fix and the one Microsoft recommends.

Send marketing mail from marketing.example.com, ticketing from support.example.com, and application notifications from mail.example.com, each with its own SPF record:

; example.com  - staff mail only
v=spf1 include:spf.protection.outlook.com -all

; marketing.example.com - bulk platform only
v=spf1 include:servers.bulkvendor.example -all

This has a second benefit beyond the lookup budget: a marketing campaign's complaint rate can no longer damage the sending reputation of your password reset emails.


Fix 4: Replace Stable Vendors with IP Mechanisms

ip4: and ip6: mechanisms cost zero lookups. Replacing an include: with the addresses it resolves to — known as SPF flattening — is legitimate when the vendor publishes a stable, documented range:

; Before: include:mail.legacyvendor.example  (3 nested lookups)
; After:
v=spf1 ip4:198.51.100.0/24 include:spf.protection.outlook.com -all

Flattening is a maintenance commitment, not a one-time fix. If the vendor changes IPs and you do not notice, their mail starts failing SPF silently. Document what you replaced, review at least quarterly, and only flatten vendors that publish their ranges.

Do not flatten Microsoft 365. Microsoft explicitly advises against flattening include:spf.protection.outlook.com because its sending infrastructure uses dynamic addresses that change frequently. The same applies to Google Workspace and any other large cloud sender.


What Not To Do

Two "fixes" circulate widely and both make your domain less safe:

  • +all authorises every host on the internet to send as your domain. It does not resolve a lookup-count permerror — the record is still parsed — and it hands spoofers a free pass while destroying any value DMARC could give you. Never publish it.
  • Deleting the SPF record entirely to make the error go away removes the authentication signal that receivers and your own DMARC policy depend on. The error stops; the deliverability problem gets worse.

Fix the lookup count. There is no shortcut that preserves the protection.


Verify the Fix

Re-resolve and re-count first:

dig +short TXT example.com | grep spf1

Then send a live test to a mailbox you control and read the headers. In Gmail, open the message, choose Show original; in Outlook on the web, open View message details. You want:

spf=pass (sender IP is 203.0.113.10) smtp.mailfrom=example.com

Paste the full header block into our email header analyzer to see the parsed SPF, DKIM and DMARC results together, which is faster than reading raw headers.

Test from every sending system, not just your mail server. Because evaluation stops at the first match, one system passing proves nothing about the others.


Prevention

  • Treat the SPF record as change-controlled. Every time someone signs up for a service that sends as your domain, the record needs review — this is the single most common regression.
  • Keep a comment in your DNS documentation recording which mechanism belongs to which vendor and who owns it. Records become unmaintainable when nobody remembers what include: number six is for.
  • Default new third-party senders onto a subdomain rather than the primary domain.
  • Publish DMARC with rua= reporting and read the aggregate reports. They surface sending sources you had forgotten about before those sources cause a bounce. Build the record with our DMARC generator.
  • Re-count lookups after any vendor migration; providers change their own nested includes without telling you.

Summary

  1. Confirm the cause: permerror plus "too many lookups" or "exceeded the hop count"
  2. Rule out two SPF records — a domain must publish exactly one
  3. Count recursively, including nested includes, up to the limit of 10
  4. Delete dead includes first, then move third-party senders to subdomains
  5. Flatten only stable vendors, never Microsoft 365 or Google Workspace
  6. Never use +all — it disables the protection rather than fixing the error

Frequently Asked Questions

Find answers to common questions

Your SPF record requires more than 10 DNS lookups to evaluate. RFC 7208 section 4.6.4 requires implementations to limit lookups to 10 and to return "permerror" if the limit is exceeded. Receiving servers treat permerror as an SPF failure, so mail can be rejected or junked even though the record looks correct.

The include, a, mx, ptr and exists mechanisms and the redirect modifier each cause a lookup. Crucially, lookups are counted recursively - an include that points to a record containing three more includes costs four, not one. The all, ip4 and ip6 mechanisms cost nothing.

Because nested includes count too. Each include: you publish triggers a lookup of that provider's own SPF record, and whatever includes that record contains are counted against your budget as well. Five of your own includes can easily resolve to fifteen or more actual lookups.

No. +all authorises every host on the internet to send as your domain and effectively disables SPF as a protection, inviting spoofing and destroying your DMARC posture. It does not fix a permerror caused by lookup count either, because the record is still evaluated. Reduce the lookup count instead.

Resolve your record, then resolve every include and redirect it references, and repeat for anything those records reference. Count every include, a, mx, ptr, exists and redirect encountered anywhere in the tree. Most SPF checking tools do this recursively and print a running total.

Flattening replaces include: mechanisms with the ip4: and ip6: addresses they resolve to, which cost no lookups. It is safe only for vendors with stable, documented IP ranges, and it needs review at least quarterly. Never flatten a cloud provider with dynamic IPs.

No. Microsoft explicitly advises against flattening it because Microsoft 365's sending infrastructure uses dynamic IP addresses that change frequently. Flattening it will silently break mail flow when Microsoft changes its ranges.

Each domain and subdomain gets its own independent budget of 10 lookups. Moving bulk email, ticketing and marketing services onto a subdomain such as marketing.example.com gives them a fresh budget and keeps your primary domain's record small.

No, and this is a common mistake that makes things worse. A domain must publish exactly one SPF record. Two records cause a permerror on their own, because the receiver cannot determine which to evaluate.

Microsoft documents two bounce messages for exceeding the limit - "The message exceeded the hop count" and "The message required too many lookups". Both point at the same cause despite the first one sounding like a routing loop.