Introduction

The SPF specification (RFC 7208) limits DNS lookups to 10 per SPF check. Mechanisms like include, a, mx, ptr, exists, and redirect each count as a lookup. When an SPF record exceeds this limit, the check returns a permerror result, and receiving mail servers may treat the email as unauthenticated, increasing the likelihood of spam classification.

Symptoms

  • Email headers show SPF: PermError or SPF: too many DNS lookups
  • DMARC reports show SPF results as permerror instead of pass or fail
  • Emails that previously passed SPF now fail after adding another include
  • Receiving servers treat the email as having no SPF authentication
  • Error message: Received-SPF: PermError (too many DNS lookups)

Common Causes

  • Too many include mechanisms for different email service providers
  • Nested include records -- each included domain's SPF record also counts toward the limit
  • Adding new email services without auditing the existing SPF record
  • mx and a mechanisms each consuming lookups
  • Third-party SPF flattening services not being used

Step-by-Step Fix

  1. 1.Count the current DNS lookups in the SPF record: Identify which mechanisms consume lookups.
  2. 2.```bash
  3. 3.# Get the current SPF record
  4. 4.dig TXT example.com +short | grep "v=spf1"
  5. 5.# Count lookups: include, a, mx, ptr, exists, redirect each count as 1
  6. 6.# Each nested include adds its own lookups
  7. 7.`
  8. 8.Use SPF flattening to reduce lookups: Replace includes with resolved IP addresses.
  9. 9.```dns
  10. 10.# BEFORE: Multiple includes consuming lookups
  11. 11."v=spf1 include:_spf.google.com include:sendgrid.net include:mailchimp.com include:amazonses.com ~all"

# AFTER: Flattened to IP addresses (no lookups) "v=spf1 ip4:142.250.0.0/15 ip4:167.89.0.0/16 ip4:198.2.128.0/18 ip4:205.251.232.0/22 ~all" ```

  1. 1.Remove unnecessary mechanisms: Clean up the SPF record.
  2. 2.```dns
  3. 3.# Remove mx if you do not receive email on this domain
  4. 4.# Remove a if the domain A record is not a mail server
  5. 5.# Replace include with specific ip4/ip6 ranges where possible
  6. 6."v=spf1 ip4:123.45.67.89 include:_spf.google.com ~all"
  7. 7.`
  8. 8.Use a dedicated SPF flattening service: Automate the flattening process.
  9. 9.`
  10. 10.# Services like spf-optimizer, flattener, or custom scripts
  11. 11.# These resolve includes to IP addresses automatically
  12. 12.# and update the SPF record when the included services change their IPs
  13. 13.`
  14. 14.Verify the flattened SPF record passes validation: Test the result.
  15. 15.```bash
  16. 16.# Check DNS lookup count
  17. 17.# Use online tools: https://www.kitterman.com/spf/validate.html
  18. 18.# Verify the record is under 10 lookups
  19. 19.dig TXT example.com +short | grep "v=spf1"
  20. 20.`

Prevention

  • Audit SPF record DNS lookup count whenever adding a new email service
  • Use IP address mechanisms (ip4, ip6) instead of include where possible
  • Avoid mx and a mechanisms unless specifically needed
  • Implement automated SPF monitoring that alerts when lookups approach 10
  • Document all email sending services and their SPF requirements
  • Use SPF flattening as part of the standard email service onboarding process