Error guide / SPF PermError: too many DNS lookups
SPF PermError: too many DNS lookups
PermError is what an SPF check returns when the record cannot be evaluated at all, and by far the most common reason is the lookup limit. RFC 7208 allows a maximum of 10 DNS-querying terms per SPF evaluation: include, a, mx, ptr, exists and redirect each cost one, while ip4, ip6 and all cost nothing. Go over 10 and the result is a permanent error, and the correct receiver behaviour is to treat the whole record as invalid, so every sender you carefully authorized stops counting at once. You meet it as mail from your domain being rejected or filed as spam, or as a permerror line in a message header, a DMARC aggregate report or a deliverability dashboard.
Check your site
What causes it
Almost always you crossed the line by adding vendors. Every include: you add for a helpdesk, a CRM or a newsletter tool costs one lookup of its own plus every lookup inside that provider's policy, because the count is recursive: their include of an include lands in your budget of 10. The second cause takes no action from you at all, a provider enlarges their own published policy and a record that cost 9 lookups yesterday costs 11 today. Less often the record is padded with a: and mx: terms for servers that have fixed addresses, or with a ptr term, which costs a lookup and is deprecated.
How to fix it
- Run the check on this page for your domain and read the number it prints. It expands your SPF record, follows every include: and redirect= recursively, and reports the total DNS lookups the record costs against the limit of 10. If it says 10 or fewer, the lookup limit is not your problem and you should look elsewhere: two v=spf1 records on the same domain, a syntax error, or more than two lookups pointing at names that do not exist (void lookups are also a PermError). If it says 11 or more, this is definitively the cause and the steps below are the fix.
- Delete the includes for services you no longer send from. Write out every include: in the record and match each one to a live sender; the CRM you trialled two years ago and the hosting company you left are usually still in there, and they are the cheapest lookups to buy back.
- Replace lookup-costing terms with literal addresses. ip4, ip6 and all are free, so a provider that publishes four sending ranges drops from several lookups to zero (this is called flattening), a: or mx: for a server with a fixed address is cheaper written as ip4, and a ptr term should simply be removed. The honest trade-off: hard-coded ranges go stale when a provider changes infrastructure and nothing warns you, so review them on a schedule and only flatten providers who publish a stable, documented list.
- Consolidate senders. Two newsletter platforms, or a CRM that can relay through the mail provider you already authorize, cost you a whole include each; moving to one provider removes the lookups permanently instead of shaving them.
- Move bulk mail to a subdomain. news.example.com or mail.example.com gets its own SPF record and its own budget of 10 lookups, so the marketing platform's include lives there instead of on your main domain. In the platform's settings point the envelope sender (Return-Path) at the subdomain, because SPF is checked against that domain and not the From: header, and note that DMARC's default relaxed alignment accepts a subdomain of your domain while strict alignment (aspf=s) does not.
- Only after all that, consider an SPF flattening service. It resolves the includes for you and keeps a generated record current, which does work, but your mail delivery now depends on someone else's uptime and on a record you no longer read, and a free tier that quietly stops updating shows up as bounced mail. After any edit, wait out the DNS TTL and run the check again to see the new number.