Files
mailflare/docs
Oday BakkourandClaude Fable 5.1 3655f616be feat(jmap): JMAP server for external mail clients
Adds a JMAP (RFC 8620 core, RFC 8621 mail, submission) endpoint so mail
apps such as Mailtemi, Twake Mail and aerc can read and send Mailflare
mail. Discovery at /.well-known/jmap, session at /jmap/session, API at
/jmap/api, blobs at /jmap/download and /jmap/upload, push at
/jmap/eventsource.

- Auth: an API key with the new `jmap` scope, as a Bearer token or as the
  password of HTTP Basic auth. `authenticateApiKeyValue` is split out of
  the Next-bound `src/lib/api/auth.ts` into a framework-free module and
  refreshes `lastUsedAt` at most once a minute, since protocol clients make
  many small calls.
- Model: the account is the user. Each Mailflare mailbox is a top-level
  JMAP Mailbox with six system children keyed by status and one child per
  user folder; ids encode `mailboxId`, `mailboxId~role` or
  `mailboxId~f~folderId`. A message is in exactly one of them.
- Methods: Mailbox/get|query|set (folders only), Thread/get,
  Email/get|query|set, SearchSnippet/get, Identity/get,
  EmailSubmission/set, Core/echo. Every */changes answers
  cannotCalculateChanges (messages have no change log), so clients
  re-query when the state string moves; eventsource emits StateChange by
  polling the state digest.
- Email/query maps FilterCondition and AND/OR/NOT trees onto message
  columns, supports collapseThreads, anchors, position and calculateTotal.
  Email/get builds objects from stored rows (no MIME parsing), with
  bodyValues, bodyStructure, attachments as blob ids, and header:X forms
  answered from stored headers.
- Email/set updates $seen/$flagged, moves via mailboxIds or
  mailboxIds/<id> patches, creates drafts (with uploaded attachments), and
  destroys to Trash first and permanently from Trash.
  EmailSubmission/set sends a draft through the existing send path and
  reports it destroyed via the implicit Email/set response, since the sent
  copy is a new row. Result references (#ids with resultOf/name/path,
  including the * form) and #creationIds work within a request.
- Settings > Account > Email apps mints a jmap-scoped key and shows the
  server details once. docs/api.md and CLAUDE.md describe the mapping.

Verified with a 47-check script on local D1: discovery redirect, 401/403
paths, Basic and Bearer auth, capabilities, unknown method/capability
errors, mailbox tree and counts, folder create/rename/destroy and system
mailbox protection, query with collapseThreads and result references,
attachment/text/operator filters, bodies with truncation, blob download
of an attachment and of a raw message, Thread/get, snippets, keyword and
mailbox patches, ifInState, upload, Identity/get, a draft created and
submitted in one request with #d1, the sent copy carrying cc and the
attachment, two-step destroy, and eventsource. tsc (11) and eslint (105)
unchanged from main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 15:32:47 +03:00
..
2026-06-19 13:47:19 +07:00
2026-09-08 11:59:21 +07:00
2026-09-08 15:42:33 +07:00
2026-09-06 11:12:45 +07:00