SPF
Expand SPF macros — %{i}, %{s}, %{d}, %{l}, %{o}, %{h}, %{v}, %{p} — with your own evaluation context. See exactly what each macro expands to before publishing the record, and understand the per-IP and per-sender authorisation patterns most receivers never document.
SPF macros — the part of the spec almost no one reads
RFC 7208 §7 defines a tiny templating language embedded
inside SPF mechanism values. At evaluation time, receivers substitute
placeholders like %{i} (the client IP) and
%{s} (the sender address) with values from the
current message. The result lets you put per-sender or per-IP logic into a
single static SPF record — a trick most ESPs use and almost no admin
debugs comfortably because there's never a clean way to see the expansion.
The debugger above lets you paste any mechanism with macros, set the evaluation context (client IP, sender, HELO, domain), and see the final expanded form plus a macro-by-macro breakdown showing the base value, the transform, and the output.
The macro letters
| Macro | Meaning | Common use |
|---|---|---|
%{s} | Sender — full envelope MAIL FROM address | Per-sender allowlisting |
%{l} | Local-part of the sender |
Mailbox-specific routing (e.g. only alerts@ via
Pagerduty)
|
%{o} | Domain of the sender | Per-tenant SPF includes in shared infra |
%{d} | Current evaluation domain | Build self-referential records |
%{i} | Client IP (IPv6 → 32 dot-separated nibbles) | Per-IP allowlisting via DNS zone |
%{p} | Validated PTR (discouraged) | Almost always returns "unknown" — avoid |
%{v} |
Literal in-addr for IPv4 or ip6 for IPv6
| Build reverse-DNS-style zones |
%{h} | HELO/EHLO domain from the SMTP session | Detect mismatch between HELO and MAIL FROM domain |
%{c} | Client IP (textual form). Only valid in exp=. | Explanation strings |
%{r} | Receiving server domain. Only valid in exp=. | Explanation strings |
%{t} | Current Unix timestamp. Only valid in exp=. | Time-bound explanation strings |
Transformations — digits, reverse, delimiters
Every macro accepts optional transformations between the letter and the
closing brace: %{letter[digits][r][delimiter]}.
- Digits — keep only the last N parts after splitting.
Example:
%{i2}on192.0.2.10yields2.10(last 2 dot-separated parts). - r (reverse) — reverse the parts before joining.
Example:
%{ir}on192.0.2.10yields10.2.0.192. - Delimiters — one or more of
. - + , / _ =. Splits the base value on any of the listed characters before applying digits/reverse. Example:%{l-}onfoo-bar-bazsplits on-giving three parts.
Why macros bite SPF flattening
The SPF Flattener can only resolve
include chains to static IPs at the time of evaluation.
Macros are evaluated per-message using runtime context
(the client IP, the sender). A record containing
exists:%{ir}.%{v}._spf.%{d}
cannot be pre-flattened — there is no single static answer. The Flattener
flags this with a macro_in_mechanism warning and skips the
expansion.
The %{p} warning
%{p} is the validated PTR domain — the receiver
runs a reverse-DNS lookup on the client IP and confirms the forward A
record matches. Per RFC 7208 §7.2, if validation fails (the typical case
for IPs without proper FCrDNS), %{p} expands to
unknown. Many receivers skip the PTR lookup entirely for
performance. Combined: %{p} almost always returns
unknown — design around it, not for it.
Common macro patterns in the wild
The presets above the tool cover the most-cited patterns. Two live examples worth knowing:
- Per-IP zone —
exists:%{ir}.%{v}._spf.%{d}looks up10.2.0.192.in-addr._spf.example.comfor an IPv4 client. Publish A records under that zone to authorise individual IPs without bloating the static SPF record. - Per-sender zone —
exists:%{l}.%{o}._spf.%{d}looks upalice.user.example.com._spf.example.com. Lets you restrict particular mailboxes to particular send paths — useful when alerts@ should only ever originate from your monitoring infra.
Related tools
- SPF Record Syntax Inspector — token-by-token breakdown of an entire SPF record (which is where macros usually live).
- SPF Record Checker — validity check with the full 10-lookup budget tally.
- SPF Flattener — the tool that has to handle macros specially because it cannot statically pre-evaluate them.
Read the complete SPF guide to learn more.