How to Set Up SPF for Cold Email Without Exceeding the Lookup Limit

The Sendvanta Team · September 23, 2026 · 11 min read

A domain can pass every DNS checker you throw at it and still fail SPF at the receiving server. The usual reason: the record needs more than 10 DNS lookups to evaluate, so the receiver stops resolving, returns a permerror, and treats the result as if SPF were misconfigured — which, technically, it is. Nothing in your DNS panel turns red. Your emails just quietly start doing worse.

This bites cold email senders harder than anyone else, because the domains most likely to be over the limit are the ones that have collected a decade of SaaS includes: a CRM, a help desk, a newsletter tool, an old transactional provider nobody has logged into since 2021. Then someone points an outbound campaign at that domain and wonders why the opens look fine but replies never come.

Here's how the limit actually works, how to count yours in five minutes, and four ways to get back under it without breaking anything else your company sends.

What the 10-lookup limit actually is

RFC 7208 section 4.6.4 says an SPF evaluation may trigger at most 10 DNS-querying mechanisms. It is not 10 include statements — it is 10 lookups across the entire recursive evaluation, including every lookup triggered inside the records you include. One include that points to a record containing three more includes costs you four, not one. This is why people count four entries in their record and assume they have room to spare.

Mechanisms that count against the limit:

  • include: — one lookup, plus everything inside the included record
  • a — one lookup
  • mx — one lookup for the MX set, plus one for each MX hostname resolved
  • ptr — one lookup (and deprecated; delete it if you find it)
  • exists: — one lookup
  • redirect= — one lookup, plus the contents of the target record

Mechanisms that cost nothing:

  • ip4: and ip6: — literal addresses, no DNS query at all
  • all — terminal, no query
  • exp= — only evaluated on failure, doesn't count toward the 10

There are two more ceilings people forget. First, the void lookup limit: no more than two lookups in the chain may return NXDOMAIN or an empty answer. An include pointing at a service you cancelled — where the vendor has since deleted their _spf record — burns a void lookup. Three of those and you get a permerror even if your total is comfortably under 10. Second, a single DNS TXT string is capped at 255 characters; longer records must be split into multiple concatenated strings, and some DNS providers handle that splitting badly. Keep the whole record under roughly 450 characters and you avoid the edge cases entirely.

Count your lookups in five minutes

Pull your current record with dig +short TXT yourdomain.com and find the string starting v=spf1. Then run that record through any SPF validator that prints a recursion tree — you want the tool to show you the total lookup count and flag void lookups, not just tell you the syntax is valid. Do not count by eye. The nesting is exactly where the surprises live, and a record that looks like four includes routinely resolves to thirteen lookups.

Two other things to check while you are in there. You should have exactly one SPF record per domain. Two separate v=spf1 TXT records is an automatic permerror regardless of lookup count, and it is one of the most common misconfigurations on domains that have migrated email providers — the old record gets left behind next to the new one. Also check your sending subdomains separately. SPF does not inherit downward. If mail leaves with an envelope domain of mail.yourdomain.com and there is no TXT record published there, the result is none, not whatever the root domain says.

Where the bloat comes from

Below are typical lookup costs for common includes. Providers restructure their records without announcing it, so treat this as a starting point and verify against your own domain rather than trusting the table as gospel.

IncludeTypical lookups consumedNotes
include:_spf.google.com4One for the include, three for the nested netblock records
include:spf.protection.outlook.com1–2Historically a flat ip4/ip6 list; cheap
include:mailgun.org2Nested regional records
include:sendgrid.net1–2Depends on current structure
include:servers.mcsv.net1Mailchimp; flat
include:_spf.salesforce.com3–4Nested; a frequent culprit
mx1 + one per MX hostUsually 3–4 on Google Workspace or Microsoft 365
a1Almost never needed for email

Add Google Workspace at four, a CRM at four, a help desk at two, and a bare mx mechanism at four, and you are at fourteen lookups before adding anything for outbound. That is the standard shape of a broken marketing domain, and it is why the first campaign sent from a long-established company domain so often underperforms a two-week-old throwaway.

Fix 1: delete what you don't actually send from

Start here, because it is free and it is usually enough on its own. Every include in your record authorizes some service to send mail as your domain. If you cancelled the tool, or you still use it but it sends from its own domain rather than yours, that include does nothing except consume lookups and widen the set of systems that can spoof you.

Walk each include and answer one question: does mail with a Return-Path at my domain currently leave that system? If you are unsure, open the vendor's settings and look for a custom envelope, bounce, or return-path domain. If that was never configured, the include is dead weight — the vendor is sending with their own envelope domain and your record is irrelevant to it. Most domains I have audited can drop two or three includes on the first pass without any change in behaviour.

Delete the mx and a mechanisms too, unless your inbound mail server genuinely originates outbound mail as your domain. On Google Workspace or Microsoft 365 the provider include already authorizes sending; mx is pure waste costing three or four lookups for nothing. The a mechanism is usually a leftover from a shared-hosting setup a decade ago.

Fix 2: move cold email onto its own domain

The cleanest structural fix is to not touch the corporate record at all. Send outbound from a separate domain — getyourbrand.com, yourbrand-hq.com, something recognisable but distinct — whose SPF record contains exactly one include and nothing else. On Microsoft 365 that is v=spf1 include:spf.protection.outlook.com -all. On Google Workspace it is v=spf1 include:_spf.google.com -all.

That is one to four lookups with enormous headroom. No history, no legacy vendors, and no chance of someone in marketing adding a sixth include next quarter and silently breaking authentication for your sequences. Reputation isolation is the bigger argument anyway — if you are weighing the options, see Should You Use Your Main Domain for Cold Email? and the subdomain vs. secondary domain trade-off.

If you go with a sending subdomain instead of a separate domain, publish a dedicated SPF record on that subdomain rather than relying on the root. Because SPF is evaluated against the exact envelope domain, send.yourdomain.com can carry one lean include while the root keeps its messy fourteen-lookup record for everything else. The two never interact.

Fix 3: replace stable includes with ip4 literals

ip4 and ip6 mechanisms cost zero lookups, because there is nothing to resolve. If a provider publishes a small, stable set of ranges — a single SMTP relay, a self-hosted server, a dedicated IP you lease — hardcode the addresses and delete the include. A record with eight ip4 entries and one include is entirely valid and evaluates in a single lookup.

Do not do this for Google or Microsoft. Their ranges shift, the lists are long, and a stale hardcoded netblock means legitimate mail starts failing SPF with no warning and no error anywhere you would think to look. The working rule: hardcode only ranges you control yourself, or ranges the vendor documents as static and commits to notifying you about before changing.

Fix 4: flattening services, with a leash

SPF flattening tools resolve your entire include tree, republish it as a flat list of ip4 mechanisms, and give you a single include to point at. One lookup, everything authorized. It works, and for a large organization with genuine multi-vendor sending it may be the only realistic route back under the limit.

The trade-offs are real and worth stating plainly:

  • Your record is only as fresh as the vendor's last refresh. If Google rotates a netblock and the flattener lags, you fail SPF for that window.
  • You have added a third-party dependency to your email authentication. If their DNS has a bad day, so does yours.
  • Flat records get long. Watch the 255-character string limit and total record size.
  • Most charge a monthly fee for something a clean outbound domain does not need.

Use flattening on the corporate domain if you genuinely must. Do not use it as a reason to skip Fix 1 — flattening a record full of dead vendors just preserves the mess in a more compact form.

Two details that matter more than the count

SPF authenticates the Return-Path, not the From header. The receiving server checks the envelope sender domain, which your recipient never sees. If your sending platform sets a bounce domain it controls, SPF can pass on a domain unrelated to your visible From address — passing SPF while failing DMARC alignment. That is the single most common reason DMARC fails even when SPF and DKIM pass, and it is why DKIM does most of the alignment work on cold email.

Use -all, not ~all, on a dedicated sending domain. Hard fail tells receivers that anything not on your list is forged, and on a domain with exactly one known sender there is no reason to hedge. Keep ~all on a complicated corporate domain where you are genuinely unsure you have enumerated every legitimate sender; a softfail there is far safer than breaking a department's mail to look strict.

A working example

Before, on a five-year-old company domain — fifteen lookups, one void:

v=spf1 mx a include:_spf.google.com include:_spf.salesforce.com include:mailgun.org include:spf.zendesk.com include:old-vendor-spf.example ~all

After, on the same domain, having dropped mx, a, and the two vendors nobody could find a login for — eight lookups:

v=spf1 include:_spf.google.com include:_spf.salesforce.com include:mailgun.org ~all

And on the new outbound domain — four lookups, hard fail:

v=spf1 include:_spf.google.com -all

Total time: about twenty minutes, most of it spent working out which vendors were still live.

Verify after every change

DNS caches. Wait out the TTL plus a few minutes, re-run the validator, and then — more importantly — send a real message to a mailbox you control and read the Authentication-Results header. You want spf=pass with the envelope domain you expect, not spf=none and not spf=permerror. Repeat that check every time someone adds a new tool to the record, because the lookup count only ever goes up on its own. Then walk the rest of the SPF, DKIM, and DMARC setup to confirm signing and alignment survived the edit.

Where Sendvanta fits

Sendvanta sends through your own Gmail, Microsoft 365, or SMTP mailboxes rather than proxying mail through shared infrastructure, so it adds nothing to your SPF record — whatever include your mailbox provider already requires is the whole record. Its layered deliverability health scoring watches authentication alongside mailbox, domain, and IP signals and slows or pauses sending when risk thresholds are crossed, so an auth regression surfaces before it costs you a campaign. If you would rather not register and configure a fresh outbound domain by hand, paid plans can register a sending domain for a one-time $20 and add managed mailboxes at $4/mo each; connecting your own mailboxes is free on every plan, including the free $0 tier. Full details at /features.

Does the 10-lookup limit apply per email or per domain?

Per SPF evaluation, which means per envelope sender domain checked. Each receiving server resolves your record independently, so a record at 11 lookups fails for every recipient every time — it is not intermittent.

What happens to my mail if I exceed the limit?

The receiver returns a permerror. Most treat that as an SPF failure or as no SPF policy at all, which weakens DMARC and raises your spam score. Mail usually still gets delivered, just to the spam folder more often — which is why the problem goes unnoticed for months.

Do DKIM or DMARC records count toward the SPF lookup limit?

No. The limit applies only to mechanisms inside the SPF evaluation chain. DKIM key lookups and the DMARC policy record are separate DNS queries with their own rules.

Is one SPF record enough if I send from multiple subdomains?

No. SPF is evaluated against the exact envelope domain, and subdomains do not inherit the root record. Publish a record on each subdomain you send from, or the check returns none for that subdomain.

Should I use -all or ~all for a cold email domain?

Use -all on a dedicated outbound domain with a single known sender. Keep ~all on a busy corporate domain where you cannot be certain you have listed every legitimate sending system.

Ready to send outbound that lands?

Create your free Sendvanta workspace — no credit card required.

Start free