Diagnosing mail that lands in spam after adding a sender
A new marketing or ticketing platform pushes the record over ten lookups, and every message starts failing SPF regardless of provider.
Parses an SPF record: mechanism checks, DNS lookup count, and the policy (~all vs -all).
Fetches the TXT record, counts DNS lookups (RFC 7208 limit: 10) and flattens includes.
Parses an SPF record: mechanism checks, DNS lookup count, and the policy (~all vs -all).
example.com
v=spf1 include:_spf.google.com ~all — PASS · 3 DNS lookups
Includes an explanation of each mechanism.
The policy (-all/~all) tells receivers how strictly to treat failures.
Your input is sent to YAS infrastructure because the tool requires server-side processing or public network queries. Input is not stored.
curl -X POST "https://yas.sh/api/v1/tools/spf-inspector" \
-H "Content-Type: application/json" \
-d '{"input":"example.com"}'const res = await fetch("https://yas.sh/api/v1/tools/spf-inspector", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"input": "example.com"
}),
});
const data = await res.json();import requests
r = requests.post("https://yas.sh/api/v1/tools/spf-inspector", json={"input":"example.com"})
data = r.json()| Field | Type | Required | Description |
|---|---|---|---|
| input | string | Yes | Domain, e.g. example.com |
{ "result": { "record": "v=spf1 ip4:1.2.3.4 include:_spf.example.com ~all", "lookupCount": 2, "lookupLimit": 10, "hasAll": true, "allValue": "~all", "permError": false, "flattenedIps": 6, "tree": [...] } }Parse SPF (v=spf1): mechanisms, DNS-lookup count vs the 10 limit, ~all/-all, flattened IP count.
400 VALIDATION_ERROR — invalid input or unsupported option.413 PAYLOAD_TOO_LARGE — input exceeds the 64 KB limit.429 RATE_LIMIT_EXCEEDED — rate limit exceeded (60 req/min).SPF publishes a TXT record listing which hosts may send mail for a domain. A receiver checks the SMTP envelope sender's domain (the MAIL FROM, not the visible From: header), evaluates the mechanisms in order — a, mx, ip4, ip6, include, exists — and applies the first match. The qualifier on the terminating all mechanism decides the outcome for everything else: -all is a hard fail, ~all a soft fail, ?all neutral.
The binding constraint is the ten-DNS-lookup limit in RFC 7208. Each include, a, mx, ptr and exists costs lookups, and nested includes count recursively. Exceeding ten produces a permerror, which most receivers treat as a failure — so an SPF record that grew by one SaaS provider too many can break authentication for every message the domain sends.
A new marketing or ticketing platform pushes the record over ten lookups, and every message starts failing SPF regardless of provider.
SPF records accumulate includes for tools nobody uses any more, each one an authorised sender you have forgotten about.
DMARC requires SPF or DKIM to pass and align. Verifying SPF alignment before setting p=reject prevents rejecting your own mail.
A parked domain should publish v=spf1 -all plus a null MX, which removes it as a spoofing vector.
What this tool deliberately does not do, and where it will disagree with other implementations.