Domain Health · SPF · Lookup limit
SPF "too many DNS lookups": a worked fix
Over 10 lookups and SPF returns permerror for every message, including your real ones. Here's one record counted line by line, then cut to 7 with no flattening and no new service.
What counts
- Cost one lookup each:
include,a,mx,ptr,existsandredirect. - Nested records count too. Each
includecosts one, plus every lookup inside the record it points to, and so on down. - Free:
ip4,ip6andall. - Void lookups: an include or
athat finds no record at all. More than 2 of those is also apermerror(RFC 7208, section 4.6.4). A tool you cancelled years ago often leaves one behind.
A worked example
A small business with hosted mail, a CRM, a newsletter tool and a help desk. All names are examples:
example.com TXT "v=spf1 a mx include:_spf.mailhost.example include:spf.crm.example include:send.newsletter.example include:mail.helpdesk.example ~all"
| Term | Lookups | Why |
|---|---|---|
a | 1 | Looks up example.com's own address |
mx | 1 | Looks up example.com's MX hosts |
include:_spf.mailhost.example | 4 | 1, plus 3 nested includes inside it |
include:spf.crm.example | 2 | 1, plus 1 nested include |
include:send.newsletter.example | 1 | Only ip4 ranges inside |
include:mail.helpdesk.example | 2 | 1, plus 1 nested include |
| Total | 11 | One over: permerror |
The checker above follows every include and shows this count for your real record. Providers change their nested records, so a record that counted 9 last year can count 11 today without you touching it.
Fixes, safest first
1. Remove includes for tools you no longer use (−2 here)
The help desk was replaced last spring. Its include stayed. Delete it. Ask whoever set up each tool before removing anything you don't recognise.
2. Remove a and mx if those hosts don't send (−2 here)
a authorises your website's server; mx authorises the servers that receive your mail. With hosted mail, outgoing mail leaves through the provider's servers, which include:_spf.mailhost.example already covers. Unless your web server sends mail itself (a contact form sending directly, for example), both terms are dead weight. If the web server does send, list its fixed address with ip4: instead, which costs nothing.
3. Check whether a tool needs your SPF record at all
SPF is checked against the message's Return-Path (bounce) domain, not the From domain. Send yourself a test from each tool and read the Return-Path header. If it's the tool's own domain, or a subdomain you set up for it such as bounces.example.com, the include on your root record is never used for that tool's mail: remove it, and make sure the tool signs DKIM with your domain so DMARC still passes (how alignment works). Many newsletter and CRM tools work this way.
4. Only then: flatten, carefully
"Flattening" swaps an include for the IP ranges it currently contains. It works until the provider changes its ranges, then mail from the new ranges fails SPF without warning. Use it only for IPs you control, or with a process that re-checks the ranges regularly.
After the fix
example.com TXT "v=spf1 include:_spf.mailhost.example include:spf.crm.example include:send.newsletter.example ~all"
4 + 2 + 1 = 7 lookups, with room for one more tool later. Run the checker again once the change has published (usually minutes, up to your record's TTL), and send a test from each remaining tool.
Quick reference
- Limit: 10 lookups including nested ones, and at most 2 that find nothing.
ip4,ip6andallare free;aandmxare not.- Remove dead tools first, then
a/mx, then includes the Return-Path shows aren't used. Flatten last. - Exactly one SPF record per name; two records is its own
permerror.
Related: SPF checker · SPF on a CNAME'd name · DMARC checker · Pre-holiday sending check