v0.89.0: app-email plaintext-only listener (:2526) + split-From mapping

Gap 1: third shim listener :2526, plaintext, does NOT advertise STARTTLS (TLSConfig
nil) — for opportunistic-STARTTLS clients with no cert-skip (cal.com, nextcloud).
Gap 2: SMTPMapping tls_mode (picks port 2525/2526/2465) + from_domain_var (split
local-part + domain for nextcloud's MAIL_FROM_ADDRESS/MAIL_DOMAIN). Default keeps
existing apps on 2525. Hub untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-29 13:13:40 +02:00
parent 6692a2f631
commit a405505e81
8 changed files with 252 additions and 47 deletions
+20
View File
@@ -1,5 +1,25 @@
## Changelog
### v0.89.0 — App-email: plaintext-only listener (:2526) + split-From mapping (2026-06-29)
- **What:** closes the two relay gaps from `FINDING-app-email-rollout-2026-06-29.md` so the
opportunistic-STARTTLS clients (cal.com, nextcloud) can use the relay.
- **Gap 1 — `internal/mailrelay/server.go`:** a **third listener `:2526`** that is plaintext and does **NOT
advertise STARTTLS** (`TLSConfig` left nil ⇒ go-smtp omits the STARTTLS capability from EHLO). Clients that
opportunistically upgrade to STARTTLS and then validate the cert with no skip-verify knob (Nodemailer/Symfony
Mailer) never attempt TLS against it. Accepted posture: plaintext on the single-tenant app Docker bridge only
(never host/internet). `:2525` (STARTTLS) and `:2465` (implicit-TLS) unchanged. New config
`mail_relay.plain_no_tls_listen` (default `:2526`).
- **Gap 2 — `internal/stacks/metadata.go` + `mailenv.go`:** `SMTPMapping` gains **`tls_mode`** (`""`/`starttls`
→2525 default; `plaintext`→2526; `implicit-tls`→2465 — `smtpEnv` now picks the port from it instead of the
hardcoded 2525) and **`from_domain_var`** (split-From: when set, inject `FromVar=<local>` +
`FromDomainVar=<domain>` separately, for nextcloud's `MAIL_FROM_ADDRESS`+`MAIL_DOMAIN`; unset = the current
`<local>@<domain>`).
- **No regression:** default `tls_mode` keeps vaultwarden/gitea/rallly on 2525 and mealie's plaintext path
unchanged; the hub is untouched (it relays whatever raw MIME the shim sends).
- **Tests:** `smtpEnv` port-by-tls_mode (+ companion that plaintext≠starttls port), split-From (+ companion
single-From), and the `:2526` listener has `TLSConfig==nil` & a real EHLO showing it does NOT advertise
STARTTLS while `:2525` does.
### v0.88.0 — App-email SMTP relay: in-process shim + per-app injection (2026-06-29)
- **What:** deployed apps can now send outbound email (password resets, invites, confirmations) through one
managed path — **app → in-controller SMTP shim → hub → Resend** — with the Resend key staying hub-side.