Free SPF Checkers Compared: What They Get Wrong About Five Real-World SPF Records
An SPF checker has one job: tell you what a receiving mail server will make of your record. Most free checkers get the easy cases right. A record that is missing, or one that is obviously over the 10-lookup limit, will light up red almost everywhere.
Real records rarely go wrong in the easy way. They break inside a vendor's include you never read, hide a one-character typo, or run into a rule most people have never heard of. So we went looking for real, public domains whose SPF records hide exactly those problems. We ran each one through 10 free SPF checkers and compared every answer with what RFC 7208, the SPF standard, says should happen.
Disclosure: DMARKOFF makes one of the checkers in this test. To keep it fair, we used real public domains as published, traced each record against RFC 7208 (with the help of a small dig-based script), confirmed every final verdict with pySPF, the library behind Kitterman's tester, saved a screenshot or page capture of every result, and published our scripts and DNS data on GitHub so you can check the expected results yourself. When a competitor does something well, we say so.
TL;DR
- Three checkers gave the right overall status on all six domains and explained every case accurately: DMARKOFF, Red Sift and Kitterman. URIports was right on five; on project7.com it showed a harmless typo under the same red "issue detected" banner it uses for broken records, so its verdict there is unclear.
- The most common mistake is treating a harmless typo as a fatal error.
ip4=50.31.98.110(with=instead of:) is an unknown modifier. Receivers ignore it, so the record still works but that IP is not authorized. Five of the nine other checkers called the whole record invalid, and dmarcian even says "no terms will be evaluated". - Two checkers put a passing headline on broken records.
- PowerDMARC showed a Valid badge on all three records whose SPF evaluation ends in a permerror, even though its issue list further down flags each problem.
- dmarcly showed "Success! Everything appears fine" on two of them, with no warning at all.
- Void lookups are almost invisible. On turnlss.com, a sender that none of the domain's providers lists runs into the recommended limit of two void lookups through Salesforce's
exists:%{i}macros, before evaluation even reaches the obviously broken include. In our test, only DMARKOFF, Red Sift and Kitterman caught it. - Among the tools we tested, only DMARKOFF shows exactly where evaluation stops. Its tree marks the term that triggers the permerror and greys out every term that is never evaluated.
- Problems in your provider's record are often blamed on you.
- EasyDMARC told korben.info to remove a
ptrthat actually lives in OVH's record. - dmarcly's "flattened record" copied that
ptrinto the customer's own record.
- EasyDMARC told korben.info to remove a
- "Free flattening" can change who is authorized without telling you. dmarcly's flattened version of the
ip4=typo becomes a realip4:that the current record does not grant. - You can test a candidate fix before you publish it. DMARKOFF accepts a draft record and evaluates it as if it were live, resolving every include in real DNS. A draft that "fixes" gitlab.com still showed 12/10 lookups before anyone touched DNS.
Why SPF checkers disagree
A receiving server evaluates your SPF record from left to right and stops at the first term that matches the sending IP. Five rules from RFC 7208 decide whether that walk ends in a normal result (pass, fail, softfail or neutral) or in a permerror. For DMARC (RFC 9989), a permerror means SPF can't provide an aligned pass: the message then needs aligned DKIM to pass DMARC, and what happens to it depends on the domain's policy and the receiver.
Almost every disagreement in this test comes from a checker getting one of these five rules wrong, or from showing the right number without saying what it means.
The test
We picked five real domains, each with a different trap, plus google.com as a clean control.
How we ran it
- Dates. We ran all tests between 15 and 20 October 2026.
- DNS. We captured every TXT record in each SPF chain at the start and at the end of the test window. The SPF records matched in both captures; we didn't monitor them in between. The only change was two extra, unrelated TXT records at sisley.fr (55 → 57), which affects only the size figure in the record-size section.
- Expected results. We traced each record against RFC 7208 with a small
dig-based script, then confirmed every final verdict with pySPF through Kitterman's tester. For sender-specific checks we used test IPs, with MAIL FROMpostmaster@the tested domain: 192.0.2.1 for a sender nobody lists, plus IPs that should match (see the reference table). The lookup and void counts in the reference table come from our trace; pySPF confirmed the verdicts. - What we compared. Domain checkers don't evaluate a specific sender, so we compared each one's overall status with what RFC 7208 implies for the published record: does it work, and if not, where does it break.
- Free versions only, as an anonymous visitor. No accounts, no email addresses, and optional cookies declined wherever there was a choice. Red Sift showed a Cloudflare "verify you are human" checkbox, which we ticked by hand.
Results at a glance
✅: overall status right, explanation accurate · ⚠️: overall status right, but the explanation, severity or advice is incomplete or misleading · ❔: overall status unclear (the tool shows the same headline for broken and working records, and its explanation doesn't settle which this is) · ❌: overall status wrong (a working record called invalid, or a broken record shown as valid)
Correct overall status (✅ or ⚠️) / fully accurate (✅ only): DMARKOFF 6/6 · Red Sift 6/6 · Kitterman 6/6 · URIports 5/4, plus 1 unclear · dmarcian 5/4 · EasyDMARC 5/3 · MxToolbox 5/3 · Mailhardener 5/2 · dmarcly 3/1, plus 1 unclear · PowerDMARC 2/2. Kitterman runs pySPF, the library we used to confirm the expected results, so its score is a consistency check rather than an independent result.
Trap 1: the limit breaks inside someone else's include (gitlab.com)
gitlab.com's own record has only eight DNS-querying terms. The problem is include:mailgun.org. Mailgun's record nests two more levels, so the walk passes 10 terms while it is inside Mailgun: term #11 is include:_spf2.mailgun.org. Every sender matched before that point still passes, including Google, Zendesk, Marketo and Mailgun's first block. A sender that matches nothing gets a permerror there, and so does every sender listed later, including the two ip4 addresses at the very end of gitlab.com's own record.
Two numbers are worth telling apart here. 13 is the size of the fully expanded record, and it's what most checkers show. 11 is where evaluation actually stops for a sender that matches nothing.
Most checkers found the 13, but most stopped there.
- PowerDMARC printed a Valid badge right next to Lookup Count 13/10. Its issue list further down does say "SPF lookup limit exceeded", but the badge is what people read first.
- dmarcly called it a "Warning" about "deteriorated deliverability", the same headline it gives korben.info's working record. It's a permerror.
- MxToolbox reported "Too many included lookups (13)" and offered paid flattening. Its term table lists what each qualifier means ("Pass" for
+, "Fail" for-), not which terms receivers actually reach. - Mailhardener marked the record "not valid", but the reason changed between runs (an unreachable nameserver, then an unrelated AAAA NODATA). The 10-lookup limit was never mentioned.
- EasyDMARC came closest. It numbers lookups in evaluation order and colours #11 to #13 red, but doesn't say what that means for your senders.
DMARKOFF lays out the same walk receivers do. Every DNS-querying term gets its number. #11 is marked over the limit, and a banner below it reads "Receivers stop here with permerror. The terms below are never evaluated." Everything after the break, _spf.eu.mailgun.org, _spf.sendergen.com and the final ip4 terms, is greyed out. The Explanation tab says it in words: only senders matched before that point get pass.

DMARKOFF: the exact term where evaluation stops, and everything receivers never look at.

EasyDMARC numbers lookups in order. The closest any competitor gets to a break point.

PowerDMARC: a "Valid" badge, with 13 of 10 lookups and an exceeded-limit warning on the same screen.
Trap 2: an include that points nowhere (sisley.fr)
sisley.fr includes mailer1.eu.threatsim.com, a name that publishes no SPF record. RFC 7208 §5.2 makes that a permerror for any sender who reaches it. Google senders and the two ip4 addresses listed before it still pass.
Most checkers caught this one. Two didn't say so in the headline:
- PowerDMARC: a Valid badge, with "No valid SPF records found for 'mailer1.eu.threatsim.com'" listed among two issues below it.
- dmarcly: "Success! Everything appears fine with your SPF record". Its free flattened record also silently drops the broken include.
URIports stood out in a good way. Along with the error it offered a corrected record with the dead include removed. DMARKOFF marks the include no SPF record, ends the walk there and shows ~all as never evaluated.

DMARKOFF: the walk ends at the include with no SPF record, and ~all is never evaluated.

dmarcly: "Success!" for a record whose SPF evaluation ends in a permerror.

URIports: names the problem and hands you a corrected record.
Trap 3: a ptr you didn't write (korben.info)
korben.info's record is short and clean: include:mx.ovh.com include:spf.brevo.com ~all. The two ptr terms that SPF best practice discourages are in OVH's record. korben.info can't edit them; only OVH can. They also have a side effect most tools miss. For any sender without reverse DNS, each ptr is a void lookup, so together they use up both void lookups the recommended limit allows. One more anywhere in the record would tip a receiver using that default into a permerror.
- EasyDMARC: "Remove it from your SPF record to ensure proper authentication." That's advice korben.info can't follow: the
ptrterms aren't in its record. - dmarcly: its "flattened SPF record" copies OVH's
ptrterms into the customer's own record, where korben.info would then be responsible for them. - MxToolbox: its PTR check reported "No type PTR found". The two
ptrterms in OVH's record didn't appear in its report. - Mailhardener: showed 2 additional DNS queries. RFC 7208 counts 4: the two includes plus OVH's two
ptrterms. - PowerDMARC: got the attribution right: "PTR record found, inside the SPF record of 'mx.ovh.com'".
- Red Sift: showed void 2/2.
DMARKOFF shows the ptr terms inside the OVH node, tagged "no PTR for unlisted senders". The void check reads 2 of 2: ptr:mail-out.ovh.net (inside mx.ovh.com) and ptr:mail.ovh.net (inside mx.ovh.com), for a sender without reverse DNS. The fix text points to the right owner: "This term is in your provider's SPF record… There is nothing to change in your own record: only the provider can change theirs. If it matters to you, contact the provider." In practice that means asking OVH whether it offers an alternative include, or dropping the include once you no longer send through OVH.

DMARKOFF: both ptr terms sit inside OVH's record, not in korben.info's.

DMARKOFF: counts the voids and tells you the fix belongs to your provider.

EasyDMARC: advice the customer can't follow.
Trap 4: a one-character typo (project7.com)
project7.com ends its record with ip4=50.31.98.110 -all. The = turns the mechanism into a modifier named ip4. RFC 7208 §6 is explicit: unknown modifiers must be ignored. The record stays valid and every other term works, but 50.31.98.110 is not authorized. Kitterman's tester confirms it: that IP gets FAIL.
The failure here can go either way, and the market managed both.
Too harsh. Five checkers called the record invalid: MxToolbox ("Invalid syntax found"), dmarcian, EasyDMARC, PowerDMARC and Mailhardener. dmarcian goes furthest: "SPF record … has invalid syntax: no terms will be evaluated", and it shows 0 lookups with every term "(ignored)". That would be true for a genuine syntax error. For this record it's wrong. Receivers evaluate it normally: Microsoft, Recharge, Shopify and SendGrid senders still pass, and a sender none of them lists goes through all eight DNS-querying terms before reaching -all.
Unclear.
- URIports listed the term as an "invalid modifier value" error, under the same red "1 issue detected" banner it shows for gitlab.com, sisley.fr and turnlss.com. Nothing on the page says whether project7.com's record still works. The value is fine; the modifier is unknown, so receivers ignore it. Its suggested replacement record keeps the typo and only changes
-allto~all.
Too lenient.
- dmarcly says "Success!" and then offers a flattened record ending in
ip4:50.31.98.110 -all. That quietly changes who is authorized: the published record doesn't grant that IP, the flattened one does, and dmarcly never mentions the difference.
Red Sift flagged Unknown modifier and Possible Typo. DMARKOFF marks the term ignored by receivers and suggests the fix: "ip4=50.31.98.110": unknown modifier, so receivers ignore this term (did you mean ip4:50.31.98.110?).

DMARKOFF: the typo is marked "ignored by receivers", with the likely fix.

dmarcian: describes a whole-record failure that isn't happening.

dmarcly: the flattened record quietly authorizes the IP from the typo.
Trap 5: void lookups behind macros (turnlss.com)
turnlss.com has an obvious problem: include:_spf.wpengine.com has no SPF record. But a sender that none of the domain's providers lists never gets that far.
Before WP Engine, the record includes both _spf.salesforce.com and salesforce.com. Salesforce's corporate record includes _spf.salesforce.com again and adds its own macro. That makes three exists:%{i}… terms. Each one builds a DNS name from the sender's IP and, for any sender Salesforce doesn't list, gets back nothing: a void lookup. Under the recommended limit of two, the third one, exists:%{i}._spf.corp.salesforce.com (term #8), ends evaluation with a permerror before WP Engine (term #9) is ever queried. A receiver configured with a higher limit would reach WP Engine and return a permerror there instead. The result is the same; only the place changes.
Senders that one of the providers does list stop earlier, with a pass: Microsoft senders at term #1 and Salesforce senders at #3. Google senders pass at #5, because Salesforce's corporate record includes Google's.
In our test, three checkers saw the void-lookup problem:
- Kitterman: "PermError SPF Permanent Error: Void lookup limit of 2 exceeded", for both the domain check and a test IP.
- Red Sift: Void Lookups 3/2, plus a note that macro results depend on the SMTP session.
- DMARKOFF: names all three terms with their paths, moves the break to the 3rd void lookup, and still flags WP Engine below it as never evaluated, so you fix both. It also flags the duplicate
_spf.salesforce.comand recommends keeping the include Salesforce documents for customers while dropping the corporateinclude:salesforce.com.
The other checkers, except dmarcly, reported the WP Engine include and stopped there. MxToolbox explicitly said "Number of void lookups is OK". dmarcly reported nothing at all.

DMARKOFF: the break moves to the 3rd void lookup. The WP Engine error is still listed below it.

Kitterman's pySPF: the reference result.
Bonus: your other TXT records count too
RFC 7208 §3.4 has a rule almost nobody checks. A receiver fetches your SPF record with one DNS query for all TXT records at your domain, so every site-verification token comes along in the same answer. The RFC recommends keeping the domain name plus the text of all those records under 450 bytes, so the answer fits in a 512-byte UDP packet. Larger answers need EDNS0 or a retry over TCP. Most receivers handle that, but some resolvers and firewalls do not.
Our test domains were far over:
This is the RFC's measure, not the size of the DNS packet itself.
Only two of the tested checkers flagged it:
- Kitterman printed "DNS: Truncated UDP Reply, SPF records should fit in a UDP packet, retrying TCP".
- DMARKOFF shows a Notice that names the cause, for example "2,165 bytes for gitlab.com and its 32 TXT records; RFC 7208 §3.4 recommends under 450". It explains that old site-verification tokens are the usual culprit. Because it's a notice, google.com still rates Healthy.

DMARKOFF: a notice that names the cause, gitlab.com's 32 TXT records.

Kitterman: notes the truncated UDP reply and retries over TCP.
Test an SPF record before you publish it
Every result above describes a record that's already live. The better moment to catch these mistakes is before the change reaches DNS.
DMARKOFF's SPF checker has a second field under the domain: "SPF record (optional — evaluate instead of DNS)".
- What it evaluates: the record you paste, as if it were published at that domain.
- What still uses live DNS: every
include,a,mxandexistsis resolved for real, so you see the actual lookup count, void lookups and dead includes your draft would produce. - What it skips: checks that only make sense for what's already published, such as the TXT size notice.
We tried it on candidate fixes for four of the domains; korben.info doesn't need one. A candidate is only a starting point: a passing check shows the record is well-formed, not that it still authorizes every service the domain uses.
turnlss.com, a candidate fix. We dropped the corporate include:salesforce.com and the dead WP Engine include:
v=spf1 include:spf.protection.outlook.com include:_spf.salesforce.com ~all
Result: Healthy, 3/10 lookups, 1/2 void lookups. Today the record ends in a permerror for unlisted senders: 9 DNS-querying terms in the expanded record, and evaluation stops at the 8th with 3 void lookups.
This draft also changes who is authorized. The corporate salesforce.com record pulls in Google's sending ranges, so dropping it means a Google IP that passes today (209.85.128.1 in our trace) would get softfail. turnlss.com's MX points to Microsoft 365, but MX records only show where a domain receives mail, not which services send on its behalf, so the domain owner has to check whether anything sends through Google. If they do send through Google Workspace, adding include:_spf.google.com keeps it: that draft shows Healthy, 4/10 lookups, 1/2 void lookups. Likewise, before deleting the WP Engine include, check whether the site still sends through WP Engine and which include WP Engine documents today.

Paste the draft, run the check, see the result the record would get once published.
sisley.fr, a candidate fix. Removing the ThreatSim include gives Healthy, 1 lookup. Today that include authorizes nobody (it only causes the permerror), so removing it takes no working sender away. If sisley.fr still runs ThreatSim campaigns, use whatever include the vendor documents today.
project7.com. Changing ip4= to ip4: clears the typo warning. Only two informational notes remain, about SendGrid being included twice inside the providers' own records. This one changes authorization on purpose: 50.31.98.110, which fails today, would pass.
gitlab.com, the fix that isn't. A natural first attempt is to drop the Zuora a: term. The draft comes back at 12/10, still a permerror. You learn that in seconds, not after a week of DMARC reports.

DMARKOFF: without the Zuora term, the draft is still at 12 of 10 lookups.
Typos caught before they go live. We also pasted common mistakes against example.com to see how each is reported:
Of these, only the syntax errors and the missing include make the record fail. A record without all or redirect= is still valid; senders it doesn't match simply get the default result, neutral.

DMARKOFF: ipv4: breaks the whole record, and the checker suggests ip4:.

Handy when a vendor gives you an include host before they've published it.
DMARKOFF isn't the only tool that accepts a pasted record. Kitterman's tools have record fields, Mailhardener's input accepts v=spf1… directly, and EasyDMARC has a separate "SPF Raw Checker". We didn't test those modes for this article.
Feature comparison
● yes · ◐ partly · ○ no · — not offered. Based on the free pages we tested; a vendor may offer more in a separate tool.
Tool by tool
DMARKOFF
- Overall status: correct on all six, with accurate explanations.
- Strengths: among the tools we tested, the only one that shows the exact break point, both for the lookup limit and the void limit. Unknown modifiers are handled the way receivers handle them, with a "did you mean" suggestion. Problems are attributed to your record or your provider's, and duplicate includes are explained. The draft-record field lets you test a candidate fix before publishing.
- Views: results come as a tree or a plain-language table, with a shareable link.
Red Sift
- Overall status: correct on all six, including both void-lookup cases.
- Strengths: names the services behind each include (Zendesk, Marketo, Mailgun and so on) and shows authorized-address totals.
- Gaps: doesn't show where evaluation stops, didn't flag duplicate includes in our run, and its "Possible Typo" card had no explanation text.
Kitterman
- Overall status: correct on all six. It runs pySPF, the library we used to confirm our expected results, so this is a consistency check rather than an independent score.
- Strengths: the only checker among the pages we tested that lets you test a specific sending IP and HELO name.
- Gaps: a plain text form with no tree and no explanations. Use it to confirm a verdict, not to understand one.
URIports
- Strengths: correct overall status on five of the six domains, RFC section references, and a ready-to-paste corrected record.
- Gaps: showed project7.com's harmless typo as an "invalid modifier value" error under the same banner it uses for broken records, kept the typo in its suggested record, and didn't report the void lookups on turnlss.com.
dmarcian SPF Surveyor
- Strengths: the clearest include tree, with lookup counts on every node and authorized-netblock totals. It explicitly advises against flattening.
- Gaps: called project7.com's typo a whole-record failure and didn't report void lookups in our run.
EasyDMARC
- Strengths: correct lookup counts, plus a numbered tree that colours lookups past the limit.
- Gaps: told korben.info to remove a provider's
ptr, called the typo invalid, and pushes paid "EasySPF" flattening. The full domain report needs an email address.
MxToolbox
- Strengths: flagged the lookup limit on gitlab.com, the dead include on sisley.fr and the duplicate includes on turnlss.com.
- Gaps: called the typo invalid syntax and reported void lookups as OK on turnlss.com. Its term table shows what each qualifier means rather than which terms receivers reach. Upsells paid flattening.
Mailhardener
- Strengths: detailed per-term descriptions and authorized-address totals.
- Gaps: its gitlab.com verdict rested on an unrelated DNS response rather than the lookup limit. Its query count for korben.info was 2 where RFC 7208 counts 4, and it called the typo invalid.
dmarcly
- Gaps: "Success!" on two permerror records with no warning, the same "Warning" headline for gitlab.com's permerror as for korben.info's working record, and a free flattened record that drops broken includes, carries a provider's
ptrinto your record and turns an ignored typo into a liveip4:.
PowerDMARC
- Strengths: the best wording on the provider's
ptramong competitors. - Gaps: its headline badge read Valid on all three records whose evaluation ends in a permerror, even though the issue list below flagged each problem. Read past the badge.
Valimail
- Its domain checker shows no SPF details, only a summary and a sales booking form, so we couldn't compare it.
A word on "free flattening"
Flattening replaces includes with the IP addresses behind them, to get under the 10-lookup limit. It's tempting, and three of the tools we tested sell it: EasyDMARC, MxToolbox and dmarcly. Our test shows why it needs care:
- It can drop broken includes silently. dmarcly's flattened sisley.fr record hides the problem instead of showing it.
- It can turn ignored text into live authorization. dmarcly's flattened project7.com record authorizes 50.31.98.110, which the published record does not.
- It copies whatever is in your provider's record,
ptrterms included, so mechanisms your provider was responsible for become part of a record you maintain. - A one-time copy freezes your provider's IPs. When Mailgun or Salesforce changes addresses, a static flattened record goes stale and legitimate mail starts failing. Managed flattening services say they keep the copy updated automatically; we didn't evaluate those.
dmarcian and Mailhardener both advise against flattening. If you do flatten, test the result before you publish it.
Which free SPF checker should you use?
- To understand what's wrong and how to fix it: DMARKOFF. It got the overall status and the explanation right on all six domains, shows where evaluation stops, separates your record from your provider's, and lets you test a candidate fix before publishing.
- For a second opinion with service names and address totals: Red Sift.
- To confirm a verdict, or to test one specific sending IP: Kitterman.
- For a quick visual of who costs you lookups: dmarcian's tree, but don't trust its verdict on unknown modifiers.
- Read twice: any "Valid" badge from PowerDMARC, any "Success!" from dmarcly, and any flattened record you didn't check yourself.
Methodology and data
Dates and versions. All checkers were tested between 15 and 20 October 2026, using the free versions available without an account. Free tools change often, so the screenshots show what we saw during that window.
Inputs. Domain checkers were run on the domain name alone. Our own traces used resolver 1.1.1.1. Sender-specific verdicts were cross-checked with Kitterman's web tester, which uses its own DNS resolver. MAIL FROM was postmaster@ the tested domain, and HELO was the tested domain.
Data and scripts. Everything needed to rerun our expected results is in dmarcoff/articles on GitHub: the DNS answers recorded during the test, our RFC 7208 tracer, the raw DMARKOFF responses and all screenshots. verify.py runs every row of the reference table through pySPF, either offline against the records as published during the test, or against today's DNS with --live.
DNS records on the test dates
Captured via 1.1.1.1 at the start and at the end of the test window (15–20 October 2026). The SPF records below matched in both captures.
gitlab.com's DNS-querying terms in order: 1 zendesk · 2 _spf.google · 3 mktomail · 4 _spf.salesforce · 5 exists:%{i} · 6 _spf-ip.gitlab · 7 a:zgateway.zuora.com · 8 mailgun.org · 9 _spf.mailgun.org · 10 _spf1.mailgun.org · 11 _spf2.mailgun.org · 12 _spf.eu.mailgun.org · 13 _spf.sendergen.com.
Reference results
From our trace. The verdicts for the published records were confirmed with pySPF through Kitterman's tester. Running pySPF locally on the recorded DNS answers reproduces all 14 rows, including the two candidates and every count (see Data and scripts above). "Terms reached" includes the term at which evaluation stops. When that's an 11th DNS-querying term, it isn't queried; a void-limit permerror happens after the third empty answer has come back.
Checkers tested
If you maintain one of these tools and something has changed, let us know and we'll retest.
FAQ
A permanent error: the receiver couldn't evaluate your SPF record to a result. Common causes are reaching an 11th DNS-querying term, more void lookups than the receiver allows (two is the recommended limit), an include that points to a name without an SPF record, or a syntax error. For DMARC (RFC 9989), a permerror means SPF can't provide an aligned pass. The message can still pass DMARC through aligned DKIM, and whether it's delivered depends on the domain's policy and the receiver.
Count the terms that trigger DNS queries: include, a, mx, ptr, exists and redirect=, at every level of nesting. ip4, ip6 and all are free. The limit is 10 (RFC 7208 §4.6.4). Two numbers are worth telling apart: the total for the fully expanded record, which is what most checkers show, and the point where evaluation actually stops for a given sender. A good checker shows both.
A DNS query that returns no records: for example an a: term for a host that doesn't exist, an include that points to a name with no TXT records, or a macro like exists:%{i}._spf.example.com for a sender it doesn't list. RFC 7208 says receivers should allow at most two (the limit may be configurable, and two is the recommended default). With that default, the third one is a permerror. Because macros depend on the sender, the count can differ from one sender to the next.
No. A syntactically valid name=value term, other than redirect= or exp=, is an unknown modifier, and receivers ignore it (RFC 7208 §6). Both the name and the value have to follow SPF syntax: foo=%, for example, is a syntax error. The rest of the record keeps working, but the address in the typo is not authorized. A typo in a mechanism name, such as ipv4:, is different: that is a syntax error and the whole record fails.
If it's in your own record, replace it. List the servers it was meant to cover with ip4, ip6, a or include, test the new record, and then remove the ptr: RFC 7208 says ptr should not be used. If it's inside a provider's record that you include, you can't edit it yourself. Ask the provider whether it offers an alternative include, or drop the include once you no longer send through that provider. A good checker tells you which of the two cases you're in.
Yes. DMARKOFF's SPF checker has an optional field that evaluates a pasted record instead of the one in DNS, while still resolving every include live. Kitterman, Mailhardener and EasyDMARC also offer ways to check a pasted record.
Indirectly. Receivers fetch all TXT records at your domain in one DNS answer. RFC 7208 §3.4 recommends keeping the domain name plus the text of all those records under 450 bytes, so the answer fits in a single UDP packet. Removing old verification tokens is usually the easiest fix.
Co-founder & CTO at DMARKOFF and GlockApps, email security specialist with 20+ years of experience, Golang & ClickHouse expert. A happy father of two teenagers.


