Siftsmith
← All guides

Fix “multiple SPF records” (SPF PermError)

A domain may publish only one SPF record. With two or more, receivers return permerror and SPF passes for none of your mail, including mail from servers both records list. See every v=spf1 record your domain publishes below, get one merged record with its DNS lookup count, and check the fix with dig or nslookup.

Last verified 1 October 2026.

What the error means

SPF lives in a TXT record on the domain itself (example.com) and starts with v=spf1. A receiving server fetches every TXT record at that name, keeps those that begin with v=spf1, and needs exactly one. RFC 7208, the SPF standard, is explicit:

Receivers don’t pick one or combine them. Microsoft’s SPF documentation says multiple SPF records “cause SPF to return permerror (the receiving system can’t determine which record to evaluate)”. A permerror is not a pass, so DMARC can only pass on an aligned DKIM signature, and mail without one fails DMARC and is handled by your p= policy. Gmail, Yahoo and Outlook.com all require SPF from bulk senders (see the bulk sender requirements), and Outlook.com’s 550 5.7.515 bounce is a common symptom.

Sources: RFC 7208 §3.2, §3.3, §4.5 and §6.1; Microsoft Learn, Set up SPF to identify valid email sources for your Microsoft 365 domain; Google Workspace Admin Help, Set up SPF (checked 1 October 2026).

See every SPF record on your domain

Enter the domain in your From: address (or the envelope sender, if it differs). The lookup runs in your browser against public DNS, lists every TXT record that starts with v=spf1 plus near misses receivers ignore, and builds one merged record with its lookup count.

This reads what your DNS publishes right now through Cloudflare’s public resolver, or Google’s when Cloudflare’s fails. If you just changed a record, an old answer can stay cached until its TTL runs out. For the full A–F grade with DMARC, DKIM, MTA-STS, BIMI and DNSSEC, use the DMARC checker.

What counts as multiple records, and what doesn’t

Two TXT records on the domain that both start with v=spf1Multiple records: permerror. Even when the two are identical. The version tag is case-insensitive, so V=SPF1 counts too.
One TXT record made of several quoted stringsFine. Receivers join the strings with no space added (RFC 7208 §3.3): "v=spf1 include:_spf.google.com " "~all" is one record. Keep a space at the end of a string or the start of the next, or two terms run together.
v=spf10, spf2.0/pra, or a record with a space before v=spf1Not SPF. The record must begin with exactly v=spf1 followed by a space or the end of the record (§4.5), so these are discarded and don’t count. They don’t authorize anything either.
One v=spf1 record plus verification tokens (google-site-verification=…, MS=…)Fine. Other TXT records are ignored by SPF.
One record on example.com and one on mail.example.comFine. Different names, and each sending name needs its own.

Why it happens

A new sender was added as a second record

The most common cause. You start sending through a marketing tool, CRM, help desk or booking system, and its setup guide says “add this TXT record: v=spf1 include:… ~all”. Adding it as a new record next to the one your mail provider needs creates the duplicate. The fix is to add the new include: to the existing record instead.

A provider switch or a host default

Moving from one mail provider to another and adding the new provider’s record without removing the old one. Some web hosts and registrars also publish a default SPF record (often v=spf1 a mx ~all) that sits next to the one you add later.

One record pasted as two

A long record entered as two separate TXT records instead of one record with two strings. If both halves start with v=spf1, that’s the error; if only the first does, the second half is silently ignored and the servers in it fail SPF.

Merge them into one record

Say example.com uses Microsoft 365 and a booking system that told you to add its own record:

v=spf1 include:spf.protection.outlook.com ip4:203.0.113.10 -all
v=spf1 include:spf.protection.outlook.com include:_spf.booking.example -all

Replace both with one:

v=spf1 ip4:203.0.113.10 include:spf.protection.outlook.com include:_spf.booking.example -all
  1. Start with v=spf1, once.
  2. Take every mechanism from every record, once each: ip4: and ip6: ranges first (they cost no DNS lookups), then a, mx and include:. Drop exact duplicates.
  3. End with exactly one all. If the records agree, keep theirs. If one says -all and another ~all, use ~all until your DMARC reports show every legitimate sender passing, then move to -all. Never use +all: it authorizes every server on the internet.
  4. Turn any redirect= into include:. A record with an all mechanism ignores redirect= (§6.1), so redirect=_spf.example.net becomes include:_spf.example.net. Keep at most one exp=.
  5. Count the DNS lookups. Every include, a, mx, ptr and exists counts, including those inside included records, and the limit is 10. Two records that were each under the limit can be over it once merged: see how to fix “too many DNS lookups”.
  6. Edit the existing record to the merged value and delete the others. Editing in place avoids a moment with no SPF record at all.

Provider includes

Verify the fix

From a terminal on macOS or Linux:

dig +short TXT example.com | grep -i 'v=spf1'

You want exactly one line. One line with several quoted parts is one record split into strings, which is fine. Two lines is the error. On Windows:

nslookup -type=TXT example.com

Each record appears as its own text = entry; exactly one should start with v=spf1. To skip your local cache:

dig +short TXT example.com @1.1.1.1
dig +short TXT example.com @8.8.8.8

If the old record still shows, the resolver is serving a cached answer: wait for its TTL to expire and check again, or run the checker above. Then send a test message to a Gmail address and look for spf=pass in “Show original”.

FAQ

Can I have two SPF records, one for each email provider?

No. A domain can publish exactly one TXT record that starts with v=spf1. To authorize a second provider, add its include: term to the existing record, for example v=spf1 include:_spf.google.com include:spf.protection.outlook.com ~all.

Is an SPF record split into several quoted strings the same as multiple records?

No. One TXT record can hold several strings, and receivers join them with no space added (RFC 7208 §3.3). It is still one record. Make sure a space sits at the end of one string or the start of the next, or two terms run together.

Does merging two SPF records change the DNS lookup count?

The merged record needs the lookups of both records combined, minus any include, a or mx term they shared. If that comes to more than 10, the merged record is a permerror too, so check the count before you publish. The checker above shows it.

Should the merged record end in -all or ~all?

If both records ended the same way, keep it. If they differed, start with ~all: while the duplicates were live no record was being applied, and -all could reject mail from a sender you haven’t tested. Move to -all once DMARC reports show all your legitimate mail passing SPF.

Do subdomains need their own SPF record?

A subdomain that sends mail needs its own record, because SPF is checked on the exact domain in the envelope sender. The one-record rule applies per name: example.com and mail.example.com can each have one v=spf1 record.

Checking many domains?

If you manage domains for clients or brands, Email Security Signals checks a whole list and returns one row per domain with SPF, DKIM, DMARC and an A–F grade. Duplicate SPF records show up as a high-severity spf_multiple_records issue, with the count in spf.recordCount, ready to filter in a CSV export. $0.02 per graded domain ($20 per 1,000); invalid inputs, domains that don’t exist, DNS lookup failures and duplicates are free.

Check a list on the Apify Store →

Related: fixing SPF “too many DNS lookups”, fixing “multiple DMARC records found” and fixing Outlook’s 550 5.7.515 bounce.