HackBlue

Tools · Email security · 01 / 18

SPF in depth: mechanisms, qualifiers, and the ten-lookup limit

Read and write SPF records mechanism by mechanism, understand how receivers evaluate them, and avoid the permerror caused by exceeding ten DNS lookups.

9 min read · practice only with authorization

What SPF checks

Sender Policy Framework lets a domain publish which servers may send mail using that domain in the SMTP envelope sender, also called the Return-Path or MAIL FROM. The receiver looks up a TXT record beginning with v=spf1 on that domain and evaluates it left to right against the connecting IP address. SPF does not check the visible From header, which is why DMARC alignment exists.

Mechanisms and qualifiers

Mechanisms include ip4 and ip6 for literal ranges, a and mx for the domain’s own hosts, include to pull in another domain’s policy, and all as the final catch-all. Each can carry a qualifier: + pass (the default), - fail, ~ softfail, and ? neutral. A typical record ends with -all once you are confident every legitimate sender is listed, or ~all while you are still discovering senders.

Snippet
dig +short TXT example.org | grep spf1
"v=spf1 ip4:203.0.113.0/28 include:_spf.mailprovider.example include:sendgrid.net -all"

The ten-lookup limit

Evaluating include, a, mx, ptr, exists, and redirect each costs a DNS lookup, and nested includes count too. More than ten lookups yields a permerror, which DMARC treats as an SPF failure. ip4 and ip6 cost nothing. Reduce lookups by removing unused senders, replacing stable includes with ip ranges you control, and avoiding ptr entirely.

  • ip4 and ip6: no lookup
  • include, a, mx, exists, redirect: one lookup each, nested ones too
  • ptr: deprecated and slow; avoid
  • Over ten: permerror

Lab: count lookups for your own domain

Fetch the SPF record for a domain you manage, then follow every include recursively and count the lookup-costing mechanisms. Compare your count with an online SPF checker. If you are near ten, list which senders are still in use with your email team and draft a trimmed record. Publish changes first to a test subdomain if possible.

Snippet
spf() { dig +short TXT "$1" | tr -d '"' | grep '^v=spf1'; }
spf example.org
spf _spf.mailprovider.example
# tally: include / a / mx / exists / redirect at every level

Diagram

How a receiver evaluates SPF

  1. Envelope sender

    Take the domain from MAIL FROM (or HELO if empty).

  2. Fetch policy

    Look up the v=spf1 TXT record.

  3. Evaluate

    Test mechanisms left to right against the client IP.

  4. Result

    pass, fail, softfail, neutral, none, temperror, or permerror.

Check yourself

1. Which identity does SPF authenticate?

2. What happens when evaluation needs more than ten DNS lookups?

3. Which mechanisms do not consume a DNS lookup?