Provides a minimal table UI to manage the list of reporting domains
authorised via <reportingdomain>._report._dmarc TXT records, replacing
the Orphan editor fallback.
Some checker dependencies (e.g. checker-caa) embed assets produced by
go:generate directives. Run go generate in every non-main module after
go mod download so embedded files are materialised before build.
The BIMI draft lets a domain explicitly opt out of BIMI by publishing
a record with v=BIMI1 and an empty l= tag. Surface that in the editor
and treat it as a first-class case in compliance.
Validators run synchronously and surface:
- Owner-name shape: <selector>._bimi (rejects empty selectors and
non-label characters).
- Version: only "BIMI1" is accepted by the current draft.
- Logo URL: l= is mandatory, must be HTTPS, warns when the path does
not end in .svg.
- VMC URL: optional but flagged as info when missing (Gmail and Yahoo
need it). Must be HTTPS when present; info if it does not look like
a .pem file.
- Evidence URL: must be HTTPS when present.
- Cross-record DMARC check: warns when no DMARC is published or when
every DMARC at the apex sits at p=none, since BIMI is only honoured
with an enforcing DMARC policy.
Adds support for Brand Indicators for Message Identification (BIMI),
the emerging standard that lets receiving mail clients display verified
brand logos next to authenticated messages.
Surfaces the RFC 7489 sec. 7.1 trap: when a DMARC record at example.com
publishes rua/ruf addresses on a third-party domain, that domain must
publish "v=DMARC1" at example.com._report._dmarc.<external> to authorize
report delivery. Without it, reports are silently dropped, which is by
far the most common cause of "DMARC is published but no report ever
arrives".
Adds a backend endpoint that resolves the RFC 7489 sec. 7.1 cross-domain
reporting authorization record, paired with the (incoming) DMARC async
validator on the front-end.
When a DMARC record at example.com publishes rua=mailto:dmarc@third.tld,
third-party receivers MUST refuse to deliver reports unless
example.com._report._dmarc.third.tld publishes a v=DMARC1 TXT. This is
the silent failure mode behind most "we configured DMARC but never see
any report" tickets.
Adds zone-aware checks to the MTA-STS async validator. Once the policy
file is fetched and parsed, compare its mx patterns to the apex MX
records of the current zone (RFC 8461 sec. 4.1):
- mta_sts.zone-no-mx (warning): the policy lists mx entries but the
zone has no MX records, so receivers will refuse delivery.
- mta_sts.zone-mx-not-covered (error in enforce, warning in testing):
one of the apex MX hosts is not matched by any policy pattern.
Senders enforcing the policy will reject mail to that host.
- mta_sts.policy-mx-unused (info): a policy pattern matches no MX in
the zone, hinting at a stale entry.
Validates a MX record set (svcs.MXs) at edit time:
- Null MX (RFC 7505): a "." target must be the only MX in the set, with
preference 0. Both deviations are surfaced.
- Targets: invalid hostnames, out-of-range preferences (uint16) and
duplicate targets (case-insensitive on the FQDN).
- Cross-zone: flags MX targets that are CNAME owners in the same zone
(RFC 5321 sec. 5.1) and warns when an in-zone target lacks any
A/AAAA service. External targets are left to runtime checkers.
Extends the compliance context with findAllServices(type?) so a
validator can iterate every service in the zone, not just a single
subdomain. The DMARC validator now uses it to flag configurations
where alignment is structurally impossible:
- p=quarantine|reject and the zone has neither a DKIM nor an SPF
record -> error: every legitimate message will fail DMARC.
- p=none in the same situation -> warning: DMARC has nothing to
align against, monitoring data will be empty.
- adkim=s (strict DKIM alignment) with no DKIM record published
anywhere in the zone -> warning: only SPF alignment can succeed.
Wires the new POST /api/resolver/mta-sts-policy endpoint into the
MTA-STS validator. The async pass runs after the local TXT checks,
debounced and cancellable through EditorCompliance, and surfaces:
- Transport-level failures: dns-error, tls-error, fetch-error,
too-large.
- HTTP-level failures: not-found (404), http-error (other non-2xx),
redirect (server tried to redirect, RFC 8461 sec. 3.3 forbids it).
- Policy file content: missing/invalid version, missing/invalid mode,
mode=none (warning, effectively disabled), mode=testing (info),
missing mx in enforce/testing modes, missing/out-of-range max_age
(0..31557600), short max_age (< 1 day, warning).
Adds a backend endpoint that fetches and parses an MTA-STS policy
file at https://mta-sts.<domain>/.well-known/mta-sts.txt per RFC 8461
sec. 3.3, paired with the (existing) MTA-STS TXT validator on the front-end.
Adds checks for svcs.TLS_RPT against RFC 8460 sec. 3.
The validator surfaces:
- Wrong owner name (must be _smtp._tls.<domain>).
- Missing or non-TLSRPTv1 v= tag.
- Missing rua= report destination.
- Empty entries inside rua=.
- rua URIs that are neither mailto: nor http(s):.
- Malformed mailto URIs (missing @ or domain).
Adds checks for svcs.MTA_STS against RFC 8461 sec. 3.1.
The validator surfaces:
- Wrong owner name (must be _mta-sts.<domain>).
- Missing or non-STSv1 v= tag.
- Missing id= tag.
- id= containing characters outside [A-Za-z0-9] or longer than 32 chars.
Adds compliance checks for svcs.DMARC against RFC 7489.
The validator parses the published TXT and surfaces:
- Wrong owner name (record must live at _dmarc.<domain>).
- Missing or non-DMARC1 v= tag.
- Missing, unknown, or "monitoring-only" p= policy.
- Invalid sp= subdomain policy.
- Invalid adkim/aspf alignment values.
- pct= out of [0..100] (error) and pct < 100 (info, partial deployment).
- Non-positive or non-numeric ri=.
- Unknown fo= entries (0 / 1 / d / s) and unknown rf= formats (afrf).
- Empty or malformed rua/ruf URIs (mailto and http(s) accepted; mailto
size suffix !N preserved).
Wires the new POST /api/resolver/spf-flatten endpoint into the SPF
validator. The async path runs after the local checks, debounced and
cancellable through EditorCompliance, and surfaces:
- spf.recursive-many-lookups / spf.recursive-too-many-lookups based on
the recursive lookupCount returned by the backend
- spf.too-many-void-lookups when more than 2 NXDOMAIN/NoData responses
occur during the walk (RFC 7208 §4.6.4)
- per-include diagnostics: spf.include-loop, spf.include-no-spf,
spf.include-resolver-error, spf.include-error — pointing at the exact
domain and mechanism that failed