Email authentication
SPF checker
Check an SPF record for the faults that silently break it, and count every DNS lookup it costs.
Paste a draft SPF record and read it term by term, with the faults named, before anything is published.
Paste the record exactly as you mean to publish it. Nothing is looked up or stored.
Nothing to read yet
Paste a draft SPF record and every term is read as you type.
This SPF record parser reads a record you paste rather than a domain you own, so a draft can be checked term by term before it is ever published — nothing here is looked up, which is also the one thing it cannot tell you.
An SPF record is a single line of terms read left to right, and the first one that matches the sending server decides the answer. Most of what goes wrong with one is visible in the text alone: a mechanism nobody spelled right, an address with an impossible prefix, a "redirect" sitting beside an "all" that cancels it, or terms added after the "all" where no receiver will ever reach them.
The rest only shows up once the record is live, because it depends on what other people publish: an "include" that costs four lookups instead of one, a target with nothing in it. That half needs a resolver and belongs to the SPF checker; this page is the half you can settle while the record is still in a text box.
The table lists every term in the order a receiver works through them, with what each one authorises and whether it spends a DNS lookup. The lookup column is where a record usually goes wrong later: ip4, ip6 and all cost nothing at all, while each include, a, mx, ptr and exists costs one before its own chain is even followed.
A red finding is a syntax error — the kind that makes a receiver return PermError and ignore the whole record, so it is worse for your mail than the one term you got wrong. An amber one is a term that is valid but does nothing useful where it sits.
No. It reads the text in the box and makes no DNS query at all, which is why it can check a record that does not exist yet. The trade-off is that it cannot tell you whether this record is the one actually published, or what its includes resolve to.
Because it assumes every "include", "a" and "mx" resolves exactly once. An include points at somebody else's record, which can hold includes of its own, and those count against the same limit of ten — so the number here is the floor and the real cost can only be higher.
A sender matching none of the terms gets the default result, Neutral, under RFC 7208 section 4.7 — which most receivers treat exactly as they treat a domain with no SPF record. The record then only helps the senders you listed and says nothing about anyone else.
No. An include asks whether the other record would pass this sender and carries on if it would not; a redirect hands the whole answer over to the other record, including its "all". A redirect is also ignored outright whenever the record has an "all" of its own.
RFC 7208 treats an unrecognised term as a syntax error in the record, so a receiver returns PermError and ignores every other mechanism in it. A single misspelled "include" leaves every correctly listed server unauthorised.
Every fixed value this page gives you comes from the provider’s own documentation. These pages change, so each one says the day it was last read here.
Resell mailbox licences for the domains you just checked, under your own brand.
Get startedcurl -X POST https://163-123-236-68.sslip.io/api/tools/spf-record-parser \
-H "Content-Type: application/json" \
-d '{"record":"v=spf1 include:_spf.google.com ip4:203.0.113.0/24 ~all"}'{
"tool": "spf-record-parser",
"input": {
"record": "v=spf1 include:_spf.google.com ip4:203.0.113.0/24 ~all"
},
"result": {
"verdict": {
"tone": "success",
"headline": "This record reads cleanly, at about 1 of 10 lookups",
"summary": "Every term is one RFC 7208 defines, and the record takes a position on unlisted senders."
},
"findings": [
{
"id": "lookup-count-is-an-estimate",
"severity": "info",
"title": "About 1 of the 10 DNS lookups, as written",
"detail": "This counts one lookup for each \"include\", \"a\", \"mx\", \"ptr\" and \"exists\" term, and one for a \"redirect\" that is not cancelled by an \"all\" — it is an estimate, not a count. Nothing is published yet to resolve, so a nested include inside one of these can add lookups this page cannot see: 1 is the floor, never the total."
},
{
"id": "record-read-term-by-term",
"severity": "pass",
"title": "3 terms read, in order",
"detail": "Every term of this record is listed below with what it does, in the order a receiver works through them — the first one that matches the sending server decides the result, and the rest are never reached (RFC 7208 §4.6.2)."
},
{
"id": "terminal-all-present",
"severity": "pass",
"title": "The record ends with \"~all\"",
"detail": "A sender matching none of the terms in front of it gets SoftFail, the usual setting while a sender list is still being confirmed — the record takes a position on everyone, which is the point of having one."
}
],
"parts": [
{
"kind": "table",
"title": "Every term, in the order a receiver reads them",
"columns": [
"#",
"Term",
"What it does",
"Lookups"
],
"mono": [
1
],
"rows": [
[
"1",
"include:_spf.google.com",
"Also passes whatever _spf.google.com passes, by reading that record too",
"1"
],
[
"2",
"ip4:203.0.113.0/24",
"Passes 203.0.113.0/24",
"—"
],
[
"3",
"~all",
"Soft-fails every sender not matched above",
"—"
]
],
"note": "Only the terms marked with a lookup count against the limit of 10; ip4, ip6 and all cost nothing."
},
{
"kind": "facts",
"title": "The record as a whole",
"rows": [
[
"Terms",
"3"
],
[
"DNS lookups, estimated",
"1 of 10"
],
[
"Ends with",
"~all"
],
[
"Characters",
"54"
]
]
},
{
"kind": "record",
"title": "The record as read",
"value": "v=spf1 include:_spf.google.com ip4:203.0.113.0/24 ~all",
"note": "Exactly the first record pasted above, with nothing added or reordered."
}
],
"limits": [
"This reads the text you pasted and nothing else. It cannot say whether this record is published anywhere, whether the domain already has another one beside it, or what any of its includes actually resolve to.",
"The lookup count is an estimate that assumes each \"include\", \"a\" and \"mx\" resolves exactly once. An include whose own record includes two more costs three, not one — run the SPF checker against the domain once this record is published to count what it really spends.",
"A \"ptr\" mechanism and any macro such as %{i} depend on the sending server's own IP address, which no amount of reading the record can supply."
]
}
}Email authentication
Check an SPF record for the faults that silently break it, and count every DNS lookup it costs.
Email authentication
Build a valid SPF record from the senders you actually use, and see the DNS-lookup cost before you publish it.
Email authentication
See how many of a domain’s SPF lookups flattening would actually remove, and what it costs to keep one flattened.
DNS
Split a long TXT record value into properly quoted 255-byte character-strings, or the one value a panel that auto-joins would want.