Add setup instructions for Cloudflare Email Routing (Option A, recommended)
and reposition ForwardEmail as an optional alternative (Option B). Clarify
Cloudflare free plan includes Workers, KV, and Email Routing. Fix security
note scope and remove redundant/misleading content.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Runs on push/PR to main. Also adds skipLibCheck to tsconfig to silence
pre-existing errors in vite/vitest declaration files that don't affect
the Worker build.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Covers extractFeedId, decodeEncodedWords, and parseForwardEmailPayload
including edge cases: missing fields, structured vs text from, headerLines
vs raw headers string, RFC 2047 subject decoding.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Hono's `html` tagged template auto-escapes all interpolated values;
`raw()` is used for the email body which must render as HTML.
This removes the ad-hoc utility and aligns entries.ts with the
same pattern already used in admin.ts.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Make feedId required in generateRssFeed (removes dead /emails/ fallback)
- Hoist loop-invariant conditional and remove intermediate variable
- Extract normalizeAllowedSenders() so JSON and form paths share same logic
- Move escapeHtml to src/utils/html.ts for reuse by admin.ts
- Parallelize the two independent KV puts in feed creation
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
When Content-Type is application/json, parse the request body as JSON and
return a JSON response instead of redirecting. Useful for automation tools
(e.g. Terraform/OpenTofu provisioning).
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Serves each email as a standalone HTML page with a Content-Security-Policy
header, useful for reading emails outside a feed reader and for debugging.
Also updates RSS item links to point to this route.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Parse the From header into name + email parts so the feed library
renders proper RFC 2822 format (email (Name)) in <author> elements.
Also passes feedId to the generator so item links can point to the
upcoming /entries/:feedId/:receivedAt route.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Dependabot will now open PRs when new versions of actions/checkout and
actions/setup-node are released, keeping the pinned SHAs up to date.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Triggers on v* tags. Builds with wrangler --dry-run, falls back to
dist/worker.js and dist/_worker.js if index.js is not produced.
Uploads as index.js so homelab Tofu can fetch a stable URL.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Mirrors the same pattern as cloudflare-email.ts — each provider has its
own adapter that translates provider-specific input into ProcessEmailInput
and delegates to processEmail(). inbound.ts is now a thin HTTP handler.
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]>
- Add `typecheck` script (`tsc --noEmit`) to package.json
- Remove conflicting `declare global` from test/setup.ts (superseded
by @cloudflare/workers-types); use `globalThis as any` for test globals
and declare minimal `require` locally to avoid pulling in @types/node
- Cast `createMockEnv()` and `deleteRes.json()` results in admin.test.ts
to silence strict `unknown` / MockKV-vs-KVNamespace errors
Co-Authored-By: Claude Sonnet 4.5 <[email protected]>