Attachments from incoming emails are uploaded to an optional Cloudflare R2
bucket and exposed as <enclosure> elements in RSS and <link rel="enclosure">
in Atom feeds, served at /files/{id}/{filename} with immutable caching.
R2 is opt-in: if ATTACHMENT_BUCKET is not bound the feature is a no-op.
Attachments are cleaned up from R2 on email/feed deletion and during
size-based feed trimming. Adds MockR2 to the test setup.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Emails are now trimmed from the oldest end when total serialised size
exceeds FEED_MAX_SIZE_BYTES (default 512 KB). Each EmailMetadata entry
stores its size so future trims are computed without re-reading KV.
Adds FEED_MAX_SIZE_BYTES, PROXY_TRUSTED_IPS and PROXY_AUTH_SECRET to Env.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- email-processor: run email put + metadata get in parallel (saves one KV round-trip per email)
- email-processor: add missing 50-email metadata cap (was unbounded unlike storage.ts)
- email-processor: remove redundant normalizeEmail call on already-normalized allowedSender
- email-parser: strip WHAT-comments and boilerplate JSDoc throughout
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Both email providers now work in parallel on the same Worker:
- ForwardEmail: existing POST /api/inbound webhook (unchanged)
- Cloudflare Email Routing: native `email` handler using postal-mime
New files:
- src/lib/email-processor.ts shared business logic (feed lookup,
sender allowlist, KV storage) extracted from inbound.ts
- src/lib/cloudflare-email.ts Cloudflare `email` handler; parses
raw RFC 2822 email with postal-mime, delegates to processEmail()
- src/lib/email-processor.test.ts 9 unit tests
- src/lib/cloudflare-email.test.ts 5 integration tests
Also fixes pre-existing CORS 204 response: c.text("", 204) →
c.body(null, 204) to match Hono's EmptyStatusCode constraint.
To enable: configure Cloudflare Email Routing with a catch-all rule
`*@domain.com` pointing to this Worker.
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>