feat(notifications): email notification channel

Adds email as a notification channel built on the shared SMTP core
(mail.Sender). Email mode is a per-account preference (off, daily
digest, or per-episode) stored in notification_email_prefs; delivery is
an account-watermark sweep over notification_deliveries that dedupes
cross-profile duplicates, advancing the watermark only after a
successful send. Admin controls cover the channel kill switch, the
per-episode allowance (off coerces those accounts to the digest),
digest hour, and an external URL for deep links inside emails.
Availability is advertised through /notifications/capability and the
user settings page gains an Email section for opt-in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Quick
2026-06-11 18:09:37 -04:00
co-authored by Claude Fable 5
parent e5b210589d
commit df95e3cb95
18 changed files with 1540 additions and 1 deletions
+8
View File
@@ -2333,6 +2333,14 @@ export interface NotificationCapability {
android_push: { available: boolean; provider: string; supported_modes: string[] };
web_push: { available: boolean; public_key?: string };
webhooks: { available: boolean; max_per_profile: number; supported_types: string[] };
email: { available: boolean; modes: string[]; digest_hour: number };
}
export type NotificationEmailMode = "off" | "per_episode" | "daily_digest";
/** Account-level (not per-profile): one mode covers all profiles. */
export interface NotificationEmailPreferences {
mode: NotificationEmailMode;
}
export interface WebPushSubscriptionView {