Skip to content
MailTwin

SPF PermError: too many DNS lookups, and how to fix it

By Ghulam Rasool · Updated

Short answer: SPF allows at most 10 DNS lookups while a receiver evaluates your record, counting every nested include. At 11, receivers stop and return permerror, which means SPF fails for every message you send, not just the ones from the last service you added. Count your lookups, remove what you do not need, and replace lookups with IP ranges or DKIM where you can.

What the error looks like

You will usually see it in a bounce, in a DMARC aggregate report, or in the headers of a delivered message:

Authentication-Results: spf=permerror (too many DNS lookups) smtp.mailfrom=example.com

Microsoft and Google both use wording close to this. In a DMARC report the SPF result for your own servers shows as permerror even though their IP addresses are in the record.

Why the limit exists

Every SPF check makes the receiving server do DNS work on your behalf. Without a cap, a sender could publish a record that makes every receiver run hundreds of lookups, which is a cheap way to attack DNS. RFC 7208 section 4.6.4 sets the limit at 10 and requires a permerror when it is exceeded.

What counts as a lookup

TermCosts a lookup?Notes
include:Yes, onePlus every lookup inside the included record, recursively.
a, a:hostYes, oneLooks up the A and AAAA records.
mx, mx:hostYes, oneThe MX hosts it returns are then resolved too, up to 10 of them.
exists:Yes, oneMostly used with macros.
ptrYes, oneSlow and discouraged by the RFC. Remove it.
redirect=Yes, onePlus the lookups in the target record.
ip4:, ip6:, allNoFree. These are how you save lookups.

There is a second limit people miss: void lookups. A lookup that returns nothing (the name does not exist, or has no record of that type) is a void lookup, and receivers may fail SPF after two of them. An include: for a service you cancelled years ago often turns into exactly that.

Count your lookups

You cannot count by reading your own record, because most of the cost is inside your providers' records and they change them without notice. Run the SPF checker. It follows every include, shows the count at each level, and flags void lookups. Write the number down, then use the fixes below in order: each one is safer than the next.

Five ways to get back under 10

1. Remove includes for services you no longer use

This is the fix most of the time. Old newsletter tools, a previous helpdesk, a website host you left: each still costs lookups. Check your DMARC aggregate reports or ask around before deleting, but anything that has not sent mail in your reports for a month can usually go.

2. Drop includes that do not help DMARC anyway

Many sending services (marketing platforms, CRMs, ticketing systems) send with their own Return-Path domain, such as bounces.vendor.net. SPF is checked against that domain, not yours, so your include: for them is never used and never aligns for DMARC. If the service signs with DKIM using your domain, DMARC passes through DKIM and the include can go. Check the service's documentation or a message header: if smtp.mailfrom is not your domain, your SPF record is not involved.

3. Replace a and mx with IP ranges

If a or mx point at servers that do not actually send mail (your website host, your inbound filter), remove them. If they do send, list their addresses with ip4: or ip6:. That costs nothing, but you must remember to update it if the addresses change.

4. Move a sender to a subdomain

Give a high-volume service its own subdomain, for example news.example.com, with its own SPF record. Messages from that service use the subdomain as the envelope sender, so its lookups no longer count against your main record. With DMARC's default relaxed alignment, news.example.com still aligns with example.com in the From address.

news.example.com. IN TXT "v=spf1 include:servers.mcsv.net -all"

5. Flatten, carefully

Flattening replaces includes with the IP ranges they resolve to. It works, but providers change their ranges, and a stale flattened record silently fails mail from new addresses. Only flatten with a tool that re-checks and updates the record automatically, and keep includes for providers known to change often.

Things that do not work

Splitting SPF across two TXT records gives you two records, which is its own permerror. Putting the overflow in a second record and using redirect= still counts every lookup. And +all "fixes" the error by authorising every server on the internet.

Check again

After you publish the change, wait for the old record's TTL to expire and run the domain check again. It queries Google and Cloudflare separately, so you can also see whether both have picked up the new record. Aim to stay at 8 or below to leave room for your providers to grow.

Guidance on this site is checked against the RFCs and live DNS. About the author.