Skip to content

Feature: read receipts (MDN, RFC 8098)#369

Merged
rathlinus merged 1 commit into
bulwarkmail:mainfrom
dealerweb:pr/read-receipts-mdn
May 30, 2026
Merged

Feature: read receipts (MDN, RFC 8098)#369
rathlinus merged 1 commit into
bulwarkmail:mainfrom
dealerweb:pr/read-receipts-mdn

Conversation

@dealerweb
Copy link
Copy Markdown
Contributor

Summary

Bulwark has no read-receipt support (JMAP/Stalwart have no native MDN). This adds it end-to-end, client-side: request one when sending, detect incoming requests, and respond with a standards-compliant MDN.

Changes

  • Request: a composer toolbar toggle sets Disposition-Notification-To on the outgoing message; default from a new requestReadReceiptDefault setting.
  • Detect: the viewer reads Disposition-Notification-To and shows a banner (Send / Ignore), hidden in Sent/Drafts/Trash/Junk and once handled.
  • Respond: lib/mdn.ts builds an RFC 8098 multipart/report (two-part per §3.1, UTF-8/base64 text part, localized subject/body); client.sendReadReceipt reuses the existing client primitives (blob upload -> Email/import -> EmailSubmission/set) and sets the $MDNSent keyword (RFC 3503) so it never re-prompts. Behavior configurable: ask / always / never.
  • JMAP client interface + real client + demo mock updated together; message/disposition-notification report parts filtered out of the attachment list. Strings added to all 17 locales.

Type of Change

  • New feature (non-breaking change that adds functionality)

Checklist

  • I have read the Contributing Guide
  • My code follows the project's code style and conventions
  • I have run npm run typecheck && npm run lint and there are no errors
  • The build passes (npm run build)
  • I have tested my changes locally
  • I have updated translations (locales/) if my changes affect user-facing text

Notes for Reviewers

Tested end-to-end on Stalwart Mail Server: request/detect/respond all work, the generated MDN is accepted, and the $MDNSent keyword suppresses re-prompts. The existing JMAP client + email-store test suites pass unchanged (24 tests across resilience + multi-account).

Bulwark had no read-receipt support (JMAP/Stalwart have no native MDN).
End-to-end, client-side, in three parts:

- Request (compose): a toolbar toggle (MailCheck, green when on) sets
  Disposition-Notification-To on the outgoing message via the JMAP
  "header:<name>:asText" create property. Threaded composer -> page ->
  email-store -> client.sendEmail. Default from requestReadReceiptDefault.

- Detect (viewer): reads Disposition-Notification-To case-insensitively from
  the parsed headers and shows a banner (green Send / red Ignore) in the
  unified notification bar. Hidden in Sent/Drafts/Trash/Junk and once handled.
  message/disposition-notification + message/delivery-status report parts are
  filtered out of the attachment list.

- Respond (MDN): lib/mdn.ts builds an RFC 8098 multipart/report (text/plain +
  message/disposition-notification, UTF-8/base64, localized subject + body).
  client.sendReadReceipt uploads the blob, imports it into Sent via
  Email/import, then submits with an explicit envelope. Both Send and Ignore
  set the $MDNSent keyword (RFC 3503) so no client re-prompts. Behaviour
  configurable: ask / always / never.

New: lib/mdn.ts, read-receipt-banner.tsx. Settings (requestReadReceiptDefault,
readReceiptResponse) + UI. All 17 locales.
@rathlinus rathlinus merged commit bebb394 into bulwarkmail:main May 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants