references/email-records.md — Email Domain Setup Checker
From version 0.1.1 of Email Domain Setup Checker, shown publicly by its creator. 5.4 KiB · SHA-256 382d248cb84db77ebadc2af1cb51a74484fd92f3d412033c3611b93e55490892.
# Email record reference This reference explains what the checker reads and how to interpret its findings. It is an inventory of public records, not a delivery test or a substitute for provider guidance. ## Record names and checks | Check | DNS name | Interpretation | | --- | --- | --- | | MX | checked domain | No MX is an error for domains expected to receive mail. | | SPF | checked domain TXT | Exactly one `v=spf1` policy is expected. Multiple policies violate the single-policy requirement. SPF output is a static lookup count following RFC 7208 processing order: include, a, mx, ptr, exists and redirect count recursively, terms after all are ignored, and redirect is ignored when all is present. The walker does not evaluate macros or match a sender IP, so it does not provide a definitive SPF pass/fail evaluation. Void lookups are not measured. Macro include/redirect targets are not followed: they produce a warning and mark the static count partial and the report incomplete. Duplicate redirect modifiers produce a warning citing RFC 7208 section 6; neither redirect is followed or counted, and the report is incomplete. An eleventh counted term stops further SPF lookups and produces a warning: "static lookup count is N, above the 10-lookup limit; evaluation can stop earlier for a matching sender". This warning alone does not cause exit 3. Loops are reported. `+all`, `?all`, and `ptr` merit attention. | | DMARC | `_dmarc.<domain>` TXT | `p=none` monitors; `quarantine` and `reject` request enforcement. The report describes `pct`, aggregate `rua`, forensic `ruf`, `adkim` and `aspf` alignment, and `sp` subdomain policy. Missing reporting addresses or relaxed alignment are review signals, not proof of failure. | | DKIM | `<selector>._domainkey.<domain>` TXT | User-supplied selectors are authoritative inputs. The tool also probes `default`, `selector1`, `selector2`, `google`, `k1`, `s1`, `s2`. Missing common selectors are informational because selector names are arbitrary. A public key alone does not prove outbound messages are signed. | | TLS-RPT | `_smtp._tls.<domain>` TXT | A `v=TLSRPTv1` policy can specify report destinations. Absence is a visibility finding. | | MTA-STS | `_mta-sts.<domain>` TXT | A `v=STSv1` record signals an MTA-STS policy. With `--mta-sts`, the checker also reads the HTTPS policy file from the checked domain's `mta-sts` subdomain. A DNS signal alone does not prove the policy file works. | | BIMI | `default._bimi.<domain>` TXT | Informational presence check. A published record does not imply that mailbox providers will display a logo. | SPF has an RFC limit of 10 terms that cause DNS lookups during evaluation. This checker inventories reachable terms in processing order, without sender-IP or macro evaluation. Recursive includes and active redirects add to the same static total; `a`, `mx`, `ptr`, and `exists` also count even when this checker does not query their target records. `all` ends only its own record, so `all` inside an included record does not stop the parent. `exp=` does not add to the static count. Mechanism and modifier names are case-insensitive. A cycle is reported rather than followed forever. The entire check also stops at 60 DNS queries and marks the report incomplete. Results can depend on the records visible to the selected resolver at check time. ## DNS-over-HTTPS and host guard The selected resolver serves JSON answers at `https://dns.google/resolve` or `https://cloudflare-dns.com/dns-query`; only Cloudflare requests include `Accept: application/dns-json`. The query contains a DNS name and record type. Recursive SPF checks look up include and redirect targets named in DNS records, which can be unrelated third-party domains; those names are sent to the selected resolver. Requests and redirects must use HTTPS and stay on the selected resolver host. With `--mta-sts`, the only additional permitted destination is `https://mta-sts.<validated-domain>/.well-known/mta-sts.txt`, including redirects. The checker does not send mail, update DNS, or read local account files. Python urllib honors `HTTPS_PROXY`, `https_proxy`, `NO_PROXY`, `no_proxy`, and macOS or Windows system proxy settings. TLS still terminates at the declared destination hosts. ## Partial results A failed lookup, skipped SPF macro target, duplicate redirect modifiers or the 60-query DNS ceiling makes the report `incomplete`, with skipped checks named. Exit status is 2 unless `--allow-partial` is supplied. The report can still contain valid findings from completed checks, but it cannot support an overall pass claim. An error finding in an otherwise complete report gives exit status 3; a complete report without errors gives 0. Invalid command-line input or fixture setup also exits 2. With `--allow-partial`, an incomplete report exits 3 if it contains error findings and 0 otherwise. ## Synthetic fixtures Tests set both `EMAIL_DNS_FAKE_RESPONSES` to an existing synthetic JSON fixture path and `EMAIL_DNS_FAKE_TRANSPORT_TEST_ACK=1`. The fixture is a JSON object keyed by each exact request URL. A value is a synthetic DNS-over-HTTPS JSON response body or an object with an `error` string for a simulated failure. The fake transport prints a stderr warning and never uses a real host. Keep fixture domains and content synthetic. Version 0.1.1. MIT license; see [LICENSE.txt](../LICENSE.txt). Google Public DNS is a Google service. Cloudflare is a trademark of Cloudflare. This product is independent and has no affiliation with either provider. By Zero Width Lab (zerowidthlab.com)
License: MIT (read it).
MIT
MIT LicenseCopyright (c) 2026 Zero Width Lab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.