WSS
Web Specification Studio Home
On this page
AuthenticationRequiredUpdated

Sender Policy Framework (SPF)

Publish a single, bounded SPF policy that authorizes legitimate envelope senders without exceeding the 10-DNS-lookup limit or using overly permissive qualifiers.

What it is

Sender Policy Framework (SPF), specified in RFC 7208, is a DNS-based authentication protocol that enables domain owners to specify which mail transfer agents (MTAs) and IP addresses are authorized to send email on behalf of their domain.

SPF operates during the initial SMTP handshake and validates the envelope sender (the MAIL FROM or Return-Path identity), as well as the HELO/EHLO domain name presented by the connecting mail server.

example.com. IN TXT "v=spf1 ip4:198.51.100.0/24 include:_spf.google.com -all"

An SPF record is published as a standard DNS TXT record at the root of the sending domain. It consists of the v=spf1 prefix followed by ordered mechanisms (ip4, ip6, a, mx, include) and a terminating qualifier (-all for hardfail, ~all for softfail, or ?all for neutral).

Why it matters

  • Spoofing and Phishing Prevention: Without SPF, any SMTP server on the internet can claim any domain in the envelope sender address. SPF provides receiving mail servers with an authoritative, cryptographic-free mechanism to verify IP authorization before accepting message payloads.
  • DMARC Compliance: DMARC (RFC 7489) requires either SPF or DKIM to achieve authentication and domain alignment with the visible From: header. A properly configured SPF policy is one of the two foundational pillars required for inbox placement at major mailbox providers (Google, Yahoo, Microsoft 365, Apple Mail).
  • Early Rejection of Malicious Mail: Because SPF is evaluated during the SMTP transaction at MAIL FROM time, receiving mail servers can reject fraudulent messages with a 550 5.7.1 error code before downloading the message body, saving bandwidth and compute.

How to implement

1. Publish exactly one SPF record per domain. Never publish multiple TXT records starting with v=spf1. Multiple records cause an immediate PermError (permanent error) on receiving mail servers, invalidating SPF authentication entirely:

; CORRECT: Single unified SPF record
example.com. IN TXT "v=spf1 ip4:198.51.100.10 include:_spf.mailgun.org include:_spf.google.com -all"

; WRONG: Multiple SPF records cause PermError
example.com. IN TXT "v=spf1 include:_spf.google.com ~all"
example.com. IN TXT "v=spf1 include:_spf.mailgun.org ~all"

2. Strictly adhere to the 10-DNS-lookup limit. RFC 7208 §4.6.4 limits the number of DNS-querying mechanisms (include, a, mx, ptr, exists, redirect) to a maximum of 10 lookups per evaluation. Exceeding 10 lookups results in a PermError and failed authentication:

  • Count nested include: lookups recursively (for example, include:_spf.google.com consumes 3 lookups internally).
  • Replace a and mx mechanisms with direct ip4: or ip6: CIDR blocks where static server IPs are known.
  • Avoid deprecated mechanisms like ptr.

3. Choose the appropriate policy qualifier.

  • -all (Hardfail): The standard production configuration. Explicitly states that any IP address not listed is unauthorized and should be rejected.
  • ~all (Softfail): Accepts messages from unlisted IPs but tags them as suspicious. Recommended during initial rollout while auditing all third-party sending services (CRM, transactional ESPs, helpdesk platforms).
  • +all (Pass all): Never use +all in production. It authorizes every IP address on the internet to send mail as your domain.

4. Publish defensive SPF records for non-sending domains. Every park domain, redirect domain, and internal subdomain that does not send email must publish a defensive “null” SPF record to block spoofers:

non-sending.example.com. IN TXT "v=spf1 -all"

Common mistakes

  • Exceeding the 10-DNS-Lookup Limit: Chaining multiple third-party marketing and CRM platforms (HubSpot, Salesforce, Zendesk, Mailchimp) frequently pushes the lookup count past 10, silently breaking SPF for all recipients.
  • Forgetting Subdomains: SPF records do not automatically inherit down to subdomains. If mail is sent with MAIL FROM: bounces.marketing.example.com, an SPF record must be published directly at bounces.marketing.example.com.
  • Using Deprecated SPF Resource Records: Do not use the obsolete DNS record type 99 (SPF). Modern resolvers only query DNS TXT records.
  • Ignoring Void DNS Lookups: RFC 7208 §4.6.4 limits lookups that return NXDOMAIN or no records to a maximum of 2. A single stale include: pointing to a deleted domain can trigger a void lookup error.

Verification

1. Query the live SPF record using dig:

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

2. Count total recursive DNS lookups: Check nested includes to ensure the total mechanism count remains well below 10:

# Check lookup resolution chain
dig +short TXT _spf.google.com

3. Inspect delivered message headers: Send a test message to an external mailbox and verify the Authentication-Results and Received-SPF headers:

Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of [email protected] designates 198.51.100.10 as permitted sender) [email protected];
       dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Received-SPF: pass (google.com: domain of [email protected] designates 198.51.100.10 as permitted sender) client-ip=198.51.100.10;

Related topics

Sources & further reading