FREE · NO ACCOUNT REQUIRED

Free SPF record checker — 10 / 2 lookup meters, policy explainer, sender inventory, provider fingerprint, and a client-side sender-IP simulator.

SPF Checker pulls your v=spf1 TXT record, expands every include to its leaves (typically 5–7 levels deep), and shows what actually matters: a live progress meter against the RFC 7208 ten-lookup limit and the two-void-lookup ceiling, a plain-English policy card (-all / ~all / ?all / +all), a sender inventory summing every authorised IPv4 and IPv6 across the chain, a fingerprint of known providers (Google Workspace, Microsoft 365, SendGrid, Mailgun, Amazon SES, Mailchimp, Zoho, Postmark, Klaviyo, HubSpot and more), rule-based findings that appear instantly, and a Test-an-IP simulator that walks the resolved chain for any sender IP with zero extra DNS queries. AI review layers on top with severity-ranked recommendations.

01 · OVERVIEW

What gets analyzed

Nine independent classes of output per check. Parsing, chain expansion and RFC compliance are the headlines; the live lookup / void meters, policy explainer, sender inventory, provider fingerprint and client-side IP simulator are what set this apart from flat SPF checkers.

SPF record parsing (RFC 7208)

Full parse into version, mechanisms (ip4, ip6, a, mx, include, exists), qualifiers (+, -, ~, ?), modifiers (redirect, exp), and the terminal `all` directive. Each piece is structured so downstream tools can act on it.

Recursive chain expansion (Every include followed)

Every `include:` is recursively expanded to its final IP4 / IP6 lists. The chain is typically 5–7 levels deep for any domain with non-trivial email infrastructure. Microsoft.com's chain has 5 top-level includes and 7 total DNS lookups.

10-lookup + 2-void meters (RFC 7208 §4.6.4)

Live progress bars against BOTH RFC ceilings: the 10-lookup cap (every include / a / mx / exists / redirect) and the 2-void-lookup cap (ptr / exists resolving to nothing). Green / amber / red bands with a plain-English margin summary. Both caps are silent permerror cliffs — most flat checkers only surface the first.

Policy strength explainer (-all · ~all · ?all · +all)

Classifies the trailing `all` qualifier as Strict / Soft-fail / Neutral / Dangerous / Missing, with a one-line headline and a paragraph of what receivers actually do. `+all` gets called out as a critical misconfiguration; `?all` and missing terminators as no-enforcement states.

Sender inventory (IPv4 · IPv6 · Includes)

Sums every unique IPv4 CIDR, IPv6 CIDR and include domain across the fully-expanded chain. Answers the question 'exactly how many machines are allowed to send as me' — surprising answer for most domains.

Provider fingerprint (Known-sender detection)

Matches include domains against a curated list of well-known providers: Google Workspace, Microsoft 365, SendGrid, Mailgun, Mailchimp, Amazon SES, Fastmail, Zoho, Salesforce, Postmark, Mimecast, Klaviyo, HubSpot, Constant Contact, iCloud and more. Renders as coloured pills so you can see 'who's sending as me' at a glance.

Health score + real stats (Not hardcoded)

Composite score derived from pass ratio, lookup pressure, void count and policy strength — bands into Excellent / Good / Fair / Poor with a matching tone. The four stat cards (Policy Strength, DNS Lookups N/10, Mechanisms, Record Status: Valid / Warning / Broken / Missing) all reflect the parsed record, not placeholder text.

Rule-based Security tab (Instant + AI merge)

Findings render immediately from the parsed record and tests: critical / warning / info / passing, each with a Fix pill. AI enrichment merges in when the analysis lands (top banner shows progress). The tab is never a dead page waiting on AI.

Test-an-IP simulator (Client-side · zero DNS)

New tab. Paste any IPv4 or IPv6 and walk the resolved chain client-side — returns pass / softfail / fail / neutral with the exact mechanism that matched and the include it lived in. Includes suggested sample IPs (Google Workspace, M365, SendGrid, a random neighbour) so you can smoke-test any record in seconds.

02 · WHY THIS MATTERS

Why SPF is still the foundation in 2026

SPF has been around since 2006 (RFC 4408, then RFC 7208), it gets compared unfavorably to DKIM and DMARC, and yet it remains the single most-checked email-authentication signal — and the single most-misconfigured one. Five things that make SPF still matter:

  • Without SPF, your domain is spoofable by default. An attacker can spoof emails from your domain to your customers (or your CEO) with no technical work required. SPF is the first line of defense — it tells receivers which IPs are allowed to send mail for your domain.
  • DMARC requires SPF or DKIM alignment. DMARC is the policy layer; it makes decisions based on whether SPF and/or DKIM aligned. You can technically do DMARC with only DKIM, but in practice almost every working DMARC setup leans on aligned SPF for at least some senders.
  • Misconfiguration is silent until you investigate. An SPF record over the 10-lookup limit returns PermError — and most receivers treat that as 'no SPF', not as 'broken SPF'. Your mail keeps flowing, just without authentication. You only find out when deliverability dies or a phishing campaign succeeds.
  • Vendor includes compound over time. Every SaaS that sends mail on your behalf — marketing platform, transactional ESP, helpdesk, calendar, billing — asks you to add their `include:` to your SPF. Five vendors in, you're already at the lookup limit. Most teams discover this only after a sixth vendor is added and email stops authenticating.
  • Even Fortune 500 records have bugs. microsoft.com's SPF record (the live sample on this page) has a critical malformed entry — `ip4:20.` instead of a complete IP address — in one of its included sub-records. If Microsoft can ship a broken SPF record, so can anyone. Automated checking catches what manual review misses.
03 · HOW IT WORKS

TXT lookup, parse, recurse, validate

An SPF check is a recursive walk through DNS. We follow the same algorithm a receiving mail server would, expand every include to its terminal IPs, and count DNS lookups along the way — exactly as RFC 7208 specifies.

  • Stage 1 — Fetch the TXT record Query the target domain for TXT records. Filter for the one starting with `v=spf1`. If there are multiple, that's already a violation — a domain can only have one SPF record (we report this as a test failure).
  • Stage 2 — Parse mechanisms left-to-right Each space-separated token is a mechanism or modifier. Mechanisms get a qualifier prefix (default `+`); modifiers use `=` syntax. Order matters — SPF evaluates left-to-right and stops at the first match.
  • Stage 3 — Recursively expand includes For each `include:domain`, fetch that domain's SPF record and recurse. Track the lookup count globally — every recursive call adds to it. Build the chain as a tree for visualization.
  • Stage 4 — Count DNS lookups Increment for each include, a, mx, exists, redirect — anything that requires a DNS query. ip4/ip6/all don't increment. Compare against the 10-limit; anything over is fatal (PermError).
  • Stage 5 — Run validation tests RFC 7208 checks: multiple-record detection, DNS lookup count against the 10-limit, void-lookup count against the 2-limit, policy-strength classification, deprecated `ptr` detection, record-length check, syntax validity. Each is pass/fail with an explanation.
  • Stage 6 — Compute derived analytics client-side From the resolved chain we compute the health score (weighted by pass ratio, lookup pressure, void count, policy), the policy classification with plain-English headline, the sender inventory (aggregated unique IPv4 / IPv6 / include domains), and the provider fingerprint (curated regex match against include domains). All zero-cost — pure functions over the already-fetched data.
  • Stage 7 — Rule-based findings + AI review Rule-based findings render instantly (critical/warning/info/passing) so the Security tab is never a dead page. AI enrichment feeds the parsed record + chain + tests to the analyzer and merges in severity-ranked issues with concrete recommendations. Both sets combine in one severity-sorted list.
04 · TERMINOLOGY

SPF vs DKIM vs DMARC — what each one actually does

These three terms get used interchangeably and conflated constantly. They're not interchangeable — they solve different problems and complement each other. The shortest accurate framing: SPF authorizes IPs, DKIM signs messages, DMARC sets policy. You generally want all three.

  • SPF — Sender Policy Framework Lists which IP addresses are allowed to send mail for your domain. Lives in DNS as a TXT record. IP-based — checks the connecting server's IP against your published list. Easy to set up; brittle when forwarded (forwarding changes the sending IP, breaking SPF).
  • DKIM — DomainKeys Identified Mail Cryptographically signs the outgoing message body and selected headers. The signature travels with the message; receivers verify it using a public key published in DNS at `<selector>._domainkey.<domain>`. Content-based — survives forwarding, since the signature stays attached to the message. Harder to set up than SPF, more reliable in practice.
  • DMARC — Domain-based Message Authentication, Reporting, and Conformance Tells receivers what to do when SPF or DKIM fails — none (just monitor), quarantine (junk it), or reject (block entirely). Lives at `_dmarc.<domain>` as a TXT record. Adds reporting (rua, ruf) so you find out who's being authenticated and who isn't. Policy-based — coordinates the two underlying mechanisms.
  • How they fit together A mail flow that's properly authenticated has: SPF allowing the sender's IP, DKIM signature verifying with a matching DNS key, AND DMARC policy that aligns the From: domain with the SPF/DKIM-authenticated domain. Receivers grade the message based on all three; DMARC's `p=reject` is the strongest signal you can publish.
  • What this tool covers SPF only. For DKIM verification, see the DKIM Checker. For DMARC policy parsing and report-URI validation, see the DMARC Checker. For a combined health view across all three, see the Email Authentication tool.
05 · MECHANISMS

Every SPF mechanism, explained

An SPF record is a sequence of mechanisms, evaluated left-to-right. The first match wins; if nothing matches, the terminal `all` decides. Each mechanism authorizes a different way of identifying a sender:

  • v=spf1 — Version (required, first) Identifies the record as SPF version 1 — the only version that exists. Must be the very first token in the record. Without it, the TXT record is just text, not SPF.
  • ip4: / ip6: — Allow specific IPs Allows the listed IPv4 or IPv6 address (or CIDR range) to send mail. `ip4:192.0.2.0/24` and `ip6:2001:db8::/32`. Does NOT count toward the 10-lookup limit — these are static and require no DNS query. The cheapest mechanism in terms of lookup budget.
  • a / a:domain — Allow A-record IPs Allows IPs found in the A (or AAAA) records of the current domain (bare `a`) or a specified domain (`a:example.com`). Counts as one DNS lookup. Used when the mail server's IPs can be derived from existing DNS.
  • mx / mx:domain — Allow MX-host IPs Allows IPs of MX-record hosts for the current domain or a specified one. One DNS lookup for the MX query, plus one each per MX target (which can stack — a domain with 4 MX servers consumes 5 lookups from a single `mx` mechanism).
  • include:domain — Include another SPF record Recursively fetches and evaluates another domain's SPF record at this position. This is what makes SPF chains deep. Counts as one lookup, plus every lookup inside the included record. The biggest source of lookup-limit exhaustion.
  • exists:domain — Allow if DNS returns any A record Passes if a DNS query for the given name returns any A record. Used in macro-based SPF for sender-specific authorization. Rare in practice. One lookup each.
  • ptr — DEPRECATED, never use Checks the sender's reverse DNS (PTR record) against the domain. Slow, unreliable, and easy to spoof. Formally deprecated in RFC 7208. The presence of `ptr` in your SPF record is itself a quality signal — none of the modern best-practice setups include it.
  • all — The terminal catch-all Matches anything not caught by previous mechanisms. Always the last token. The qualifier on `all` is what defines your SPF policy strength — see section 06.
  • redirect=domain — Replace with another record (modifier) Discards this record and uses the target domain's SPF instead. Used by SaaS platforms to consolidate SPF management. Counts as one lookup. Can't coexist with an `all` mechanism in the same record.
  • exp=domain — Custom explanation (modifier) Specifies a domain whose TXT record provides a custom explanation message for failures. Almost never used in practice; receivers don't typically display it.
06 · QUALIFIERS

What -all, ~all, ?all, and +all actually do

Every mechanism can carry a qualifier prefix. The qualifier tells receiving mail servers what to do when the mechanism matches. The qualifier on `all` is the most consequential — it defines your overall SPF policy strength.

  • + (Pass) — The default Mail passes SPF. This is the implicit qualifier if no prefix is given — `ip4:192.0.2.1` and `+ip4:192.0.2.1` are identical. You almost never write `+` explicitly; it's understood.
  • - (Fail / hard fail) Mail FAILS SPF — receivers should reject. Used with `-all` at the end of a record for strict policy. Microsoft.com's record ends in `-all`, which is the gold-standard SPF posture: only explicitly listed senders are authorized; everyone else is rejected.
  • ~ (SoftFail) Mail fails SPF, but receivers should accept it with a soft mark (typically marked as suspicious or sent to junk, but not outright rejected). Used with `~all` during a transition or while testing — you want telemetry without breaking legitimate-but-misconfigured senders.
  • ? (Neutral) No policy expressed. Used with `?all`, which is functionally identical to not having an SPF record at all from a policy perspective. Rare; usually a sign someone forgot to finish configuring.
  • + (Pass) on `all` — DANGEROUS `+all` means 'everyone is authorized to send mail for this domain' — which defeats the entire purpose of SPF and is actively worse than having no record. If you see `+all` in a production SPF, treat it as an emergency: the domain is configured to allow universal spoofing.
  • The policy hierarchy `-all` (strict) > `~all` (testing) > `?all` (neutral, useless) > `+all` (disastrous). Production domains should land on `-all` once SPF is correctly configured. Use `~all` only while bootstrapping — long-term reliance on softfail leaves your domain partially spoofable.
07 · THE TWO SILENT LIMITS

The 10-lookup and 2-void-lookup cliffs — why SPF fails silently

RFC 7208 imposes two independent hard caps that both cause a permerror when exceeded — and permerror is silent (most receivers treat it as 'no SPF'). The 10-lookup cap counts every include / a / mx / exists / redirect. The 2-void-lookup cap counts every ptr / exists that resolves to nothing. Our Summary tab shows both as live progress meters; the Security tab escalates them to critical when hit.

  • What counts toward the limit Every `include:` (one + everything inside it). Every `a`, `mx`, `exists`, and `redirect=` directive (one each). Every PTR query inside `ptr` mechanisms (deprecated, but still counts if present). The initial TXT lookup for `v=spf1` is technically free, but `include:` chains consume budget fast.
  • What doesn't count `ip4:` and `ip6:` directives — these are static and require no DNS query. The terminal `all` — also no query. This is why SPF flattening works: replacing `include:` chains with explicit ip4/ip6 lists eliminates lookups entirely.
  • How fast it adds up A single popular SaaS include can consume 4–6 lookups on its own (their own chain has includes). Add 3 vendors and you're at 12 — over the limit. Office 365's `include:spf.protection.outlook.com` alone counts as 1 (just the outer include), but vendors that chain through Exchange Online or similar can easily blow the budget.
  • Why exceeding it is silent PermError isn't a hard reject — most receivers just treat it as 'we couldn't determine SPF', which is essentially equivalent to having no SPF record. Your mail keeps flowing, deliverability gradually degrades, and the failure mode is invisible until DMARC reports start showing fail counts. By then, you've been authenticating no mail for weeks.
  • How to fix it — by effort Easiest: audit and remove unused includes (vendors you no longer use, forgotten tools, deprecated mail relays). Medium: consolidate via a single managed-SPF provider (EasyDMARC, dmarcian, Valimail) that flattens chains for you. Hardest but most precise: maintain your own flattened SPF — replace `include:` chains with explicit ip4/ip6 lists, and monitor for upstream IP changes.
  • Why microsoft.com is at 7/10 Microsoft splits their SPF across 5 includes (`_spf-a` through `_spf-c`, plus `_spf-ssg-a.msft.net` and `_spf1-meo`). Each one expands into more lookups. They've already used 7 of the 10 allowed — adding one more vendor would risk pushing over the limit. This is a real cost of SPF that grows over time.
  • The 2-void-lookup cap (the other silent cliff) RFC 7208 §4.6.4 also permerrors when 2+ mechanisms resolve to nothing — typically `ptr` chasing a missing reverse DNS, or `exists:%{i}._foo.example.com` filters that mostly return NXDOMAIN. Because both live under the same 'permerror' response, receivers can't distinguish which cliff you hit. Our Summary meter surfaces void count independently so the failure mode is obvious.
07B · SENDER INVENTORY & PROVIDER FINGERPRINT

Who is actually allowed to send as you

Most teams add includes over the years and forget half of them. The Sender Inventory + Provider Fingerprint cards in the Summary tab answer 'who can send mail as me right now, and does that match my mental model?' — sourced from the fully-expanded chain so nothing hides behind an include.

  • Aggregate IPv4 / IPv6 / include count Walks every node in the expanded chain, deduplicates unique IPv4 CIDRs, IPv6 CIDRs and include domains. A record with three top-level includes can easily authorise 60+ CIDR blocks — the inventory number is often the first surprise.
  • Provider fingerprint from includes Each include domain is matched against a curated regex library of well-known senders: Google Workspace (_spf.google.com), Microsoft 365 (spf.protection.outlook.com), SendGrid, Mailgun, Amazon SES, Mailchimp, Fastmail, Zoho, Salesforce, Postmark, Mimecast, Klaviyo, HubSpot, Constant Contact, Proofpoint, iCloud, and others. Renders as coloured pills for a one-glance sender map.
  • What it catches Shadow senders (an SES include no one remembers adding), legacy vendors (a Mailchimp include from a campaign three years ago), acquisition drift (M365 stacked on top of Google Workspace during a migration nobody finished), and misconfigurations (a marketing platform included at the wrong scope). Every anomaly is worth investigating.
  • How to use it Cross-check the pill list against your active vendor stack. Anything you don't recognise is a candidate for removal — every removed include potentially frees lookup budget and shrinks your spoofable surface. Non-matched includes appear only as raw domain names; that's a hint to audit them by hand.
07C · TEST-AN-IP SIMULATOR

See what SPF actually decides for a sender IP

The Test-an-IP tab is a client-side SPF evaluator: paste an IPv4 or IPv6, and we walk the already-resolved chain from top-level record down through every include, returning the first mechanism that matches (or the trailing `all` if nothing matches). No new DNS queries — everything is computed from the chain we already fetched.

  • How the walk works Depth-first through the resolved chain. At each node we compare the target IP against every ip4:CIDR and ip6:CIDR mechanism. On a match we return the mechanism's qualifier: `+` → pass, `-` → fail, `~` → softfail, `?` → neutral. If nothing matches at any node, we fall through to the top-level `all` qualifier.
  • CIDR-aware matching IPv4 matching handles /0–/32 masks with 32-bit arithmetic. IPv6 matching normalises `::` shorthand, expands to eight 16-bit groups, and compares up to the requested prefix length. Bare IPs (no `/N`) are treated as /32 or /128.
  • Walk trace + matched-mechanism receipt The result card shows the exact mechanism that matched (e.g. `ip4:35.190.247.0/24`), the include it lived in (e.g. `_spf.google.com`), and the full breadcrumb of domains walked to get there. Useful for explaining SPF verdicts to stakeholders who don't want to read a raw record.
  • Suggested sample IPs Four one-click suggestions: a Google Workspace IP, an M365 IP, a SendGrid IP, and a completely unrelated IP (8.8.8.8) so you can immediately verify both the pass path and the fail path against any domain's SPF.
  • What it's for Deliverability investigations ('why did this specific IP softfail?'), pre-migration checks ('will the new ESP's outbound range match my SPF?'), incident response ('is the phishing IP actually in our SPF?'), and vendor audits ('does the ESP's own SPF cover the IPs they actually use?').
08 · API

Use this programmatically

Every field — parsed record, expanded chain, test results, AI findings — is available as JSON. Useful for pre-DMARC deployment checks, email-migration verification, vendor onboarding gates, and continuous SPF monitoring. Rate-limited per IP on the free tier.

JavaScript (fetch)
const res = await fetch(
  'https://api.domainscan.in/api/v1/domain/spf?domain=microsoft.com&tests=true&expand=true'
);
const { data: spf } = await res.json();

// Raw + parsed record
console.log(spf.spf);                          // v=spf1 include:... -all
console.log(spf.parsed.qualifier);             // '-all'  (strict policy)
console.log(spf.expanded.lookupCount);         // 7  (of 10 max, RFC 7208)
console.log(spf.expanded.includes.length);     // 5  (top-level includes)

// Compliance tests (RFC 7208 checks)
const failures = spf.tests.filter(t => !t.passed);
if (failures.length) console.warn('SPF issues:', failures.map(f => f.test));

// AI review — severity-ranked issues
const critical = (spf.AiAnalysis?.issues || []).filter(i => i.severity === 'critical');
critical.forEach(i => console.error(i.title, '—', i.recommendation));

// -----------------------------------------------------------------
// Derived analytics — computed client-side from `expanded` (no extra
// requests). Ship these to your dashboard / alerting layer.
// -----------------------------------------------------------------
import * as spfAnalytics from './spf-analytics.js';

const policy    = spfAnalytics.classifyPolicy(
  spfAnalytics.extractQualifier(spf.spf, spf.parsed.mechanisms),
);
const lookups   = spfAnalytics.countLookups(spf.expanded);          // 7
const voids     = spfAnalytics.countVoidLookups(spf.expanded);      // 0
const health    = spfAnalytics.computeHealth({
  tests: spf.tests, lookupCount: lookups, voidCount: voids, policy,
});
const inventory = spfAnalytics.summarizeInventory(spf.expanded);
const providers = spfAnalytics.detectProviders(spf.expanded);

console.log(policy.strength);      // 'Strong'
console.log(health.score);         // e.g. 88
console.log(inventory);            // { ipv4Count: 78, ipv6Count: 12, includeCount: 5, ... }
console.log(providers.map(p => p.name));  // ['Microsoft 365']

// Test-an-IP simulator (fully client-side, walks the resolved chain)
const verdict = spfAnalytics.simulateSender('40.92.10.20', spf.expanded);
console.log(verdict);
// { result: 'pass', matchedBy: 'ip4:40.92.10.0/24', matchedIn: 'spf.protection.outlook.com',
//   chain: ['microsoft.com', '_spf-a.microsoft.com', 'spf.protection.outlook.com'] }
Response schema (abridged)
// Wire-level API response (backend). Compliance tests are what the
// backend ships. Derived analytics (health, policy, inventory,
// providers, sender simulation) are computed client-side via
// `spf-analytics.js` from `expanded`.
{
  "spf":    "v=spf1 include:_spf-a.microsoft.com ... -all",
  "parsed": {
    "version":    "v=spf1",
    "qualifier":  "-all | ~all | ?all | +all",
    "mechanisms": { "ip4": [], "ip6": [], "include": ["..."], "a": [], "mx": [] },
    "modifiers":  [],
    "directives": ["include:...", "-all"]
  },

  "tests": [
    { "test": "Multiple SPF Records",     "result": "...", "passed": true },
    { "test": "Too Many DNS Lookups",     "result": "DNS lookups within limit (7/10).", "passed": true },
    { "test": "SPF Policy Strength",      "result": "...", "passed": true },
    { "test": "No 'PTR' Mechanism",       "result": "...", "passed": true },
    { "test": "SPF Record Length",        "result": "...", "passed": true },
    { "test": "Number of Void Lookups",   "result": "...", "passed": true },
    { "test": "SPF record validity",      "result": "...", "passed": true },
    { "test": "No Deprecated Mechanisms", "result": "...", "passed": true }
  ],

  "expanded": {
    "domain":      "string",
    "spfRecord":   "string",
    "lookupCount": "number (total DNS lookups across the chain)",
    "ip4List":     ["string"],
    "ip6List":     ["string"],
    "mechanisms":  [{ "type": "...", "qualifier": "+|-|~|?", "value": "..." }],
    "includes":    [
      {
        "domain":   "string",
        "expanded": { /* recursive: same shape */ }
      }
    ]
  },

  "AiAnalysisMeta": { "id": "...", "avgMs": 4500 }, // when cache-miss
  "AiAnalysis": {                                   // when cache-hit
    "issues": [
      {
        "severity":       "info | warning | critical",
        "title":          "string",
        "description":    "string",
        "recommendation": "string"
      }
    ],
    "quick_recommendations": ["string"]
  }
}

// -------------------------------------------------------------------
// Derived analytics (computed client-side, not shipped by the API)
// -------------------------------------------------------------------
{
  "policy": {
    "code":     "strict | softfail | neutral | pass_all | missing",
    "label":    "Strict (-all)",
    "strength": "Strong | Moderate | Weak | Dangerous | None",
    "headline": "Hard fail — unauthorized senders rejected",
    "explain":  "Receiving servers should reject...",
    "tone":     "emerald | amber | red"
  },
  "lookupCount": 7,
  "voidCount":   0,
  "health":      { "score": 88, "band": "Good", "tone": "emerald" },
  "inventory":   {
    "ipv4Count":    78,
    "ipv6Count":    12,
    "includeCount": 5,
    "includes":     ["_spf-a.microsoft.com", "..."],
    "maxDepth":     3
  },
  "providers":   [
    { "name": "Microsoft 365", "tone": "indigo", "matchedOn": "spf.protection.outlook.com" }
  ]
}
09 · USE CASES

How teams use SPF Checker

Six patterns we see most often:

Pre-DMARC deployment (Setup)

Before publishing a DMARC policy with `p=quarantine` or `p=reject`, audit your SPF. A misconfigured SPF + strict DMARC = legitimate mail rejected. Fix the SPF first, then ratchet up DMARC.

Email-migration verification (Migration)

Moving from G Suite to Office 365 (or vice versa, or onto a new ESP). Add the new include, verify it doesn't push you over 10 lookups, then remove the old one. Re-check before flipping production traffic.

Vendor onboarding gate (Procurement)

A new SaaS asks you to add their `include:` to your SPF. Run the check after adding to verify the lookup count stays under 10. Some vendors publish wildly bloated SPF records — better to catch it before deploying.

Deliverability incident response (Incident)

Mail to a key customer is bouncing or landing in spam. SPF check is the first thing to run — PermError due to lookup overrun is one of the most common silent causes of deliverability degradation.

M&A and vendor due diligence (Diligence)

Acquiring a company or evaluating a vendor's email infrastructure. SPF strength (`-all` vs `~all` vs `?all`) and chain quality are leading indicators of how seriously they take email security.

Continuous monitoring (Operations)

Cron the API against your domains. Alert when lookup count creeps toward 10, when a test starts failing, or when an AI critical issue appears. Catches the silent drift that breaks SPF over months.

IP-level SPF debugging (Simulator)

A specific sender IP is bouncing / softfailing / being marked as spam. Paste it into the Test-an-IP tab and get the exact mechanism verdict + matched include + walk trace, without touching production DNS or spinning up a test MTA.

Shadow-vendor audit (Cleanup)

The Sender Inventory + Provider Fingerprint pills often surface includes for tools nobody actively uses anymore. Removing them shrinks the lookup budget and reduces the spoofable surface — usually a five-minute win.

10 · QUESTIONS

Common questions

  • What's the difference between SPF, DKIM, and DMARC? SPF lists which IPs can send mail for your domain (IP-based, lives in a TXT record). DKIM cryptographically signs the outgoing message (content-based, signature travels with the email). DMARC tells receivers what to do when SPF or DKIM fails (policy-based, lives at `_dmarc.<domain>`). They're complementary, not interchangeable — proper email authentication uses all three.
  • What does "too many DNS lookups" mean and how do I fix it? RFC 7208 limits SPF checks to 10 DNS lookups. Every `include:`, `a`, `mx`, `exists`, and `redirect=` counts; `ip4:` and `ip6:` do not. Exceed 10 and the entire SPF check returns PermError, which most receivers treat as 'no SPF'. Fix it by: removing unused includes, consolidating via a managed SPF service (EasyDMARC, dmarcian, Valimail), or maintaining a flattened SPF record where `include:` chains are replaced with explicit IP lists.
  • What's the difference between -all and ~all? `-all` is strict — receivers should reject mail that fails SPF. `~all` is soft-fail — receivers should accept the mail but mark it suspicious (typically junk it). `-all` is the production goal; `~all` is appropriate during initial deployment or while transitioning between providers. `?all` (neutral) is essentially the same as having no SPF record. `+all` allows everyone to spoof your domain — never use it.
  • Can I have multiple SPF records? No — RFC 7208 explicitly forbids it. A domain must have exactly one SPF record. Multiple SPF TXT records cause a PermError on the entire check, just like exceeding the lookup limit. If you find yourself wanting two records (e.g., one for marketing and one for transactional mail), use a single record with multiple `include:` directives instead.
  • What is SPF flattening and should I use it? SPF flattening replaces `include:` chains with explicit `ip4:` / `ip6:` lists. The result has zero recursive DNS lookups, which makes the 10-limit irrelevant. Tradeoffs: you must monitor for upstream IP changes (vendor adds new sending infrastructure → your flattened record gets stale → mail starts failing). Use it when you have no other choice (more than 10 lookups required); otherwise, prefer fewer includes. Managed services (EasyDMARC, dmarcian, Valimail) handle the monitoring automatically.
  • Do I still need SPF if I have DKIM and DMARC? Technically you can pass DMARC with only DKIM aligned. Practically, SPF is the cheapest authentication signal to publish (just a TXT record), receivers still weigh it independently in their spam-scoring algorithms, and forwarded mail (where DKIM helps and SPF breaks) is the minority case. Publish all three. The marginal effort is small; the benefit is meaningful.
  • Why does my legitimate mail still go to spam despite valid SPF? SPF passing is necessary, not sufficient. Receivers also weigh sender reputation (IP and domain), DKIM, DMARC alignment, content signals (links, language patterns), engagement (do recipients open and reply?), and many other factors. A perfect SPF record won't save mail from a low-reputation sender, and forwarding breaks SPF entirely (the forwarder's IP isn't in your record). If SPF is valid but mail still spams, look at DKIM coverage, DMARC alignment, and sender reputation tools (Google Postmaster, Microsoft SNDS).
  • What does the ptr mechanism do and why is it deprecated? `ptr` checks the sender's reverse DNS (PTR record) against the SPF domain. Two problems: it's slow (every check requires an extra DNS round-trip), and PTR records are owned by the IP block holder, not the sender — so the trust model is fundamentally weak. RFC 7208 formally deprecates `ptr`; the existence of `ptr` in a published SPF record is itself a red flag indicating an old or low-quality configuration.
  • What is a void lookup and why does the meter go to 2? A void lookup is an SPF mechanism (typically `ptr` or `exists:`) that resolves to nothing — no A record, or NXDOMAIN. RFC 7208 permits at most 2 per SPF evaluation before returning permerror. Because permerror is silent, void-lookup overflow is often invisible until deliverability drops. Our meter tops out at 2 so you can see the cliff coming.
  • How does the Test-an-IP simulator work? Does it make new DNS queries? Zero. The Summary lookup already resolves the entire chain (every include expanded to its ip4 / ip6 leaves). The simulator walks that already-resolved tree client-side, matching your IP against each mechanism's CIDR — full IPv4 and IPv6 support with /0–/32 and /0–/128 masks. Results include the exact matched mechanism, the include it lived in, and the walk trace. No API cost, no rate limit.
  • The Security tab shows findings before the AI badge appears. Which do I trust? Both. The instant findings are rule-based — derived directly from the parsed record + RFC 7208 tests + lookup / void counts + policy classification. They're deterministic and always available. The AI enrichment layers on top with a small `AI` pill, adding context / edge cases the rule engine can't catch (e.g. semantic issues, misspelled includes, unusual mechanism ordering). If the two ever conflict, the rule-based finding is authoritative for what the record says; the AI finding is authoritative for what it means in context.
  • Which providers does the fingerprint detect? Google Workspace, Microsoft 365, SendGrid, Mailgun, Mailchimp, Amazon SES, Fastmail, Zoho, Salesforce, Mandrill, Postmark, Mimecast, Intermedia, Campaign Monitor, Klaviyo, HubSpot, Freshworks, Proofpoint, Constant Contact and iCloud. Includes that don't match any known provider still appear in the raw record and Sender Inventory count — they just don't get a coloured pill. Missing a provider you use? Open a feedback ticket and we'll add the fingerprint.
11 · RELATED

Related email authentication tools