Skip to content

df38dea/mailx

Repository files navigation

mailx

mailx is an experimental, single-tenant, multi-account jmap service for Cloudflare Workers, Email Workers, D1, KV, and R2/S3-compatible object storage.

This project is not a complete JMAP server. It implements only a pragmatic minimum subset of two RFCs:

  • RFC 8620, JMAP Core
  • RFC 8621, JMAP Mail

The implementation is aimed at lightweight personal or small-team deployments and real-world webmail compatibility experiments. Expect protocol gaps, client-specific compatibility fixes, and behavior that intentionally degrades to simpler polling or storage models.

Status

This is an experimental project. Do not treat it as a production-grade mail server, compliance archive, enterprise mailbox, or full IMAP/JMAP replacement.

The current goal is to provide enough JMAP Core/Mail behavior for basic webmail workflows:

  • Sign in
  • List mailboxes
  • Receive mail through Cloudflare Email Routing
  • Read/search simple message lists
  • Save drafts
  • Send mail through Resend
  • Upload/download blobs and attachments
  • Track basic mail state changes

Feature Matrix

JMAP Client Workflows

Feature Status Notes
Receiving mail Fully usable Cloudflare Email Routing delivers to the Email Worker; raw MIME is stored in object storage and metadata is written to D1.
All mail / mailbox listing Fully usable Mailbox/get, Mailbox/query, Email/query, and mailbox counters cover the basic mailbox/all-mail views used by tested clients.
Marking messages Fully usable Supports common keyword changes such as $seen, $flagged, and $draft.
Moving between folders Fully usable Supports mailboxIds patches for archive, inbox removal, and normal folder moves.
Drafts Fully usable Supports Email/set create for draft creation, body values, recipients, keywords, and mailbox assignment.
Sending mail Partially usable Resend delivery succeeds, but at least one tested client still reports failure in the UI despite successful delivery/webhook callbacks. This remains a JMAP response/client-compatibility issue.
Attachments Partially usable Basic inbound/outbound attachment upload, send, parse, and download paths exist. MIME tree fidelity, inline CID handling, and complex multipart structures are still simplified.
Templates Partially usable Template-like drafts can be saved and reused manually, but there is no first-class template model or template API.
Search Partially usable Basic mailbox/keyword query behavior exists; full-text search and full RFC filter/sort semantics are not implemented.
Threads Partially usable Lightweight thread ids are exposed, but conversation grouping is minimal.
Submission status Partially usable Resend webhook updates submission state, but event history and deduplication are incomplete.
Push/realtime sync Degraded EventSource is only a compatibility endpoint; clients should fall back to polling Foo/changes.

Platform And Management

Feature Status Notes
Worker HTTP app Fully usable Hono app with JMAP and /v0/* APIs.
Email Worker entrypoint Fully usable Handles inbound mail from Cloudflare Email Routing.
Local auth Fully usable Username/password login with Bearer tokens.
JMAP Basic auth Fully usable Supports username or assigned email identity.
Account management Fully usable Single-tenant multi-account management through /v0/management.
Identity management Fully usable Admin-assigned sending identities and user-editable identity metadata.
Dynamic domains Fully usable DOMAIN supports JSON array strings and dynamic postmaster/catch-all behavior.
Resend relay Partially usable Sends through Resend HTTP API; no durable retry queue.
Resend webhooks Partially usable Delivery callbacks update current submission state; no complete svix-id dedupe/event history.
Object storage Partially usable R2/S3 abstraction stores raw messages and uploads; no historical object migration or full GC.
Local runtime Fully usable SQLite, file KV, and file object storage for tests/local development.

Not Implemented

Feature Status Notes
Full RFC 8620 compliance Not implemented Only a minimal practical subset is implemented.
Full RFC 8621 compliance Not implemented Only common mail workflows are implemented.
IMAP/SMTP/POP3/LMTP/ManageSieve Not implemented mailx is not a traditional mail server stack.
Sieve filtering Not implemented No server-side filtering language.
JMAP WebSocket, RFC 8887 Not implemented Clients must use polling.
JMAP Quotas, RFC 9425 Not implemented No quota capability or enforcement.
Calendar/contacts/tasks Not implemented Mail only.
Multi-tenant deployment Not implemented One deployment is one tenant.
End-user self-registration Not implemented Accounts are admin/management-key created.
OAuth/OIDC login Not implemented Placeholder documentation only.
Full-text search Not implemented No search index.
Advanced JMAP filter/sort/collation Not implemented Basic filters only.
Complete MIME editing Not implemented No robust inline CID rewriting, calendar invite handling, signing, or encryption support.
DKIM/SPF/DMARC implementation Not implemented Delegated to external DNS/relay/provider behavior.
Spam/virus scanning Not implemented No content safety pipeline.
Mailbox ACL/shared mailboxes Not implemented No shared mailbox model.
Quota enforcement Not implemented No storage/send quota enforcement.
Durable outbound retry queue Not implemented Failed Resend calls are recorded as failed submissions.

Intentional Degradations

Several behaviors intentionally degrade to simpler implementations:

  • Push degrades to polling. /jmap/eventsource exists for compatibility, but it does not provide continuous real-time push.
  • WebSocket is not advertised or implemented.
  • Query changes degrade to conservative remove/add replacement for updated messages.
  • Mailbox counters are recomputed from D1 relationships instead of maintained as authoritative counters.
  • Attachments are downloaded by reparsing the stored raw message and extracting the requested attachment part.
  • Threading degrades to simple stored or virtual thread ids rather than complete RFC-grade conversation grouping.
  • Outbox degrades to client compatibility cleanup rather than a durable server-side send queue.
  • Delivery tracking degrades to Resend state snapshots in email_submissions.relay_response rather than a full event history.
  • Session discovery without credentials returns public discovery with empty accounts so clients can discover the endpoint before auth.
  • Unknown or unsupported JMAP methods return unknownMethod rather than attempting broad compatibility shims.

Important Configuration

Required Worker configuration:

  • TOKEN_SECRET
  • MANAGEMENT_KEY
  • PUBLIC_BASE_URL
  • D1 binding: DB
  • KV binding: KV
  • R2 binding: BUCKET, or compatible object storage configuration

Common optional configuration:

  • DOMAIN, JSON array string such as ["example.com"]
  • RESEND_API_KEY
  • RESEND_WEBHOOK_SECRET
  • RESEND_FROM_DOMAIN
  • TOKEN_TTL_SECONDS
  • UPLOAD_TTL_SECONDS
  • SEND_RATE_LIMIT
  • SEND_RATE_WINDOW_SECONDS

TOKEN_SECRET, MANAGEMENT_KEY, and PUBLIC_BASE_URL are reserved deployment configuration and cannot be overwritten through the management API.

Other mutable config may be stored with /v0/management Config/set, including secret values such as RESEND_API_KEY and RESEND_WEBHOOK_SECRET.

Storage Model

New inbound, imported, and draft messages are stored as raw RFC822/MIME objects:

emails/{accountId}/{emailId}.eml

For new messages:

  • blobId = emailId
  • storage_key = emails/{accountId}/{emailId}.eml

Uploaded temporary blobs are stored separately under account upload paths and may be referenced by draft creation or import flows.

Resend Webhooks

Webhook endpoint:

https://<your-public-base-url>/webhooks/resend

Recommended Resend events:

  • email.sent
  • email.delivered
  • email.delivery_delayed
  • email.bounced
  • email.failed
  • email.complained
  • email.suppressed

Optional tracking events:

  • email.opened
  • email.clicked

Do not enable unrelated domain/contact events unless you add handlers for them.

Development

Common checks:

bun run format
bun run typecheck
bun run test
bun run test:local

Cloudflare Workers pool tests may fail in constrained containers due to workerd/tcmalloc virtual address space assumptions. The local runtime tests are the primary fast feedback path for this repository.

Documentation

Additional API and design notes live in:

  • docs/spec.md
  • docs/v0-api.md

License

This project is released under CC0 1.0 Universal. See LICENSE.

About

mailx is an experimental, single-tenant, multi-account jmap service for Cloudflare Workers, Email Workers, D1, KV, and R2/S3-compatible object storage.

Topics

Resources

License

Stars

Watchers

Forks

Contributors