Skip to content

SecurityPart of: Email authentication

Multiple SPF records and the 10-lookup limit: how to fix SPF PermError

Multiple SPF records on one domain make SPF fail for every message, and so do more than 10 DNS lookups. How to merge two SPF records into one, count your lookups, and bring the count back under 10.

getReport teamUpdated 26 Sept 202610 min read

A domain may have only one SPF record. With multiple SPF records, receivers stop with a permanent error (PermError) and treat your domain as having no valid SPF at all, and the same happens when your one record needs more than 10 DNS lookups. The fix for both is the same kind of edit: merge everything into a single TXT record that starts with v=spf1, then remove or replace entries until the lookup count is 10 or less.

This guide is for anyone whose checker, bounce or DMARC report says "multiple SPF records", "SPF PermError" or "too many DNS lookups". You will end with one valid record and a way to keep it that way. For what each part of an SPF record means, see the SPF record syntax guide; for how SPF fits with DKIM and DMARC, the SPF, DKIM and DMARC setup guide.

Quick answer

  • Find every SPF record: dig +short TXT example.com | grep spf1. More than one line is the problem.
  • Merge them: one v=spf1 at the start, every include:, ip4: and ip6: from both records once, and a single ~all at the end.
  • Count lookups: each include, a, mx, ptr, exists and redirect costs one, and so does every one of those inside an included record. The limit is 10.
  • To get under 10: remove services you no longer use, drop includes a service does not need, replace a and mx with ip4: ranges, and move bulk senders to a subdomain.
  • Check the result with the free email and DNS health check, which follows every include and reports the total.

Why multiple SPF records break SPF

RFC 7208, the SPF standard, is explicit: when a receiver finds more than one TXT record starting with v=spf1 at a domain, the result is permerror. It does not pick one or combine them. Your mail then fails SPF from every server, including the legitimate ones.

Only records that start with v=spf1 count. Other TXT records at the same name, such as google-site-verification=… or a domain verification string for Microsoft 365, are ignored by SPF and can stay. And an SPF record at www.example.com or news.example.com belongs to that name, not to the root, so it is not a duplicate.

The second record almost always comes from an addition, not a mistake in the original:

  • a new email provider's setup wizard that says "add this TXT record" without checking for an existing one;
  • a web host that created a default SPF record when the domain was registered;
  • a DNS move where records from two zones were combined;
  • a marketing tool whose instructions show a full record instead of just the include.

How to merge two SPF records

Take the two records apart and put the pieces into one:

dns
; Before: two records, so SPF fails with permerror
example.com.  TXT  "v=spf1 include:_spf.google.com ~all"
example.com.  TXT  "v=spf1 a mx include:servers.mcsv.net -all"

; After: one record
example.com.  TXT  "v=spf1 include:_spf.google.com include:servers.mcsv.net ~all"

The rules for the merged record:

  1. One v=spf1, at the very start.
  2. Every sender once. Copy each include:, ip4: and ip6: from both records; drop exact duplicates.
  3. Question the a and mx. Web hosts often add them by default. Keep mx only if your mail servers also send your outgoing mail, and a only if your web server sends mail itself.
  4. One all, at the end. If the two records disagree, use ~all while you check that every sender is listed; -all can follow later.
  5. Edit one record and delete the other. Do not leave an empty or half-edited record behind.

Then save, wait for the old record's TTL to expire, and check again. The change applies to all mail from that moment; messages already rejected are not retried.

The 10-lookup limit

RFC 7208 (section 4.6.4) limits SPF evaluation to 10 terms that trigger a DNS lookup. The count is not per record but for the whole evaluation, including every nested include. Over 10, the receiver stops with permerror, exactly as with two records.

Costs one lookup eachCosts nothing
include:, a, mx, ptr, exists:, redirect=ip4:, ip6:, all
... and the same terms inside every included recordOther TXT records at the domain

Two further limits in the same section catch fewer domains:

  • An mx or ptr term that returns more than 10 host names is itself a permerror.
  • More than two void lookups, lookups that return no answer or a name that does not exist, also end in permerror. Includes for services you cancelled, whose SPF records have since been deleted, are the usual cause.

Counting a real record

Here is a record for a domain using Google Workspace, Mailgun and Salesforce, with the costs as they were when we looked them up in September 2026:

dns
example.com.  TXT  "v=spf1 include:_spf.google.com include:mailgun.org include:_spf.salesforce.com mx ~all"
TermLookupsWhy
include:_spf.google.com1Google's record lists IP ranges directly
include:mailgun.org5The include, plus four nested includes, two levels deep
include:_spf.salesforce.com2The include, plus an exists term inside it
mx1One lookup for the MX records
Total91 left

Providers change their records without notice, so a record at 9, like this one, can be at 11 next year with no edit on your side. Count with a tool, not from memory.

How to fix "SPF too many DNS lookups"

Work through these in order; the first two usually suffice.

1. Remove services you no longer use. Old newsletter tools, a previous email host, a helpdesk you replaced. Each costs at least one lookup, and a cancelled service's include can also produce void lookups.

2. Drop includes a service does not need. Many sending services use their own bounce address (the envelope sender that SPF checks), so SPF is checked against their domain, not yours, and your include does nothing. They authenticate your domain with DKIM instead. Newsletter and transactional tools often work this way; check the service's current setup page before removing it, and keep the include only if the service asks for one.

3. Replace a and mx with addresses. If your web or mail server does send mail, list its address with ip4: or ip6: instead, at no lookup cost. Update the record if the address changes.

4. Drop ptr. RFC 7208 says not to use it: it is slow and unreliable, and it costs lookups.

5. Move a sender to a subdomain. Send newsletters from news.example.com and give that subdomain its own SPF record. Under DMARC's default relaxed alignment, mail from news.example.com still aligns with example.com, and the root record gets shorter.

6. Flatten, with care. "Flattening" replaces includes with the ip4: and ip6: ranges they currently resolve to. It gets you to one lookup, but the ranges go stale when the provider changes them, and your mail starts failing without warning. Only flatten with a service that re-checks and updates the record automatically, and never flatten a provider that uses exists or macros, like Salesforce above.

Do not use redirect= to dodge the limit: it costs a lookup too, and the redirected record's terms count towards the same 10.

What happens to your mail meanwhile

A permerror does not automatically mean every message bounces. Receivers treat it as a failed SPF check, and DMARC can still pass through DKIM. If all your services sign with DKIM for your domain, most mail keeps getting through; if some rely on SPF alone, their mail fails DMARC and is quarantined or rejected under a strict policy. Bounces such as "554 5.7.5 permanent error evaluating DMARC policy" often trace back here; the guide to the 554 5.7.5 DMARC error covers the other causes.

DKIM on every sending service is also what makes SPF problems survivable in future, so switch it on wherever it is missing.

Check your SPF record

The check reads every TXT record at your domain, flags more than one SPF record, follows each include and redirect to the end and reports the total lookups, include loops and includes whose target has no SPF record. When it passes, it shows the count, for example "valid (7 of 10 DNS lookups)".

From a terminal:

Shell
dig +short TXT example.com | grep spf1
dig +short TXT _spf.google.com

The second command shows what one include contains, so you can see whether it pulls in further includes.

Platform notes

  • Google Workspace: the include is include:_spf.google.com. The Google Workspace SPF, DKIM and DMARC guide has the full setup.
  • Microsoft 365: the include is include:spf.protection.outlook.com; see the Microsoft 365 SPF, DKIM and DMARC guide.
  • Cloudflare DNS: TXT records are never proxied, so SPF is unaffected by the orange cloud. Enabling Cloudflare Email Routing adds an SPF record with include:_spf.mx.cloudflare.net; if you already had one, merge the two.
  • Long records: a TXT string holds at most 255 characters. A longer record is split into several quoted strings in one record, which receivers join. Keep the whole record short anyway; very long records are harder to maintain.

Questions people ask

How do I add multiple senders to my SPF record?

Add each sender's include: to your one existing SPF record instead of creating a new one: v=spf1 include:_spf.google.com include:mail.zendesk.com ~all. Two separate SPF records make both invalid. Watch the total of 10 DNS lookups across all includes, and check whether a service really needs an include; many newsletter tools only need DKIM.

What does SPF PermError mean?

It means the receiver could not evaluate your SPF record at all, because of a permanent problem in it: two SPF records, more than 10 DNS lookups, more than two lookups that return nothing, or a syntax error. Receivers treat it as an SPF failure for every message. Merge or trim the record until a checker reports it valid.

How do I fix too many DNS lookups in SPF?

Remove includes for services you no longer use, drop includes for services that authenticate with DKIM and their own bounce domain, replace a and mx with the ip4: addresses they stand for, and move bulk senders to a subdomain with its own record. Flattening includes into IP ranges works only with a service that keeps them updated.

Is SPF flattening safe?

Only when something keeps it current. Flattening replaces includes with the IP ranges they point to, which saves lookups, but providers change their ranges without notice, and a stale flattened record makes real mail fail SPF. Use an automated flattening service or avoid it. Removing unused includes and moving senders to subdomains are safer ways to get under 10.

Do ip4 and ip6 entries count towards the SPF lookup limit?

No. ip4: and ip6: entries are matched directly against the sending address without any DNS query, so they cost nothing, and neither does all. Only include, a, mx, ptr, exists and redirect count, together with the same terms inside included records. Very long lists of addresses make the record harder to maintain, though.

Check your site before and after Check