Skip to main content
SPF

SPF Macro Debugger

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.

Try a preset:
Evaluation context
Expanded mechanism
exists:42.100.51.198.in-addr._spf.example.com

Macro-by-macro breakdown

%{ir}%i
Base value198.51.100.42
Transformreverse
Expands to42.100.51.198
%{v}%v
Base valuein-addr
Transformno transform
Expands toin-addr
%{d}%d
Base valueexample.com
Transformno transform
Expands toexample.com

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

MacroMeaningCommon use
%{s}Sender — full envelope MAIL FROM addressPer-sender allowlisting
%{l}Local-part of the senderMailbox-specific routing (e.g. only alerts@ via Pagerduty)
%{o}Domain of the senderPer-tenant SPF includes in shared infra
%{d}Current evaluation domainBuild 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 IPv6Build reverse-DNS-style zones
%{h}HELO/EHLO domain from the SMTP sessionDetect 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} on 192.0.2.10 yields 2.10 (last 2 dot-separated parts).
  • r (reverse) — reverse the parts before joining. Example: %{ir} on 192.0.2.10 yields 10.2.0.192.
  • Delimiters — one or more of . - + , / _ =. Splits the base value on any of the listed characters before applying digits/reverse. Example: %{l-} on foo-bar-baz splits 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 zoneexists:%{ir}.%{v}._spf.%{d} looks up 10.2.0.192.in-addr._spf.example.com for an IPv4 client. Publish A records under that zone to authorise individual IPs without bloating the static SPF record.
  • Per-sender zoneexists:%{l}.%{o}._spf.%{d} looks up alice.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.

Get the full picture with DMARCguard

Continuous monitoring, aggregate report parsing, and actionable insights for all your email authentication protocols.

Start Free