import PostalMime, { type RawEmail } from "postal-mime"; import { getAddress, incrementReceivedCounter } from "./db.ts"; import type { Dispatcher } from "./dispatch.ts"; import type { SqlExecutor } from "./storage.ts"; import type { OwnerRef, ParsedMail } from "./types.ts"; // Deliberately not Cloudflare's ForwardableEmailMessage: postal-mime accepts // every raw format either mode hands it (a ReadableStream from Email Routing, // a string from mail.tm's API), so this is the only shape core needs. export interface InboundMessage { to: string; from: string; raw: RawEmail; } export async function handleInboundEmail( message: InboundMessage, db: SqlExecutor, dispatcher: Dispatcher ): Promise { const recipient = message.to.toLowerCase(); const row = await getAddress(db, recipient); const now = Math.floor(Date.now() / 1000); if (!row || row.revoked !== 0 || (row.permanent !== 1 && row.expires_at <= now)) { return; } const owner: OwnerRef = { type: row.owner_type, id: row.owner_id }; await incrementReceivedCounter(db); const parsed = await PostalMime.parse(message.raw, { attachmentEncoding: "arraybuffer" }); const mail: ParsedMail = { from: parsed.from?.address ?? message.from, to: row.address, subject: parsed.subject ?? "(no subject)", text: parsed.text ?? "", html: parsed.html, attachments: parsed.attachments.map((a) => ({ filename: a.filename ?? "attachment", contentType: a.mimeType, size: a.content instanceof ArrayBuffer ? a.content.byteLength : 0, content: a.content as ArrayBuffer, })), }; const result = await dispatcher.deliverMail(owner, mail); // A failed delivery (most often the recipient having DMs closed) must not // throw. The mail is already accepted at this point and retrying would // just redeliver. But failing silently makes it impossible to tell a // broken adapter from an empty inbox, so record that it happened. Only the // adapter type and error are logged: never message content, addresses, or // owner ids. if (!result.success) { console.warn(`delivery failed via adapter "${owner.type}": ${result.error ?? "unknown error"}`); } }