DNSVerdictAll toolsGuidesHow it works

SPF syntax errors: every checker message explained

Published · Updated

An SPF record with a syntax error returns permerror, so receivers do not evaluate it at all. RFC 7208 §4.6 says “if there are any syntax errors anywhere in the record, check_host() returns immediately with the result ‘permerror’.” Paste your domain into the SPF checker, find the red line in the table below, and apply the fix. One typo anywhere in the record is enough to disable all of it.

Messages and fixes

The first column is the text the checker shows.

Checker messageCauseFix
Record does not start with v=spf1 (RFC 7208 §4.5)Text before v=spf1, v=spf 1, spf1, a stray quoteMake v=spf1 the first characters of the value
Unparseable term ”…”A term that matches no mechanism or modifier shape, e.g. the 192.0.2.1 left over from ip4 192.0.2.1 (space instead of colon, which also triggers the “ip4 requires an address” line)Use ip4:address and include:domain with a colon
Unknown mechanism ”…” → permerror (§4.6.1)Typo such as inlcude:, ipv4:, mxxCorrect the name: include, a, mx, ptr, ip4, ip6, exists, all
“include” requires a domain (§5.2)include: with nothing after it, or include aloneAdd the provider’s domain
“exists” requires a domain (§5.2)Same for exists:Add a domain
“ip4” / “ip6” requires an addressip4: emptyAdd an address or range
“+all” allows any sender — effectively no SPF protection+all or all with the default +Use ~all or -all
Terms after “all” are never evaluated (§5.1)Mechanism written after allMove all to the end
…: included domain has no SPF record → permerror for that include (§5.2)include: of a domain that publishes no v=spf1 recordCorrect the domain name or remove the include
N SPF records on … → permerror (§3.2): must be exactly oneMore than one v=spf1 TXTSee Two SPF records
N DNS lookups — limit is 10 (§4.6.4) → permerror at many receiversToo many include, a, mx termsSee SPF too many lookups
N void lookups — limit is 2 (§4.6.4)Includes or names that return nothingRemove dead names
Unknown modifier ”…” is ignored by receivers (§6)Unrecognized name=value termWarning only; delete if it is a typo for redirect= or exp=
ptr is deprecated and slow (§5.5)ptr mechanismReplace with ip4/ip6 or an include

The section numbers in the left column are the checker’s own. Where RFC 7208 is more general than the message, for example for unknown mechanisms, the rule behind it is the syntax-error rule in §4.6. Warnings (unknown modifier, ptr, terms after all) describe terms that are ignored or discouraged, not permerrors.

Examples

Typos and their corrections:

Wrong:   v=spf1 inlcude:_spf.google.com ~all
Right:   v=spf1 include:_spf.google.com ~all

Wrong:   v=spf1 ip4:192.0.2.0/33 ~all
Right:   v=spf1 ip4:192.0.2.0/24 ~all

Wrong:   v=spf1 include: ~all
Right:   v=spf1 include:spf.protection.outlook.com ~all

IP and CIDR errors

An ip4: value takes a full dotted address, optionally followed by / and a prefix length from 0 to 32. ip6: accepts a prefix length from 0 to 128 (RFC 7208 §5.6). The RFC also says: “It is not permitted to omit parts of the IP address instead of using CIDR notations”, so ip4:192.0.2 is invalid. Values outside those ranges do not match the grammar (§12), so they fall under the syntax-error rule in §4.6 and the result is permerror. The checker reports each case separately:

MistakeChecker message
Prefix too longPrefix length "/33" in ip4:192.0.2.0/33 is out of range: ip4 allows 0 to 32 → permerror (§5.6, §12)
Leading zerosPrefix length "/024" in ip4:192.0.2.0/024 has leading zeros; write it as /24 → permerror (§12)
Non-numeric prefixInvalid prefix length "/x" in ip4:1.2.3.4/x: must be a number from 0 to 32 → permerror (§5.6, §12)
Incomplete addressInvalid IPv4 address "192.0.2" in ip4:192.0.2 → permerror (§5.6, §12)

The ip6: messages are the same with the 0 to 128 range. A frequent real-world mistake is pasting a network with a host bit set, such as 192.0.2.5/24; that parses, but it authorizes the whole /24, which may be more than intended.

Include of a domain without SPF

When include: points at a domain with no SPF record, the nested evaluation returns “none”, and §5.2 maps that to permerror. It happens when you misspell a provider’s domain or when the provider changed its hostname. Compare the include with the provider’s own documentation. The provider setup check shows the documented include for a provider and whether your domain uses it. For setup from the beginning, see How to set up an SPF record.

The +all trap

v=spf1 +all, or the shorter v=spf1 all, is syntactically valid and passes every sender. That is why the checker lists it as an error although receivers do not return permerror. It usually comes from a test record that was never replaced. Use ~all or -all; see ~all vs -all.

FAQ

Does one typo break the whole record? Yes. A syntax error anywhere returns permerror for the full evaluation (RFC 7208 §4.6).

Is an unknown modifier also a permerror? No. Section 6 says unrecognized modifiers “MUST be ignored”, so the checker only warns. An unknown mechanism is a syntax error.

My record looks right but the checker still reports an error. Read the line beginning with the included domain. Errors inside an included record are shown with that domain’s name, and you cannot edit them; contact the provider or remove the include.

Sources

Tools used

SPF Record CheckerEmail Provider Setup Check