d2d4e49fa66d45b9782422b34bba7af0a85917a3
Admins configure one mail server; each staff member gets their own mailbox login. Read, reply and compose against real IMAP/SMTP. IMAP and SMTP are raw TCP, so none of this can run in a browser — every operation is a TanStack Start server function. mail.functions.ts ships to the client bundle, so imapflow/nodemailer/mailparser and the crypto helpers are imported inside handlers, never at the top level. Verified that Nitro inlines all three into .output/server/_libs, since the Docker runner stage copies only .output and has no node_modules. Note this ties the app to the Node deployment: the default local build targets Cloudflare Workers, which cannot open IMAP sockets. Credential handling, since a mailbox password grants full read and send access to someone's mail: - user_mailboxes has RLS enabled, no policies, and SELECT revoked from anon and authenticated. Verified: teacher and admin both see zero rows and no ciphertext; only service_role can read it. The revoke is belt and braces — Supabase's default privileges had granted SELECT, leaving the table one stray policy away from leaking. - Passwords are sealed with AES-256-GCM using MAIL_CRED_KEY from .env.secret, so a database dump alone opens nothing. GCM also makes tampering fail the auth tag instead of decrypting to garbage. - Provisioning verifies credentials against the live IMAP server before storing them, so typos surface at setup rather than as a broken inbox. Message bodies render as plain text; sender HTML is never injected, which would execute sender-controlled markup and leak read receipts via tracking pixels. Mailboxes are limited to admins and teachers. Students are excluded deliberately — external mail for minors carries archiving, monitoring and consent obligations that should be chosen, not inherited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Description
No description provided
1 MiB
Languages
JavaScript
42.2%
Dockerfile
30.4%
TypeScript
27.4%