Login link: queue the mail, resolve any verified address !270

merged merged by cmc on 2026-09-05 19:51 UTC · krz/gitbay:login-followups into main

Discussion

cmc

Two follow-ups from reviewing the email-login work.

The mail went out from a fire-and-forget goroutine, which kept the send off the request path but lost it on a restart — http.Server.Shutdown waits for requests, not for goroutines a handler spawned. It now goes through store.EnqueueMail, which notify.Mailer drains with retries, so it survives a crash rather than only a graceful shutdown. The timing property that goroutine existed for is unaffected: an INSERT is comparable to the miss path's SELECT.

A login link expires in fifteen minutes, so a queue that retried past that would deliver a dead link — worse than dropping it, because the recipient sees only "invalid link". Worst case is 450s against a 900s TTL, and TestLoginLinkOutlivesMailerRetries recomputes that from the mailer's own constants rather than restating the numbers, so changing either side fails the test instead of silently shipping expired links.

Resolution by username went through PrimaryVerifiedEmail, so an account with an unverified primary and a verified secondary got nothing by username while succeeding by giving that address directly. PreferredVerifiedEmail prefers a verified primary and otherwise takes the alphabetically first verified address — the ordering ListEmails already uses. PrimaryVerifiedEmail is unchanged; its four callers mean what its name says.

The enumeration test gained that account shape rather than getting a test of its own, so the byte-for-byte guarantee still covers it.

Closes #158 Closes #159