SPF, DKIM and DMARC, explained
Anyone can write your address in the From line of an email. Three DNS records let a receiving server judge whether a message may claim your domain. SPF lists the servers that may send mail for a domain. DKIM adds a cryptographic signature to each message, checked with a public key that sits in DNS. DMARC says what receivers should do when neither of them passes in alignment with the visible From domain, and where to send reports. This page reads those records, and the related MX, MTA-STS, TLS-RPT, BIMI, DANE, CAA and DNSSEC data, from live DNS, then says what each one contains and which rule it breaks, if any. When something has to change, the Build panel writes the corrected records, a zone file and a rollout plan.
SPF
The whole include tree, the 10 lookup limit counted in evaluation order, void lookups, loops, ptr, +all and duplicate records.
DKIM
36 common selectors plus yours, RSA key size, Ed25519 keys, CNAME hand-offs, revoked and testing keys.
DMARC
Policy, subdomain policy, alignment, report addresses and whether outside addresses have agreed to receive your reports.
Transport
MX and null MX, MTA-STS, TLS-RPT, BIMI, DANE, CAA and the DNSSEC flag.
Build
SPF, DMARC, DKIM, MTA-STS, TLS-RPT and BIMI records, a zone file, SPF flattening, DKIM keys and a rollout plan to p=reject.
SPF: the sender list and the 10-lookup limit
An SPF record is a TXT record that starts with v=spf1. It lists IP ranges (ip4:, ip6:) and the records of other domains (include:), and normally ends with ~all or -all. While it evaluates a message a receiver may make at most 10 DNS lookups for the terms include, a, mx, ptr, exists and redirect, counting the ones inside included records. ip4, ip6 and all cost nothing. Go over the limit and the result is a permanent error, so SPF cannot pass. A second limit allows at most two lookups that return nothing (void lookups), and a name with more than ten MX records is also an error (RFC 7208 section 4.6.4). The checker builds the include tree, numbers each lookup in the order a receiver would make them, and marks the term that crosses the line.
Typical fixes: drop services you no longer send through, send bulk mail from a subdomain with its own SPF record, or flatten the record by replacing includes with the IP ranges they stand for. Flattening removes lookups but the list goes out of date when a provider changes its addresses, so someone has to refresh it. Keep exactly one SPF record per name, because two records give a permanent error (RFC 7208 section 4.5). RFC 7208 section 3.4 asks that the DNS answer fit within 512 octets and mentions about 450 characters for the record; the checker warns above 450.
DKIM: signatures and selectors
The sending system signs each message with a private key. The matching public key is a TXT record at selector._domainkey.yourdomain. The selector is a name chosen by whoever set the signing up, such as selector1 and selector2 for Microsoft 365 or google for Google Workspace. Many services publish a CNAME that points at a key they rotate themselves. DNS cannot list selectors, so this page tries 36 common names and any you type. Your provider's setup page shows the right one, and a message you sent shows it as s= in the DKIM-Signature header. Not finding a key on the common names does not mean DKIM is off.
RFC 8301 section 3.2 requires signers to use RSA keys of at least 1024 bits and says they should use at least 2048; verifiers must handle keys from 1024 to 4096 bits. Ed25519 keys (RFC 8463) are published as the base64 of the raw 32-byte public key. An empty p= means the key was revoked, and t=y marks a key as still in testing. A 2048-bit key is longer than one 255-byte DNS string, so it is stored as several quoted strings that verifiers join (RFC 6376 section 3.6.2.2).
DMARC: policy, alignment and reports
DMARC passes when SPF or DKIM passes and the domain that passed matches the From domain, which is called alignment. Relaxed alignment (the default) accepts a subdomain of the same organisation, strict alignment needs an exact match. The policy tells receivers what to do with mail that fails:
| Policy | What the domain asks for | Typical use |
p=none | No action on delivery; reports are collected | The first weeks, while you find every sender |
p=quarantine | Treat failing mail as suspicious | Once reports show that your own mail passes |
p=reject | Reject failing mail | The end state |
The rua address receives aggregate reports. If it is on another domain, that domain must publish a TXT record at yourdomain._report._dmarc.otherdomain to accept them (RFC 7489 section 7.1, RFC 9990 section 4); the checker looks for it. sp= sets the policy for subdomains and, in the newer RFC, np= for subdomains that do not exist.
Two rules for finding the record. RFC 7489 falls back from a subdomain to the organisational domain found with the Public Suffix List. RFC 9989 (May 2026, the update that obsoletes RFC 7489) replaces that with a DNS tree walk of at most eight queries. When both lead to different records for the domain you check, the page shows both and marks the difference with a note. It also lists tags that RFC 9989 treats as historic (pct, rf, ri) or adds (np, psd, t).
Build the records and roll them out
The Build panel writes the records for you and checks them while you type. Pick a starting point (Microsoft 365, Google Workspace, your own mail server or blank), tick the services that send mail as your domain, add IP ranges, then choose the policy and a report address. Records shows the exact host and value of each TXT record, with a note when it differs from what is live. A value longer than 255 characters is split into several quoted strings in the zone file, which is how DNS stores it. After a check, Load checked domain and the suggestions under Fix it in the builder start from the published records, so you change what is there instead of starting over. Imported records and a setup link do the same from text.
A domain that sends no mail needs three records: a null MX (0 ., RFC 7505), v=spf1 -all and DMARC at p=reject. The Sends no mail switch builds them, plus a DKIM record with an empty key that revokes every selector. MTA-STS and TLS-RPT are optional: the builder writes the TXT records and the policy file, which you must host yourself at https://mta-sts.yourdomain/.well-known/mta-sts.txt. BIMI needs DMARC at quarantine or reject, and Gmail and Apple Mail also want a certificate.
SPF over the limit. The builder counts the lookups in your own record and, with Count the nested ones too, the ones inside every include. Flatten swaps includes for the IP ranges they stand for, so the record needs no lookups; keep the includes of providers that change their ranges often, and run it again every few weeks. DKIM keys. Microsoft 365 and Google Workspace create their own keys and show a CNAME or a value to copy. If you run your own mail server, Generate a key pair makes an RSA or an Ed25519 key with the WebCrypto of your browser. The key is not sent or stored, so copy the private key before you close the window.
The rollout plan. Going straight to p=reject can block your own invoices or newsletters, so Rollout moves in five steps: monitor with p=none, read the reports and fix every legitimate sender, quarantine a quarter of the failing mail, then all of it, and finally reject. Each step has the record to publish, a checklist and a date, and the plan downloads as a calendar file. The percentage steps use the pct tag, which RFC 9989 marks as historic; receivers that follow RFC 7489 still apply it.
MX, MTA-STS, TLS-RPT, BIMI, DANE and CAA
MX records say where mail for the domain goes; a single 0 . is a null MX, the way to say a domain accepts no mail (RFC 7505), and an MX target should be a real host, not an alias (RFC 2181 section 10.3). MTA-STS (RFC 8461) asks senders to require TLS when they deliver to you; it needs a TXT record and a policy file on an mta-sts host, and this page reads only the DNS part. TLS-RPT (RFC 8460) says where senders report TLS failures. BIMI is an Internet-Draft for brand logos; mailbox providers decide whether to show one, so the page checks the record's syntax and nothing else. DANE for SMTP (RFC 7672) publishes TLS certificate data in TLSA records and only counts when the answers are DNSSEC-validated. CAA (RFC 8659) limits which certificate authorities may issue for a name. The DNSSEC line shows whether a DS record exists and whether the resolver reported the answer as validated (the AD flag), which is only as trustworthy as your connection to that resolver (RFC 4035).
How the lookups work, and what can block them
A web page cannot send ordinary DNS queries, so it uses DNS-over-HTTPS: each question is an HTTPS request from your browser to a public resolver. Two request formats are used: a JSON format that the page asks Cloudflare and Google for, and the binary format of RFC 8484, which the page encodes and decodes itself and can send to any of the five resolvers. Auto tries Cloudflare JSON, Google JSON, the same two by IP address (1.1.1.1 and 8.8.8.8) and then the binary format on Cloudflare, Google, Quad9, AdGuard and NextDNS, and moves on to the next only when one fails. Each request times out after 5 seconds, at most 6 run at once, answers are kept for up to 60 seconds (shorter if the record's TTL is shorter), a resolver that fails twice in a row without ever answering is skipped for a minute, and a whole check stops after 60 seconds. A simple domain takes about 50 small queries; a large SPF tree or several mail servers add more. Every section shows which resolver answered, and the Query log in the Lookup view lists every attempt. The IP-address endpoints are there because some networks block the host names cloudflare-dns.com and dns.google but let the addresses through; the request format and the resolver behind it are the same.
Some networks block these requests. A company or school firewall, a DNS filter, a browser extension or a VPN can stop them, and a resolver can also refuse requests from web pages. A browser reports all of these as the same network error, so the page cannot tell them apart; Test resolvers shows which resolvers answer from where you are. If none does, try another network, then paste records from dig or nslookup into the Offline view. Different resolvers can also disagree for a while after a DNS change, which the Compare resolvers tool shows.
Privacy and what the page stores
Your browser sends the domain name straight to the DNS-over-HTTPS resolver you select (Cloudflare, Google, Quad9, AdGuard or NextDNS). Nothing is sent to jasperbernaers.com; the page has no server. The site's analytics counts page views only. With Auto, a lookup goes to the next resolver only when the one before it failed. Cloudflare and Google are also tried by IP address (1.1.1.1 and 8.8.8.8); that is the same company's service, so the same privacy policy applies. If you enter a custom resolver URL, every domain you check is sent to that server, so use only one you trust. For what the resolvers keep, see their privacy policies: Cloudflare, Google, Quad9, AdGuard, NextDNS.
The page stores these things in your browser's local storage, all optional: jb-spfchk-resolver (the resolver you chose, and a custom URL if you typed one, which is only put back into the form and never switched on by itself), jb-theme (dark or light, set by the site's theme switch), and for the Build panel jb-emailauth-v2 (the form: the domain you type there, the senders, the policy, the report addresses and the public DKIM key; a private key that you paste by mistake is never saved) and jb-dmarc-ui (how the host is written, the TTL and the rollout tasks you ticked). Checking a domain stores no domain names. The share link keeps the domain after a #, and the setup link keeps the Build settings after a #, a part of the address that browsers do not send to a server.
Sources and limits
The rules come from RFC 7208 (SPF), RFC 6376, RFC 8301 and RFC 8463 (DKIM), RFC 7489, RFC 9989 and RFC 9990 (DMARC), RFC 8461 (MTA-STS), RFC 8460 (TLS-RPT), RFC 7505 (null MX), RFC 7672 (DANE for SMTP), RFC 8659 (CAA), RFC 4035 (DNSSEC) and RFC 8484 (DNS-over-HTTPS). Sender and provider names are marked Documented when the provider's own help pages show the record, and Pattern guess or Convention when they only match a name. The organisational domain comes from the Public Suffix List (ICANN section, list version 2026-10-31), used under the Mozilla Public License 2.0. The page reads DNS only. It cannot see whether a particular message passed, which is a question for that message's headers, and a clean result does not promise delivery.
More free tools for mail and networks
To read what a receiver concluded about one real message, use the message header analyzer. For sending ranges, the subnet calculator does the CIDR arithmetic.