refactor(ingest): return a domain result from processEmail, map HTTP at the edge

processEmail/validateEmail now return an IngestResult discriminated union
({ ok } | { ok: false; reason }) instead of an HTTP Response. The status mapping
moves to the edge (ingestResultToResponse in forwardemail.ts), and the Cloudflare
email handler now logs the rejection reason instead of silently discarding it.

The ingestion core is transport-agnostic. End-to-end status mapping stays covered
by inbound.test.ts (now incl. 410 expired); email-processor.test asserts on the
domain result directly.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Julien HerrandClaude Opus 4.7 committed 2026-05-24 00:02:05 +02:00
1 parent 6b51173722
commit 8f036cf223
5 files changed
+80 -49

No files matched your search

+9
View File
@@ -135,6 +135,15 @@ describe("POST /api/inbound — handler logic", () => {
expect(res.status).toBe(403);
});
it("returns 410 when the feed has expired", async () => {
await env.EMAIL_STORAGE.put(
`feed:${VALID_FEED_ID}:config`,
JSON.stringify({ expires_at: Date.now() - 1000 }),
);
const res = await worker.fetch(makeRequest(makePayload()), env);
expect(res.status).toBe(410);
});
it("returns 200 when sender matches allowlist by exact address", async () => {
await env.EMAIL_STORAGE.put(
`feed:${VALID_FEED_ID}:config`,