Technology Aug 25, 2026 · 5 min read

The SPF redirect trap: why -all can make redirect= useless

The SPF redirect trap: why -all can make redirect= useless SPF records often look simple until you start combining mechanisms and modifiers. One particularly easy mistake is to write a record like this: v=spf1 include:_spf.google.com -all redirect=_spf.example.com At first glanc...

DE
DEV Community
by Petr Michal
The SPF redirect trap: why -all can make redirect= useless

The SPF redirect trap: why -all can make redirect= useless

SPF records often look simple until you start combining mechanisms and modifiers.

One particularly easy mistake is to write a record like this:

v=spf1 include:_spf.google.com -all redirect=_spf.example.com

At first glance, it seems reasonable:

  • authorize Google,
  • reject everything else,
  • and use another SPF policy through redirect=.

But the redirect= part will never be used.

The reason is an important detail of how SPF evaluation works.

redirect= is not a fallback after -all

An SPF record is evaluated mechanism by mechanism.

For example:

v=spf1 ip4:192.0.2.10 include:_spf.google.com -all

The receiver checks the mechanisms until one matches.

The all mechanism is special because it always matches.

That means:

-all

effectively says:

If nothing before this matched, return SPF Fail.

Now consider this record again:

v=spf1 include:_spf.google.com -all redirect=_spf.example.com

Once SPF reaches -all, it already has a result.

There is no reason to evaluate redirect=.

The redirect modifier is only used when none of the mechanisms in the record produce a match.

Because all always matches, a record containing all prevents redirect= from being used.

What redirect= is actually for

The redirect modifier is useful when several domains should share one central SPF policy.

Imagine these domains:

example.com
example.net
example.org

Instead of maintaining the same SPF configuration independently on every domain, they can redirect to a central policy.

For example:

example.com TXT "v=spf1 redirect=_spf.example.com"
example.net TXT "v=spf1 redirect=_spf.example.com"
example.org TXT "v=spf1 redirect=_spf.example.com"

And the central record might contain:

_spf.example.com TXT "v=spf1 ip4:192.0.2.10 include:_spf.google.com -all"

Now the sending policy can be maintained in one place.

This is very different from include:.

redirect= vs include:

These two are easy to confuse.

include:

Use include: when you want to authorize senders defined by another SPF record as part of your own policy.

Example:

v=spf1 include:_spf.google.com ip4:192.0.2.10 -all

This says:

Google is allowed, this IP is allowed, and everything else should fail.

Your domain still owns the final policy.

redirect=

Use redirect= when another domain should provide the entire remaining SPF policy.

Example:

v=spf1 redirect=_spf.example.com

A useful mental shortcut is:

include:  → add another policy
redirect= → use another policy

That distinction matters when debugging SPF records.

A common broken configuration

Consider this:

v=spf1 ip4:192.0.2.10 -all redirect=_spf.provider.com

Someone may expect the following behavior:

  1. allow 192.0.2.10,
  2. if it does not match, check _spf.provider.com,
  3. otherwise fail.

But SPF does not work that way.

The real evaluation is:

  1. check ip4:192.0.2.10,
  2. if it does not match, evaluate -all,
  3. all matches every sender,
  4. return SPF Fail,
  5. redirect= is never used.

If you really want the provider to define the policy, the record should instead look like:

v=spf1 redirect=_spf.provider.com

If you want both your own IP address and the provider's authorized senders, include: is usually the appropriate mechanism:

v=spf1 ip4:192.0.2.10 include:_spf.provider.com -all

The position of redirect= can be misleading

Another subtle point is that redirect= is a modifier, not a mechanism.

So it should not be read as if SPF simply processes it from left to right like ip4, include, mx, or all.

This record:

v=spf1 redirect=_spf.example.com -all

does not mean:

Try redirect first, then -all.

The presence of the all mechanism still means SPF can produce a result without using the redirect.

A good mental model is:

Evaluate the SPF mechanisms first.
Only if none of them match can redirect= provide another SPF record to evaluate.

Why this matters in production

A broken SPF redirect can be surprisingly difficult to notice.

The DNS record is syntactically valid.

A DNS lookup succeeds.

The domain has an SPF record.

Yet mail from an expected sender may still fail SPF because the redirected policy was never evaluated.

This becomes especially confusing when organizations centralize SPF records across many domains.

A small mistake in the parent policy can affect multiple domains at once.

When debugging this kind of issue, check:

  1. whether the record contains an all mechanism,
  2. whether redirect= is actually reachable,
  3. whether you really need redirect= or should use include:,
  4. the SPF result returned by the redirected domain,
  5. the total number of DNS-querying SPF terms.

A simple rule to remember

If your SPF record contains:

-all

and also:

redirect=...

you should take a closer look.

In most cases, that combination indicates that the redirect is not doing what the author intended.

Use:

redirect=

when another domain should define the SPF policy.

Use:

include:

when another SPF policy should be incorporated into your own.

And use:

-all

when you are ready to explicitly fail senders that did not match any previous mechanism.

If you are debugging a more complex configuration, I wrote a more detailed guide to the SPF redirect modifier, including redirect= vs include:, DNS lookup behavior, common errors, and practical examples.

You can also inspect an SPF record directly with the MXFend SPF checker.

DE
Source

This article was originally published by DEV Community and written by Petr Michal.

Read original article on DEV Community
Back to Discover

Reading List