Skip to main content
Relaymetry

SPF PermError after adding a new sender: why a new platform broke SPF and the fix

You added a new sending platform and SPF started returning `permerror`, which means SPF no longer passes for any message from that domain. When a newly-added sender triggers it, one of two things happened: the platform's setup wizard had you add a second `v=spf1` record, and a domain may publish only one, or its `include:` pushed your record past the 10-DNS-lookup limit. A single TXT query tells you which, and the fix depends on the answer.

Quick answer

You added a new sending platform, such as an ESP, a CRM, a help desk, or a transactional service, and SPF started returning permerror. A permerror means SPF can no longer produce a pass for any message from that domain (RFC 7208 §4.5). When a newly-added sender triggers it, one of exactly two things happened. Either the platform's setup wizard told you to add a second TXT record beginning with v=spf1, and a domain may publish only one (RFC 7208 §4.5), or the platform's include: pushed your existing record past the 10-DNS-lookup limit (RFC 7208 §4.6.4). The fix depends on which one, and you can tell them apart with a single TXT query.

The two ways a new sender breaks SPF

The trigger is the same in both cases: you onboarded a platform and followed its DNS instructions. The failure mode is not.

The first mode is a second v=spf1 record. Many setup wizards present a ready-to-paste SPF record. Google Workspace, for example, documents v=spf1 include:_spf.google.com ~all and tells you to add it as a new TXT record. If your domain already had an SPF record, you now have two. A receiver that finds more than one v=spf1 record at the same name returns permerror and evaluates neither (RFC 7208 §4.5). The new platform is authorized in its own record, but that authorization is never read.

The second mode is the 10-lookup limit. If you correctly merged the new include: into your existing single record, you avoided the duplicate problem, but every include: you add expands into its own chain of DNS queries. RFC 7208 §4.6.4 caps the number of DNS-querying mechanisms (include, a, mx, ptr, exists, and the redirect modifier) at 10 per evaluation, and requires permerror when that count is exceeded. A domain sitting at eight or nine lookups can be tipped over by one new platform whose include: resolves three levels deep.

The distinction matters because the two modes have different fixes. A duplicate record is removed by merging and deleting. A lookup overflow is removed by reducing the number of querying mechanisms. Doing the wrong remediation leaves the permerror in place.

How to diagnose which mode you hit

Query every TXT record at the affected name and read the result before changing anything. On Windows, run nslookup -q=TXT example.com. On macOS or Linux, run dig TXT example.com. Substitute the domain that appears in the return-path of the failing messages — SPF is evaluated per DNS name, so if the bounce names a subdomain like mail.example.com, query that name, not the apex.

In the output, count how many TXT records begin with v=spf1:

  • More than one means you are in the first mode. The new platform's record was added alongside the old one instead of merged into it. Other TXT records, such as a DMARC policy, DKIM keys, or a domain-verification string, do not count. Only the v=spf1 prefix does.
  • Exactly one means you are in the second mode, or close to it. Take the single record and count its DNS-querying mechanisms, expanding every include: into the mechanisms it resolves to. Add up every include, a, mx, ptr, and exists across the whole expansion. If the total is above 10, the new sender pushed you over.

If you find exactly one record and the expanded count is at or under 10, the new sender is not the cause of a limit or duplicate permerror, and you should look instead at a syntax error introduced while editing the record.

How to fix it

  1. Run the TXT query above and decide which mode you are in by counting v=spf1 records.

  2. If you have more than one record, collect every legitimate mechanism from all of them. That means the new platform's include:, the existing platform's include:, and any real ip4: or ip6: addresses. Discard mechanisms from providers you no longer use.

  3. Write one merged record containing those mechanisms followed by a single all qualifier. For a domain that sends through Google Workspace and a new ESP, the merged record looks like this:

    v=spf1 include:_spf.google.com include:newesp.example.net -all
    
  4. Update one existing v=spf1 record to hold the merged value, then delete every other v=spf1 record at that name until exactly one remains.

  5. If you have exactly one record and the expanded lookup count is over 10, reduce the number of DNS-querying mechanisms. Move a stable-IP vendor from its include: to explicit ip4: and ip6: entries, move the new platform to its own subdomain (each name has its own 10-lookup budget), or drop providers you no longer use. The generic remedies are covered in the SPF too many DNS lookups guide.

  6. Note the TTL of the record and wait one full TTL cycle, often between one and twenty-four hours, before testing, because receivers may still serve the old records from cache.

  7. Re-query the name, confirm exactly one v=spf1 record is visible and its expanded lookup count is 10 or fewer, then send a test message and read the Authentication-Results header for spf=pass.

What this does not prove

A public TXT check reads the records published at your domain and tells you how many begin with v=spf1 and how many DNS lookups the single record expands into. That is enough to identify which of the two failure modes a new sender caused, and to confirm the count after you fix it.

It cannot tell you whether the merged record authorizes the right sending IPs for your actual outbound streams, whether a specific past delivery returned permerror for this reason rather than a syntax error, or whether DKIM and DMARC are passing and aligned. For those answers you need message headers from a real send, your DMARC aggregate report feed, and a list of every platform that sends on your domain's behalf. Clearing the permerror removes one failure mode; it does not on its own guarantee that SPF will pass.

Frequently asked questions

I just added a new email platform and SPF broke. What actually happened?

One of two things. Either the platform told you to add a second TXT record beginning with `v=spf1`, and a domain may publish only one before receivers return `permerror`; or the new `include:` pushed your single record past the 10 DNS-lookup limit, which also returns `permerror`. Query your TXT records and count how many begin with `v=spf1` to tell the two apart.

The new platform is authorized in its own SPF record. Why does mail still fail?

Because when a receiver finds more than one `v=spf1` record at the same name, it returns `permerror` without evaluating the content of either record. The authorization in the new platform’s record is never read. Both records must be merged into one before evaluation can proceed.

I merged the new include into my existing record, so why am I still getting permerror?

Merging avoids the duplicate-record problem but not the lookup-limit problem. Every `include:` expands into its own chain of DNS queries, and RFC 7208 §4.6.4 caps the total at 10 DNS-querying mechanisms per evaluation. If the new platform’s `include:` tipped your expanded count above 10, you get `permerror`. Count the lookups across the full expansion, not just the visible `include:` count.

Which mechanisms count toward the 10-lookup limit?

The `include`, `a`, `mx`, `ptr`, and `exists` mechanisms and the `redirect` modifier each count. `ip4:`, `ip6:`, and `all` do not, because they require no DNS query. A nested `include:` that points to a record with three more `include:` statements adds four lookups, not one, which is why a record with only a few visible includes can still exceed 10.

Can the new sender only break SPF on a subdomain?

Yes. SPF is evaluated independently at each DNS name. If you added the new platform on a subdomain like `send.example.com`, that name hits `permerror` while the apex stays clean. Query the specific domain that appears in the return-path of the failing messages, because that is the name each delivery stream is evaluated against.

Other email authentication problems

References

Browse all guides →