CertaDNS
Skip to lesson

SPF Fundamentals · lesson 5 of 6

include, redirect, and nested records

After this lesson you can

Trace an SPF evaluation through nested includes and say where it stopped.

Assumes you have read Mechanisms and evaluation order.

Most real SPF records are mostly include. It is how a domain authorises a platform whose addresses it does not know and should not have to track. It also behaves in one way that surprises people, and that surprise is the source of a whole category of bugs.

What include actually does

include:other.example means: evaluate other.example’s SPF record against this same connecting IP, and if that evaluation produces a pass, treat this mechanism as a match.

The word "include" is misleading. Nothing is textually inserted. It is a function call that returns pass or not-pass, and only pass matters.

Included record evaluates toThe include mechanism
passMatches. Evaluation of the outer record stops here.
fail, softfail, neutralDoes not match. Evaluation continues with the next term.
none (no record at the included domain)The whole outer record becomes permerror.
permerrorThe outer record becomes permerror.
temperrorThe outer record becomes temperror.

The one that catches people

An included record ending in -all does not cause the outer record to fail. It produces fail, which is simply "not a pass", so the include does not match and evaluation moves to the next term. You can safely include a platform whose record ends in -all, and nearly all of them do.

But an include pointing at a domain with no SPF record at all is a hard failure of your entire record — RFC 7208 §5.2. This is how a decommissioned vendor takes your SPF down months after you stopped using them.

Nesting

Included records contain includes of their own, and those are evaluated too. PayPal’s record is a clear example of deliberate nesting:

$ dig +short TXT paypal.com | grep spf1
"v=spf1 include:pp._spf.paypal.com include:3ph1._spf.paypal.com include:3ph2._spf.paypal.com include:3ph3._spf.paypal.com include:3ph4._spf.paypal.com include:sendgrid.net include:aspmx.pardot.com ~all"
Checked 2026-09-12. Each of those sub-records contains further terms, and sendgrid.net contains includes of its own.

Tracing this by hand means fetching each included record in turn:

dig +short TXT pp._spf.paypal.com
dig +short TXT sendgrid.net
# ...and any includes those contain, recursively

Every one of those lookups counts against a limit, which is the subject of the next lesson and the reason SPF records cannot simply grow forever.

redirect, and how it differs

redirect= is a modifier, not a mechanism. It means: abandon this record and use that one instead, including its all.

v=spf1 redirect=_spf.example.net
  • It is only used if no mechanism matched. A redirect in a record that also contains all is dead code, because all always matches first.
  • The target’s result becomes your result, including a fail. Unlike include, you inherit the ending.
  • It is the right tool for shared policy. If fifty domains should all have identical SPF, give them each a one-term record redirecting to a single maintained record, and there is one place to edit.

Choosing between them

Use include to add a sender to a record you own. Use redirect to say that this domain’s policy is another domain’s policy. If you find yourself with a record containing both a redirect and an all, the redirect is doing nothing and someone has misunderstood one of them.

Try it on a real domain

Free, no account, public DNS only.

Last reviewed