24-Apr-2026 — SPF/DMARC management, plain-text alternatives, List-Unsubscribe header
GitHub #186 — commit 77db1d9
Three deliverability fixes for transactional email, headlined by a new Email Authentication panel on the Brevo Senders page that lets admins fix SPF and DMARC with one click.
Email Authentication panel
The new panel sits above the existing MX records panel and shows colour-coded badges for SPF and DMARC, the current record contents, and a Fix Auth Records button that merges missing includes or creates the records. Existing policies are never widened; multi-record SPF states disable the button with a tooltip pointing at manual consolidation.
SPF missing the Brevo include

ashfordramblers.org.uk — SPF exists for the Cloudflare mail path but misses spf.brevo.com. DMARC is already in place and is left untouched.
Stricter existing DMARC

canterburyramblers.org.uk — same SPF gap, but this domain runs p=reject. The fix will merge in the Brevo include while preserving the stricter policy exactly.
SPF fixed — strict DMARC preserved

canterburyramblers.org.uk after Fix Auth Records — SPF now contains both _spf.mx.cloudflare.net and spf.brevo.com; p=reject is retained.
Fresh domain with nothing in place

berkshire-weekend-walkers.ngx-ramblers.org.uk — nothing at all. The panel shows exactly what will be created before the button is pressed.
After one-click fix on a fresh domain

Fresh v=spf1 include:_spf.mx.cloudflare.net include:spf.brevo.com ~all created, plus a monitor-only v=DMARC1; p=none so the admin can raise enforcement later without surprise.
Other fixes shipping with this change
- Plain-text alternative — every transactional email now gets a
textContentderived from HTML when the caller supplied none. HTML-only mail is a documented spam-filter penalty signal. - List-Unsubscribe header —
<mailto:replyTo?subject=unsubscribe>is added to transactional sends unless the caller sets its own. Campaigns are unchanged; Brevo manages their unsubscribe headers natively. - Migration iterates every Brevo-registered domain, not just the env's configured
baseDomain. Per-domain failures are logged and skipped — one bad zone can't block the rest. - www-vs-apex false warning fixed — a new shared
apexHost()helper stripswww.on both sides of the site/Brevo-domain comparison. - Cleaner 500 responses — a shared
errorResponse(error)returns{code, message}so clients see the real cause instead of a serialised empty Error. - Idempotent destination-address creation — POSTing an existing address returns the match instead of tripping Cloudflare's "verification sent too recently" cooldown.