SPF returns PermError: too many DNS lookups when checking your record forces a receiving server through more than ten lookup-causing terms: include, a, mx, ptr, exists and redirect. Every lookup inside an included record counts against your ten as well. It typically appears right after someone adds a CRM, helpdesk or marketing tool to a record that already covers Google Workspace or Microsoft 365. Fix it in this order: count where the lookups come from, delete senders you no longer use, drop includes for tools that never put your domain in the Return-Path, then move the new sender to a subdomain. Flattening comes last, not first.
This guide is based on RFC 7208 (SPF), RFC 9989 (the DMARC standard that replaced RFC 7489 in May 2026), Google's and Microsoft's current SPF documentation, and the setup pages of each sender named below, all checked October 16, 2026. We also queried public DNS that day to count what each provider's include currently costs. We have not tested these changes on a private domain or inside any vendor account. Providers change their records without notice, so recount yours before you edit DNS.
What counts toward the ten
RFC 7208, section 4.6.4 caps the terms that cause DNS queries at ten per SPF evaluation. Exceeding it must produce permerror.
| Term in your record | Counts toward 10? | What to know |
|---|---|---|
include: |
Yes, plus every lookup term inside the included record | A vendor's nested includes are charged to your domain |
a, mx |
Yes, one each | An mx term also returns permerror if one MX lookup leads to more than ten address lookups |
exists |
Yes | Common in macro-based vendor records |
ptr |
Yes | Section 5.5 says it should not be published at all |
redirect= |
Yes | Hands the whole check to another domain's record |
ip4, ip6, all |
No | No DNS query at evaluation time |
exp= |
No | Only looked up later, for an explanation message |
Three related problems produce the same error label. The same section says receivers should allow no more than two void lookups (queries that return no answer or a nonexistent domain), typically caused by a term pointing at a vendor domain that no longer exists. Section 5.2 turns an include whose target has no SPF record into permerror. And publishing two v=spf1 records at one name returns permerror under section 4.5, which often happens when someone adds a vendor's record as a new TXT record instead of merging it.
Why only some messages fail
The limit applies "during SPF evaluation." Microsoft's SPF setup guide explains that receivers check sources left to right and stop at the first match. Workspace mail that matches your first include can keep passing, while a sender listed late in the record, or an unlisted source, crosses ten and gets permerror. Checkers that add up the whole tree, ours included, report a worst case. Treat any total above ten as a defect anyway: the failures land on the mail that is hardest to trace.
What common sender includes cost right now
What matters is how many lookups each include expands into. We counted these through public resolvers on October 16, 2026, around 15:30 UTC; treat them as a dated snapshot.
| Sender | What its current docs ask for | Lookups added | Note |
|---|---|---|---|
| Google Workspace | include:_spf.google.com (Google) |
1 | Some older guides count four. On October 16 the record listed Google's ranges directly, with no nested includes. |
| Microsoft 365 | include:spf.protection.outlook.com (Microsoft) |
1 | Microsoft says not to flatten it because its IPs change frequently. |
| Zendesk | include:mail.zendesk.com (Zendesk) |
1 | Zendesk says this include must sit in the first layer of your record. |
| Freshdesk | include:email.freshdesk.com (Freshdesk) |
7 | The same page lists one record per data center, each costing 1 today, and says SPF isn't required if DKIM is set up. |
| Mailgun | include:mailgun.org on the domain you add to Mailgun (Mailgun) |
5 | Adding a sending subdomain to Mailgun keeps these off your root record. |
| Twilio SendGrid | SPF on an em#### subdomain it generates (Twilio) |
0 on your root | A root include:sendgrid.net costs 2. Check whether anything still needs it. |
| Mailchimp | Two DKIM CNAMEs and a DMARC record, no SPF step (Mailchimp) | 0 | A leftover include:servers.mcsv.net costs 1. |
| HubSpot | An account-specific include: value, when the setup prompts for one (HubSpot) |
Varies | Count the value your account shows. |
Step 1: Confirm the error and find the domain being checked
- Collect the evidence. Microsoft says a rejection can cite "The message required too many lookups" or "The message exceeded the hop count." In a delivered message, look for
spf=permerrorin the Authentication-Results header. Google's SPF troubleshooting page warns that some providers' messages wrongly claim you have no SPF record at all. - Read the Return-Path of a failing message. SPF checks the envelope sender (MAIL FROM) domain, not the From address people see. If the failing message's Return-Path is a vendor domain, your record isn't the one failing.
- Confirm there is exactly one
v=spf1TXT record at that domain or subdomain. If there are two, merge them first. Zendesk's documentation shows the merged form:v=spf1 include:_spf.google.com include:mail.zendesk.com -all.
Step 2: Count lookups per sender
Run the domain from that Return-Path through our SPF record checker. Choose Live DNS + dependency inspection, enter the domain and select Check published SPF. The Expanded lookup terms total and the Record and dependency trace show what each include costs. The tool counts the whole tree, stops at 20 TXT queries and does not test void lookups, so treat a partial result as unknown. Google points to the Check MX tool in its Admin Toolbox for the same count.
To check by hand, run dig +short TXT example.com, then repeat for each include or redirect target and its own includes. Add one for every lookup term at every level. A target reached twice is counted twice.
Then list each sender with its owner, include, lookup cost, whether it still sends, its Return-Path domain and its DKIM signing domain. The last two decide which fix applies; DMARC aggregate reports help fill the gaps.
Step 3: Apply fixes from safest to riskiest
1. Delete senders that no longer send
Google says to remove includes for third parties that no longer send for your domain, and to remove duplicates. Typical candidates are a replaced helpdesk, a previous email platform, a former agency's tool, or an a or mx term left from a retired server. Watch for hidden duplicates: Freshdesk's include already contains sendgrid.net, so a separate root include:sendgrid.net can be charged twice. Confirm with the tool's owner and your DMARC reports first; a source that still appears there is not dead.
2. Remove includes your Return-Path never uses
An include helps SPF only when the vendor sends with the domain you are editing in MAIL FROM. Mailchimp says its envelope sender usually contains its own domains, such as mcsv.net or mcdlv.net (source). Twilio SendGrid's domain authentication places SPF on its em#### subdomain. In both cases a root include adds cost and no SPF benefit.
DMARC can still pass. Under RFC 9989, an aligned SPF result or an aligned DKIM signature produces a pass, and section 8 says p=reject domains must not rely on SPF alone. Publish the vendor's DKIM records so it signs as your domain; Freshdesk says SPF isn't required once DKIM is set up. Confirm dkim=pass for your domain in a test message's headers, and use our DKIM checker to confirm the selector is published. For background on alignment, see SPF, DKIM and DMARC explained.
Some vendors rely on the include. Zendesk needs it, in the first layer, to send as your domain instead of identifying the sender as zendesk.com, and HubSpot prompts for its value during setup. For those, use fix 3 or 4.
3. Use the provider's leaner documented record
Freshdesk lists data-center records (fdspfus.freshemail.io for the US, plus EU, India and Australia versions) for accounts whose SPF uses too many lookups. In our October 16 count, that swap cut the cost from seven lookups to one. Only use a narrower record the vendor documents; don't build your own from their DNS.
4. Move the sender to a subdomain
Microsoft recommends subdomains such as marketing.contoso.com for email services you don't directly control, and states that each subdomain has its own 10-lookup budget. The subdomain needs its own SPF record because SPF is not inherited. DMARC is: Microsoft notes subdomains inherit the parent's policy unless overridden, and RFC 9989 makes relaxed alignment the default, so mail from news.example.com signed as example.com still aligns. The trade-off is a visible change of From address. That's fine for newsletters and product mail, and awkward for support replies, where fix 2 or 3 is usually better.
Cold outreach often goes a step further: separate sending domains. In a May 2023 walkthrough, Jan advised setting up SPF, DKIM and DMARC on every sending domain and buying secondary domains for outreach to protect the main domain's deliverability. His example was a separate lookalike domain, not a subdomain, and it is dated reputation advice rather than a lookup test. A sequencer that sends through connected mailboxes may not need its own include: Instantly's DNS setup guide tells you to take the SPF value from your mailbox provider and lists no Instantly-specific include. OutboundXYZ has an affiliate relationship with Instantly (our review); it did not influence these steps. For sourcing domains and mailboxes, see our cold email mailbox providers comparison.
5. Replace an include with IPs only where they are documented and stable
Microsoft suggests ip4:/ip6: values only when a vendor publishes a stable, documented set of sending addresses, and says you must then monitor for changes. That fits your own fixed-IP server, not Microsoft 365, which Microsoft says not to flatten. Google's include costs one lookup today, so replacing it gains nothing. Google warns against broad shared cloud ranges and notes the 255-character string limit. RFC 7208 section 3.4 adds that SPF answers too large for a single UDP packet could be silently ignored by some verifiers.
6. Treat flattening as a last resort
Flattening replaces includes with the IP addresses they resolve to, copying data you don't control. When a vendor adds a range, its legitimate mail starts failing SPF with no change on your side. Microsoft says to document what you replaced, monitor vendor changes, review at least quarterly and test after each change. Zendesk says flattening works but may be less stable than its include. A hosted flattening service automates the tracking, but adds another vendor to your mail path.
Worked example (illustrative)
The domain and history below are invented; the lookup counts use the October 16, 2026 DNS snapshot. example.com runs Google Workspace, and its record has grown to:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:sendgrid.net mx ~all
That costs five lookups: Google 1, Mailchimp 1, SendGrid 2, mx 1. Support switches on Freshdesk and appends its documented include:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:sendgrid.net mx include:email.freshdesk.com ~all
Freshdesk's include expands to seven, so the total is twelve. Workspace mail still passes at the first include; mail matching only near the end of Freshdesk's chain, and any unlisted source, now gets permerror.
The cleanup, with the evidence each step needs:
- A Mailchimp test campaign shows a Mailchimp Return-Path and a passing DKIM signature for
example.com: removeinclude:servers.mcsv.net. - A SendGrid test shows its
em####subdomain as Return-Path: remove the rootinclude:sendgrid.net. - MX points to Google, and nothing else sends from those hosts: remove
mx. - The Freshdesk account is in the US data center: swap to Freshdesk's US record.
v=spf1 include:_spf.google.com include:fdspfus.freshemail.io ~all
Two lookups, with room for the next tool. If any check had gone the other way, that sender would belong on a subdomain instead.
| Situation for one sender | Best first move | Avoid |
|---|---|---|
| Vendor uses its own Return-Path | Remove root include, publish vendor DKIM | Assuming the include makes DMARC pass |
| Vendor documents a smaller record | Use that record | Inventing a narrower one |
| Bulk or marketing service | Subdomain with its own SPF and DKIM | Adding it to the root |
| Cold outreach mailboxes | Separate domains, mailbox provider's SPF only | Sending cold email from the root domain |
| Nothing else fits | Monitored flattening | Hand-flattening Google or Microsoft |
Verify the fix
- Recheck the domain in the SPF record checker. The total should be ten or fewer, and every include should resolve.
- Allow for caching. Google says SPF changes can take 24 to 48 hours to take effect globally.
- Send a test from every sender, not just the new one, to a Gmail and an Outlook mailbox. In Authentication-Results, look for
spf=passon the Return-Path domain ordkim=passwith your domain, anddmarc=pass. - Watch DMARC aggregate reports for new failures. The DMARC checker confirms you publish a report address. If you run several domains, our DMARC monitoring tools comparison covers ongoing visibility.
Before the next tool goes live, count its include first.
Frequently asked questions
What counts toward the SPF 10 DNS lookup limit?
The include, a, mx, ptr and exists mechanisms and the redirect modifier, including those inside nested includes, per RFC 7208 section 4.6.4. ip4, ip6 and all don't count.
Is SPF flattening safe?
It works until a provider changes its IPs; then legitimate mail fails SPF until someone updates the record. Use it only after removing dead senders and moving bulk senders to subdomains, with a documented review schedule.
Do I need to add my cold email tool to SPF?
Usually not when it sends through connected Google Workspace or Microsoft 365 mailboxes; each sending domain publishes the mailbox provider's include. Check the tool's DNS guide, and keep outreach on domains separate from your main one.
What happens when an SPF record exceeds 10 lookups?
The check returns permerror. Handling varies: Microsoft says the message can be rejected, and because SPF didn't pass, DMARC depends on an aligned DKIM signature. Switching -all to ~all doesn't help; the error comes from the lookup count. For the wider picture, see our email authentication protocols guide.

