SPF Record Exceeding DNS Lookup Limit

Advanced Email Deliverability

Your domain's SPF record causes receiving servers to perform more than 10 DNS lookups during evaluation, violating RFC 7208. When the limit is exceeded the result is `permerror`, which many DMARC policies treat the same as `spf=fail`, causing legitimate email to be quarantined or rejected. This is a common but non-obvious failure mode as organizations add multiple ESPs and SaaS tools.

Symptoms

  • SPF check returns `permerror` or `too many DNS lookups` in Authentication-Results
  • DMARC aggregate reports show high spf=fail or spf=permerror counts
  • Emails from some sending services authenticate correctly while others fail
  • Problem appeared after adding a new ESP, CRM, or marketing platform
  • SPF flattening tools report your record has 11+ mechanisms requiring DNS resolution
  • Intermittent delivery failures that vary by recipient server implementation

Possible Root Causes

  • Accumulated `include:` directives from adding multiple ESPs, CRMs, and SaaS tools over time
  • Nested includes: a single `include:` directive references a record that itself contains multiple includes
  • Using `mx` or `a` mechanisms that require additional lookups instead of explicit `ip4:` ranges
  • Third-party vendor SPF records unexpectedly adding new nested includes without notice
  • Copy-pasting vendor SPF guidance without auditing the cumulative lookup count

Diagnosis Steps

Step 1: Retrieve and Count Your Current SPF Record

dig TXT example.com +short | grep "v=spf1"

Step 2: Count DNS-Resolving Mechanisms

The following SPF mechanisms each consume one DNS lookup: include:, a, mx, ptr, exists, and redirect=. The ip4: and ip6: mechanisms do NOT count.

Manually trace each include: recursively:

# Top-level record
dig TXT example.com +short | grep spf1

# For each include, recurse:
dig TXT _spf.google.com +short
dig TXT _spf.sendgrid.net +short
dig TXT spf.protection.outlook.com +short
# Continue until all includes are exhausted

Step 3: Use an Automated SPF Counter

Tools like MXToolbox SPF Checker (https://mxtoolbox.com/spf.aspx) or kitterman.com/spf/validate.html enumerate nested includes and report the total lookup count.

Step 4: Identify Which Records Contribute the Most Lookups

# Trace the lookup tree for a major ESP
dig TXT include:_spf.google.com +short
# "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com ..."
# Each nested include costs another lookup

Step 5: Test With a Specific Sender IP

# Use spfquery if available
spfquery -ip=198.51.100.5 [email protected] -helo=mail.example.com

# Or use Python's pyspf
python3 -c "import spf; print(spf.check2(i='198.51.100.5', s='[email protected]', h='mail.example.com'))"

Solution

Option 1: SPF Flattening (Manual)

Replace DNS-resolving mechanisms with static ip4: and ip6: ranges:

# Step 1: Resolve all includes to their final IP ranges
# For Google Workspace:
dig TXT _netblocks.google.com +short
dig TXT _netblocks2.google.com +short
dig TXT _netblocks3.google.com +short

# Step 2: Build a flattened record using only ip4:/ip6: entries
# example.com TXT "v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip6:2001:4860::/32 -all"

Limitation: IP ranges published by ESPs change without notice. Flattened records require manual maintenance.

Option 2: Use an SPF Flattening Service

Services like dmarcian SPF Surveyor, PowerSPF, or AutoSPF maintain a dynamically updated single include: that resolves to all your authorised IPs:

# example.com TXT "v=spf1 include:spf.your-provider.io -all"
# The provider's record handles all sub-lookups within 10 total

Option 3: Reduce the Number of Mechanisms

Audit your include list and remove ESPs or services no longer in use:

# Current record (12 lookups):
# "v=spf1 include:_spf.google.com include:sendgrid.net include:spf.protection.outlook.com
#  include:amazonses.com include:mailchimp.com a mx -all"

# Replace 'a' and 'mx' with explicit ip4: ranges to save 2 lookups
# Remove deprecated include: entries to save more

Option 4: Subdomain Delegation

Route bulk or transactional mail through a subdomain (e.g., mail.example.com) with its own SPF record, reserving the apex record for corporate mail only:

# example.com TXT "v=spf1 include:_spf.google.com -all"  (2 lookups)
# mail.example.com TXT "v=spf1 include:sendgrid.net include:amazonses.com -all"  (4 lookups)

Prevention

  • Audit your SPF record whenever adding a new ESP or SaaS email sender; refuse to exceed 8 DNS-resolving mechanisms (leave headroom)
  • Set up automated SPF lookup count monitoring via a weekly cron job or third-party service that alerts when the count rises above 8
  • Prefer ip4: and ip6: over include: for services that publish stable IP ranges
  • Document all authorised senders and their SPF contribution in a DNS runbook so lookups are visible
  • Review and revoke include: entries for decommissioned services during quarterly DNS audits

Related Protocols

Related Terms

More in Email Deliverability