fix(mail): send verification + reset emails as multipart/alternative #87

Merged
nrupard merged 1 commit from fix/email-spam-multipart into main 2026-05-13 20:33:47 +02:00
Owner

Summary

  • Verification + password-reset emails were sent plaintext-only via Mailer::send; Gmail/Outlook routinely flag plaintext transactional mail with a bare URL as spam, while the login-alert and digest emails (Mailer::send_multipart) land in the inbox.
  • Convert both bodies to Askama templates under server/templates/email/ (matching the login-alert + digest layout), expose typed structs in a new views::email_auth module, and switch both dispatch paths to send_multipart so every outbound user email goes through the same multipart code path.

Test plan

  • Trigger registration with a fresh email; confirm the verification message arrives as multipart/alternative and lands in Inbox, not Spam.
  • POST /forgot for a known address; confirm the reset email is multipart/alternative and not in Spam.
  • Sign in from a new device; confirm login-alert email still renders unchanged (regression check).
  • just check clean.
## Summary - Verification + password-reset emails were sent plaintext-only via `Mailer::send`; Gmail/Outlook routinely flag plaintext transactional mail with a bare URL as spam, while the login-alert and digest emails (`Mailer::send_multipart`) land in the inbox. - Convert both bodies to Askama templates under `server/templates/email/` (matching the login-alert + digest layout), expose typed structs in a new `views::email_auth` module, and switch both dispatch paths to `send_multipart` so every outbound user email goes through the same multipart code path. ## Test plan - [ ] Trigger registration with a fresh email; confirm the verification message arrives as `multipart/alternative` and lands in Inbox, not Spam. - [ ] POST `/forgot` for a known address; confirm the reset email is `multipart/alternative` and not in Spam. - [ ] Sign in from a new device; confirm login-alert email still renders unchanged (regression check). - [ ] `just check` clean.
fix(mail): send verification + reset emails as multipart/alternative
Some checks failed
Check / clippy + fmt + tests (pull_request) Failing after 13s
4ef2489205
Verification and password-reset emails were dispatched as plaintext-only (`Mailer::send`), which lands them in spam much more often than the digest and login-alert emails that already go out as `multipart/alternative` via `Mailer::send_multipart`. Plaintext-only transactional mail with a bare URL scores higher on Gmail/Outlook spam heuristics; an HTML alternative with the link as a proper anchor reads as a legitimate transactional message.

Move both bodies into Askama templates under `server/templates/email/` (matching how login alerts and the digest are structured), add a `views::email_auth` module to expose the typed template structs, and switch both dispatch paths to `send_multipart` so every outbound user email goes through the same code path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nrupard deleted branch fix/email-spam-multipart 2026-05-13 20:33:47 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!87
No description provided.