Saga sends one email today: Reset your password, through Resend from hello@saga.pictures. Below is that email as it renders, rendered by the builder in src/server/lib/email.ts, then what launch needs from the code, then drafts of the rest in the same frame.
Today: Reset your password
The real HTML from resetPasswordEmail(). Only the image host is rewritten so the artifact can show the pictures. The email itself doesn't change between light and dark mode: it's dark by design, and only the mail app around it changes.
Subject
Reset your Saga password
Preview line
Choose a new password for your Saga account. The link works for one hour.
From → To
Saga <hello@saga.pictures> → sam@example.com
Sent from
emailAndPassword.sendResetPassword
Inbox
S
Saga<hello@saga.pictures>
To: sam@example.com
Today 5:42 PM
Reset your Saga password
Desktop mail · light mode
Inbox
S
Saga<hello@saga.pictures>
To: sam@example.com
Today 5:42 PM
Reset your Saga password
Desktop mail · dark mode
9:41
Inbox
S
Saga5:42 PM
To: sam@example.com
Reset your Saga password
iPhone Mail · 390 pt · light mode
9:41
Inbox
S
Saga5:42 PM
To: sam@example.com
Reset your Saga password
iPhone Mail · 390 pt · dark mode
9:41
Inbox
S
Saga5:42 PM
To: sam@example.com
Reset your Saga password
Remote content is hidden. Load
iPhone Mail · 390 pt · dark mode · remote content off
In the inbox
Saga5:42 PM
Reset your Saga password
Choose a new password for your Saga account. The link works for one hour. Reset your password Use the button below to choose a new password for your Saga account. Set a new password Or paste this link into your browser: https://saga.pictures/reset-password?token=q7Hc2vX9rLmP4tKa8WnYd3Fs This link works for one hour. If you didn't ask for this, ignore this email. Saga · saga.pictures
iPhone Mail, light
Saga5:42 PM
Reset your Saga password
Choose a new password for your Saga account. The link works for one hour. Reset your password Use the button below to choose a new password for your Saga account. Set a new password Or paste this link into your browser: https://saga.pictures/reset-password?token=q7Hc2vX9rLmP4tKa8WnYd3Fs This link works for one hour. If you didn't ask for this, ignore this email. Saga · saga.pictures
iPhone Mail, dark
SagaReset your Saga password- Choose a new password for your Saga account. The link works for one hour. Reset your password Use the button below to choose a new password for your Saga account. Set a new password Or paste this link into your browser: https://saga.pictures/reset-password?token=q7Hc2vX9rLmP4tKa8WnYd3Fs This link works for one hour. If you didn't ask for this, ignore this email. Saga · saga.pictures5:42 PM
Gmail on the web
Plain-text part
Reset your password
Open the link below to choose a new password for your Saga account.
https://saga.pictures/reset-password?token=q7Hc2vX9rLmP4tKa8WnYd3Fs
This link works for one hour. If you didn't ask for this, ignore this email.
Saga · saga.pictures
What breaks in real mail apps
FixApple Hide My Email drops itApple-only accounts get the reset email too (auth.ts), but Apple's relay refuses senders that aren't registered. Register saga.pictures and hello@saga.pictures under Sign in with Apple for Email Communication. SPF on send.saga.pictures and DKIM (resend._domainkey) are already in place, which Apple checks.
FixReplies go nowhereNo reply_to is set, and saga.pictures has no MX record, so a reply to hello@saga.pictures bounces. Add reply_to: support@osroc.io in sendEmail (or route hello@ with Cloudflare Email Routing).
FixNo DMARC record_dmarc.saga.pictures doesn't exist. Gmail and Yahoo require DMARC from bulk senders and weigh it for everyone. Start with p=none and a report address.
FixThe preview line runs into the bodyThe preheader has no filler after it, so Gmail and iPhone Mail continue with "Reset your password Use the button below…" (see the rows below). Pad it with ‌ pairs.
FixOutlook for WindowsIts Word engine ignores max-width (the email stretches to the window), border-radius (square panel and button) and padding on the link (the button shrinks to a tight box around the words). Wrap the 600 px table in an MSO-only table and put the padding on the button's cell.
FixThe poster band is 647 KBposters.png is 1200 × 460 with its background baked in, so it needs no transparency. As an 80% JPEG it's 128 KB: it loads before the button on cellular instead of after.
WatchDark-mode inversionDark by design, so Apple Mail and Outlook leave it alone. Gmail's apps can still recolor dark email; logo.png is bone on transparent, so on a lightened background it disappears. Check once in the Gmail app in dark mode, or give the logo a basalt background.
WatchGmail drops the <style> blockIn the Gmail app with a non-Google account, the 480 px media query is ignored and the panel keeps 40 px padding on phones. It still reads fine.
FinePictures blocked by defaultOutlook and some corporate Gmail block images. Both have alt text and the email reads the same without them (see Pictures off).
FineGmail clipping4.9 KB of HTML against Gmail's 102 KB clip. Far under.
FinePlain-text partMatches the HTML and keeps the raw link on its own line.
FineRate limits3 reset emails per address and 10 per IP every 15 minutes (in the Durable Object's memory).
The launch list
From the code: better-auth has email and password, Google and Apple, Change password and Delete account; no email verification and no Change email. The app has an in-app inbox for follows, requests and invites; reports go to a CLI. Every candidate, kept, deferred or cut:
Email
Verdict
Why
Kind
Sent from
Effort
Reset your password
Launch
Exists (#393, #396). Ships as is today; fix the six items above.
Transactional
emailAndPassword.sendResetPassword
Template and one line in sendEmail
Apple Hide My Email
Launch
Not an email, a setting. Apple drops mail to @privaterelay.appleid.com from senders it doesn't know, so an Apple user who hid their address gets no reset, no security notice, nothing.
Setup
Apple Developer → Sign in with Apple for Email Communication
Owner, 10 minutes, no code
New report (to support)
Launch
The Terms promise a review within 24 hours and nothing tells you a report came in (#43). Goes to support@osroc.io, never to users.
Internal
reportService.create
Small server hook and template
Password changed
Launch
Settings → Change password and reset both exist. This is the only warning someone gets if another person changes their password.
Transactional
hooks.after /change-password, onPasswordReset
Small server hook and template
Account deleted
Launch
Confirms a step that can't be undone, which the Privacy Policy promises. Skip relay addresses: the Apple grant is revoked first, so it can't arrive.
Transactional
deleteUser.afterDelete
One line and template
Confirm your email
Launch
Email sign-ups are never checked (emailVerified is always false), so a typo means a reset can never reach them. Sent once on sign-up, never blocks sign-in, and doubles as the welcome.
Transactional
better-auth emailVerification (sendOnSignUp)
Setting, template, landing line, resend limit
Email changed
Later
There's no Change email in Settings (better-auth's changeEmail is off). When it ships, it needs two emails: confirm the new address, and a notice to the old one.
Transactional
user.changeEmail
Ships with that feature
Account suspended / username reset
Later
Sign-in already says the account is suspended and gives the support address; setup asks for a new username. Worth it once moderation volume is real.
Transactional
POST /api/admin/reports/:id/resolve
Hook and template
Data export ready
Later
No export exists; the Privacy Policy sends export requests to support.
Transactional
None yet
Needs the export feature
Someone followed you
Later
The in-app inbox covers it. Social-activity email needs a per-kind off switch and one-click unsubscribe; push (#289) is the better channel.
Needs opt-out
notification-writes
Preferences, unsubscribe, template
Digest: new episodes this week
Later
Recurring mail about content counts as commercial: opt-in, one-click unsubscribe, a postal address in the footer (CAN-SPAM) and a cron. Decide the channel in #289 first.
Needs opt-in
A weekly cron
Large
Welcome (separate)
Never
Folded into Confirm your email. Google and Apple sign-ups never typed an address, and a second email in the same minute is noise.
Report received / outcome to the reporter
Never
The app already says "Thanks, we'll take a look." Emailing the outcome would tell one person how another was moderated.
Invite a friend
Never
Saga would be emailing someone who never signed up. Spam complaints land on saga.pictures. Invites go through the share sheet and the person's own apps (#158).
Opt-in and unsubscribeEvery launch email is transactional or internal: it answers something the person did, so CAN-SPAM needs no unsubscribe link, only honest From and subject lines. Anything about content (digests, follows) is commercial or close to it: opt-in, one-click unsubscribe and a postal address.
Resend's limitsFree: 100 emails a day, 3,000 a month. Pro: $20 a month for 50,000, no daily cap. The API takes 10 requests a second per team. Confirm-on-sign-up makes a launch day pass 100 quickly: launch on Pro.
Rate limits in placeReset: 3 per address and 10 per IP every 15 minutes. Reports: 10 per person an hour. New: cap report alerts at 20 an hour overall, and Resend confirmation at 3 per address every 15 minutes, both with createRateLimiter. Password changed needs the current password; Account deleted happens once.
Domain healthDKIM (resend._domainkey) and SPF on send.saga.pictures are set. Missing: DMARC, an MX for replies, and the Apple relay registration.
Drafts for launch
Same frame as the reset email: logo, poster band, granite panel, one ochre button at most, footer. Real copy, ready to ship as written. In build order.
1New report (to support)
Subject
New report: @nightowl_88 · Harassment
Preview line
Reported by @mara. The Terms promise a review within 24 hours.
From → To
Saga <hello@saga.pictures> → support@osroc.io
Sent from
reportService.create, after the row is written
Inbox
S
Saga<hello@saga.pictures>
To: support@osroc.io
Today 5:42 PM
New report: @nightowl_88 · Harassment
Desktop mail · light mode
9:41
Inbox
S
Saga5:42 PM
To: support@osroc.io
New report: @nightowl_88 · Harassment
iPhone Mail · 390 pt · dark mode
Saga5:42 PM
New report: @nightowl_88 · Harassment
Reported by @mara. The Terms promise a review within 24 hours. New report on @nightowl_88 Someone reported a profile. The Terms of Use promise a review within 24 hours. Reason Harassment Note Keeps leaving the same insult on everything I rate. Reported @nightowl_88 · Night Owl By @mara Report #212 · 3 open reports Review it from a terminal: API_URL=https://saga.pictures ADMIN_TOKEN=… pnpm admin:reports Sent to support@osroc.io for every new report, at most 20 an hour. Saga · saga.pictures
iPhone Mail, light
Saga5:42 PM
New report: @nightowl_88 · Harassment
Reported by @mara. The Terms promise a review within 24 hours. New report on @nightowl_88 Someone reported a profile. The Terms of Use promise a review within 24 hours. Reason Harassment Note Keeps leaving the same insult on everything I rate. Reported @nightowl_88 · Night Owl By @mara Report #212 · 3 open reports Review it from a terminal: API_URL=https://saga.pictures ADMIN_TOKEN=… pnpm admin:reports Sent to support@osroc.io for every new report, at most 20 an hour. Saga · saga.pictures
iPhone Mail, dark
SagaNew report: @nightowl_88 · Harassment- Reported by @mara. The Terms promise a review within 24 hours. New report on @nightowl_88 Someone reported a profile. The Terms of Use promise a review within 24 hours. Reason Harassment Note Keeps leaving the same insult on everything I rate. Reported @nightowl_88 · Night Owl By @mara Report #212 · 3 open reports Review it from a terminal: API_URL=https://saga.pictures ADMIN_TOKEN=… pnpm admin:reports Sent to support@osroc.io for every new report, at most 20 an hour. Saga · saga.pictures5:42 PM
Gmail on the web
Plain-text part
New report on @nightowl_88
Reason: Harassment
Note: Keeps leaving the same insult on everything I rate.
Reported: @nightowl_88 · Night Owl
By: @mara
Report: #212 · 3 open reports
Review it: API_URL=https://saga.pictures ADMIN_TOKEN=… pnpm admin:reports
The Terms of Use promise a review within 24 hours.
2Password changed
Subject
Your Saga password was changed
Preview line
If you changed it, you're all set. If you didn't, reset it now.
From → To
Saga <hello@saga.pictures> → sam@example.com
Sent from
hooks.after on /change-password, and emailAndPassword.onPasswordReset
Inbox
S
Saga<hello@saga.pictures>
To: sam@example.com
Today 5:42 PM
Your Saga password was changed
Desktop mail · light mode
9:41
Inbox
S
Saga5:42 PM
To: sam@example.com
Your Saga password was changed
iPhone Mail · 390 pt · dark mode
Saga5:42 PM
Your Saga password was changed
If you changed it, you're all set. If you didn't, reset it now. Your password was changed The password for your Saga account ( sam@example.com ) was changed on Oct 9, 2026 at 9:42 PM UTC. Your other devices were signed out. If you did this, there's nothing else to do. If you didn't, reset your password now. Reset your password Need help? Email support@osroc.io . Saga · saga.pictures
iPhone Mail, light
Saga5:42 PM
Your Saga password was changed
If you changed it, you're all set. If you didn't, reset it now. Your password was changed The password for your Saga account ( sam@example.com ) was changed on Oct 9, 2026 at 9:42 PM UTC. Your other devices were signed out. If you did this, there's nothing else to do. If you didn't, reset your password now. Reset your password Need help? Email support@osroc.io . Saga · saga.pictures
iPhone Mail, dark
SagaYour Saga password was changed- If you changed it, you're all set. If you didn't, reset it now. Your password was changed The password for your Saga account ( sam@example.com ) was changed on Oct 9, 2026 at 9:42 PM UTC. Your other devices were signed out. If you did this, there's nothing else to do. If you didn't, reset your password now. Reset your password Need help? Email support@osroc.io . Saga · saga.pictures5:42 PM
Gmail on the web
Plain-text part
Your password was changed
The password for your Saga account (sam@example.com) was changed on Oct 9, 2026 at 9:42 PM UTC. Your other devices were signed out.
If you did this, there's nothing else to do. If you didn't, reset your password now:
https://saga.pictures/reset-password
Need help? Email support@osroc.io.
Saga · saga.pictures
3Account deleted
Subject
Your Saga account was deleted
Preview line
Your library, lists, profile and follows are gone. This can't be undone.
From → To
Saga <hello@saga.pictures> → sam@example.com
Sent from
deleteUser.afterDelete (skip Apple relay addresses: the grant is already revoked)
Inbox
S
Saga<hello@saga.pictures>
To: sam@example.com
Today 5:42 PM
Your Saga account was deleted
Desktop mail · light mode
9:41
Inbox
S
Saga5:42 PM
To: sam@example.com
Your Saga account was deleted
iPhone Mail · 390 pt · dark mode
Saga5:42 PM
Your Saga account was deleted
Your library, lists, profile and follows are gone. This can't be undone. Your account was deleted We deleted your Saga account and everything in it: your swipes and library, your lists, your profile and photo, and your follows. Your username, @sam , is held for 30 days. After that, anyone can claim it. This can't be undone. To use Saga again, sign up for a new account. Didn't delete your account? Email support@osroc.io . Saga · saga.pictures
iPhone Mail, light
Saga5:42 PM
Your Saga account was deleted
Your library, lists, profile and follows are gone. This can't be undone. Your account was deleted We deleted your Saga account and everything in it: your swipes and library, your lists, your profile and photo, and your follows. Your username, @sam , is held for 30 days. After that, anyone can claim it. This can't be undone. To use Saga again, sign up for a new account. Didn't delete your account? Email support@osroc.io . Saga · saga.pictures
iPhone Mail, dark
SagaYour Saga account was deleted- Your library, lists, profile and follows are gone. This can't be undone. Your account was deleted We deleted your Saga account and everything in it: your swipes and library, your lists, your profile and photo, and your follows. Your username, @sam , is held for 30 days. After that, anyone can claim it. This can't be undone. To use Saga again, sign up for a new account. Didn't delete your account? Email support@osroc.io . Saga · saga.pictures5:42 PM
Gmail on the web
Plain-text part
Your account was deleted
We deleted your Saga account and everything in it: your swipes and library, your lists, your profile and photo, and your follows.
Your username, @sam, is held for 30 days. After that, anyone can claim it.
This can't be undone. To use Saga again, sign up for a new account.
Didn't delete your account? Email support@osroc.io.
Saga · saga.pictures
4Confirm your email
Subject
Confirm your email for Saga
Preview line
One tap, so we can send you a reset link if you ever forget your password.
From → To
Saga <hello@saga.pictures> → sam@example.com
Sent from
better-auth emailVerification.sendOnSignUp (email sign-ups only; never blocks sign-in)
Inbox
S
Saga<hello@saga.pictures>
To: sam@example.com
Today 5:42 PM
Confirm your email for Saga
Desktop mail · light mode
9:41
Inbox
S
Saga5:42 PM
To: sam@example.com
Confirm your email for Saga
iPhone Mail · 390 pt · dark mode
Saga5:42 PM
Confirm your email for Saga
One tap, so we can send you a reset link if you ever forget your password. Welcome to Saga, Sam Confirm this is your email, so we can send you a reset link if you ever forget your password. Confirm email Or paste this link into your browser: https://saga.pictures/api/auth/verify-email?token=eyJhbGciOiJIUzI1NiJ9.c2FtQGV4YW1wbGUuY29t&callbackURL=%2F This link works for 24 hours. If you didn't sign up for Saga, ignore this email. Saga · saga.pictures
iPhone Mail, light
Saga5:42 PM
Confirm your email for Saga
One tap, so we can send you a reset link if you ever forget your password. Welcome to Saga, Sam Confirm this is your email, so we can send you a reset link if you ever forget your password. Confirm email Or paste this link into your browser: https://saga.pictures/api/auth/verify-email?token=eyJhbGciOiJIUzI1NiJ9.c2FtQGV4YW1wbGUuY29t&callbackURL=%2F This link works for 24 hours. If you didn't sign up for Saga, ignore this email. Saga · saga.pictures
iPhone Mail, dark
SagaConfirm your email for Saga- One tap, so we can send you a reset link if you ever forget your password. Welcome to Saga, Sam Confirm this is your email, so we can send you a reset link if you ever forget your password. Confirm email Or paste this link into your browser: https://saga.pictures/api/auth/verify-email?token=eyJhbGciOiJIUzI1NiJ9.c2FtQGV4YW1wbGUuY29t&callbackURL=%2F This link works for 24 hours. If you didn't sign up for Saga, ignore this email. Saga · saga.pictures5:42 PM
Gmail on the web
Plain-text part
Welcome to Saga, Sam
Confirm this is your email, so we can send you a reset link if you ever forget your password:
https://saga.pictures/api/auth/verify-email?token=eyJhbGciOiJIUzI1NiJ9.c2FtQGV4YW1wbGUuY29t&callbackURL=%2F
This link works for 24 hours. If you didn't sign up for Saga, ignore this email.
Saga · saga.pictures
My recommendation
Five emails and two settings at launch, in this order. Everything else waits for the feature it belongs to, or for #289 to pick a channel.
Fix the reset email and the domainreply_to support@osroc.io, preheader filler, Outlook button and width, the poster band as JPEG, a DMARC record.
Template only, plus one DNS record
Register Apple's private relaysaga.pictures and hello@saga.pictures under Sign in with Apple for Email Communication. Without it, none of these reach Apple users who hid their address.
Owner, Apple Developer, no code
New report (to support)Keeps the 24-hour promise without checking the CLI daily. Closes the open item in #43.
Small server hook in reportService.create, template
Password changedFrom Settings and after a reset. The one warning someone gets when another person takes over.
Server hook (hooks.after, onPasswordReset), template
Account deletedSent after the rows are gone; skipped for Apple relay addresses.
One line in afterDelete, template
Confirm your emailEmail sign-ups only, never blocks sign-in, doubles as the welcome. Last because it adds a setting, a landing line and a resend limit.
better-auth setting, template, small app change
Move to Resend Pro before launch dayThe free plan stops at 100 a day.