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<void> {
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",