Commit Graph

74 Commits

Author SHA1 Message Date
Julien Herr 5308544672 refactor: simplify quick-win code after review
- 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 <noreply@anthropic.com>
2026-05-20 23:55:17 +02:00
Julien Herr fdedbe13c4 feat: accept JSON on POST /admin/feeds/create and return {feedId, email, feedUrl}
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 <noreply@anthropic.com>
2026-05-20 23:52:14 +02:00
Julien Herr 298765527c feat: add HTML view for individual email entries at /entries/:feedId/:receivedAt
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 <noreply@anthropic.com>
2026-05-20 23:51:28 +02:00
Julien Herr 54e7a1bfa0 feat: parse <author> from From header in RSS items
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 <noreply@anthropic.com>
2026-05-20 23:50:54 +02:00
Julien Herr 243eec0cce refactor: extract ForwardEmail adapter to src/lib/forwardemail.ts
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 <noreply@anthropic.com>
2026-05-20 23:13:43 +02:00
Julien Herr 093efe7fc9 feat: add Cloudflare Email Workers support alongside ForwardEmail
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 <noreply@anthropic.com>
2026-05-20 22:54:46 +02:00
Julien Herr 29446a2aac chore: add typecheck script and fix pre-existing TypeScript errors
- 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 <noreply@anthropic.com>
2026-05-20 22:54:32 +02:00
Julien Herr 3ed9d2ee22 chore: apply Prettier formatting to entire codebase
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-20 22:01:53 +02:00
Young Lee fe1fcda745 fix(admin): make bulk delete retry safe + clarify copyable errors 2026-02-06 15:13:43 -08:00
Young Lee de7978f7bc fix(admin): make bulk delete resilient + persistent error toasts 2026-02-06 15:10:55 -08:00
Young Lee 1c1de9699e fix(admin): clarify bulk delete server error 2026-02-06 14:39:04 -08:00
Young Lee 4b7bb8faf1 fix(admin): improve Cloudflare limit error messages 2026-02-06 14:37:48 -08:00
Young Lee bf3a4d9672 Improve admin delete confirmations 2026-02-06 13:36:17 -08:00
Young Lee aaafe5eab2 fix(admin): make bulk feed delete fast + add purge endpoint 2026-02-06 01:36:05 -08:00
Young Lee 1c40740686 feat(admin): async bulk delete with toasts 2026-02-06 01:17:03 -08:00
Young Lee 2d350a7601 feat(admin): style search + clarify bulk actions 2026-02-06 00:49:36 -08:00
Young Lee 65cf54a764 feat(admin): resizable + sortable table columns 2026-02-06 00:26:38 -08:00
Young Lee 0b898bf600 fix(admin): hide empty descriptions in list view 2026-02-06 00:13:22 -08:00
Young Lee 022c188873 fix(admin): truncate spam titles + speed up table view 2026-02-06 00:11:32 -08:00
Young Lee 223560e874 fix(security): lock down admin + add bulk cleanup UI 2026-02-05 23:18:25 -08:00
Young Lee daf54a0fc0 chore: modernize setup, dependencies, and project docs 2026-02-05 22:34:13 -08:00
Young Lee 6e546d31a0 Testing 2026-02-05 22:18:29 -08:00
Young Lee 56a8263f33 Enhance admin interface, security, and feed management with improved UX and authentication 2025-02-27 18:04:01 -08:00
Young Lee 8839aac24b Set up initial project and files 2025-02-27 14:51:38 -08:00