Commit Graph
255 Commits
Author SHA1 Message Date
Linus Rath ae66f8d89d Feature: per-viewer colors for shared calendars (#345) 2026-05-31 15:52:27 +02:00
dealerwebandLinus Rath bebb394f54 Feature: read receipts (MDN, RFC 8098)
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.
2026-05-30 15:58:39 +02:00
dealerwebandLinus Rath 2ba0003e16 Feature: localizable sandboxed plugins (manifest locales + api.i18n.t)
The plugin runtime received the active locale (init payload + 'locale-change')
and plugins could declare a `locales` map, but none of it was usable: the
locales never reached the runtime, and buildPluginApi exposed no i18n. So
plugin code calling pluginApi.i18n.t(...) (as the External Link Warning plugin
does) always got undefined and fell back to English.

Thread plugin locales end to end and surface an i18n API:
- ServerPlugin gains `locales`; the upload route persists manifest.locales
  (alongside configSchema/settingsSchema), and /api/plugins surfaces it to the
  client so it flows registry -> client -> sandbox host-bridge -> runtime.
- runtime sets __PLUGIN_LOCALE__ at init (not only on later 'locale-change')
  and buildPluginApi exposes `i18n.locale` + `i18n.t(key, vars)` resolving
  against the plugin's declared locales (manifest.locales) with English/key
  fallback and {placeholder} interpolation.

Lets any sandboxed plugin localize its strings from its manifest.
2026-05-30 15:56:55 +02:00
31e96d6a46 Feat: Scheduled send and send delay #322
* ADD DOC

* Scheduld Send

* add new shortcuts

* fix

* fix

* fix bugs

* rework

* fix draft duplicating

* fix err

* some fixes

* fixes from review

* fixes from review

* fixes from review

* disable password managers for recipients

* fix email store lazy load

* add translations

* fix styling

* fixes

---------

Co-authored-by: Linus Rath <139418639+rathlinus@users.noreply.github.com>
2026-05-28 18:46:49 +02:00
Shuki VakninandGitHub e93dd44111 fix: report real upload progress; XHR with progress events #333
The Files page UI sat at 0% throughout an upload because uploadBlob()
uses fetch(), which does not surface upload progress events. The store
set loaded=0 before the call and loaded=file.size after it, so users
saw the progress bar jump from 0% straight to 100% on completion --
and on slow connections (or large files) it appeared frozen.

Switch uploadBlob() to XHR when the caller passes onProgress or an
AbortSignal, so progress events from xhr.upload.onprogress can drive
the UI. Callers that don't pass either keep the fetch path so we
preserve the existing 401-retry behaviour in authenticatedFetch().

Wire the file store to pass both onProgress (updates uploadProgress
in real time) and the existing AbortController's signal (so cancel
now actually aborts the network request, not just the post-upload
createFileNode step).

uploadBlob() is part of IJMAPClient so the signature change is also
applied to the demo client (synthesises 0% then 100%).
2026-05-28 18:20:22 +02:00
Linus Rath 3a8daf8bff feat: allow drag-and-drop into shared mailboxes 2026-05-25 18:53:54 +02:00
Linus Rath f8e7cce85a fix: prevent empty main pane when reordering tabs across panes 2026-05-25 18:25:55 +02:00
Linus Rath 534894c38d feat: locale-aware date format in email list with preset picker #331 2026-05-25 16:17:32 +02:00
Linus Rath 537707d9ed feat: include group inboxes in unified mailbox view #328 2026-05-23 16:01:22 +02:00
Linus Rath acc90eb455 feat: add "Move to Trash and mark as read" delete action #323 2026-05-22 19:08:02 +02:00
Linus Rath 58e4a3d117 feat: add post-export action setting (keep/archive/trash) 2026-05-22 15:36:15 +02:00
Linus Rath e3f6ae874d feat: add settings template for multi-email .zip filename 2026-05-22 15:30:15 +02:00
Linus Rath 3ac14ecf38 feat: add filename transform settings 2026-05-22 14:57:25 +02:00
Linus Rath ca0d6805cf feat: add Downloads settings tab with template editor for .eml and attachment filenames 2026-05-22 14:46:25 +02:00
Linus Rath d3778e6521 fix: handle malformed event dates in calendar route #316 2026-05-22 14:04:02 +02:00
Linus Rath fc5f6f43d6 feat: expose PWA, app identity, and extension directory keys in JSON config #312 2026-05-21 23:35:58 +02:00
Linus Rath e80412b6fd feat: show contacts from all logged-in accounts in Pro shell 2026-05-21 22:32:17 +02:00
Linus Rath 4cfee4f672 feat: split owned vs shared calendars per account in sidebar in Pro shell 2026-05-21 18:54:09 +02:00
Linus Rath 7076f1ded8 feat: show calendars from all logged-in accounts in Pro shell 2026-05-21 18:48:55 +02:00
Linus Rath 33e655bcce feat: narrow-pane sidebars and cross-account file picker in Pro shell 2026-05-21 17:54:03 +02:00
Linus Rath 280f5bc675 feat: support cross-account email moves in Pro shell 2026-05-21 17:22:31 +02:00
Linus Rath 1756f5ac1c feat: enable search in unified mailbox in pro mode 2026-05-21 17:12:06 +02:00
Linus Rath 426d344aa8 feat: multi-account mail sidebar and client routing for Pro shell 2026-05-21 16:52:03 +02:00
Linus Rath ed90e096b5 feat: add per-account mailbox cache for Pro shell data layer 2026-05-21 16:11:26 +02:00
Linus Rath 9763ffa2a3 fix: keep proInterface per-device instead of syncing it 2026-05-21 15:39:02 +02:00
Linus Rath 5008857880 fix: respect server-resolved locale on first visit #309 2026-05-20 23:53:44 +02:00
Linus Rath 628966d3b5 fix: split app into (main)/(sandbox) route groups so plugin iframe hydrates properly 2026-05-20 23:41:49 +02:00
Linus Rath d45c8ef511 feat: list and reorder logged-in accounts in settings #282 2026-05-20 19:22:44 +02:00
Linus Rath 433a63bf1a fix: normalize malformed contact photo data URIs #307 2026-05-20 18:42:12 +02:00
Linus Rath c3b4707f85 feat: pro: drop top/bottom split, keep side-by-side only 2026-05-18 19:51:43 +02:00
Linus Rath 43ac0725ce feat: pro: drag tabs to reorder, drag to edge to split 2026-05-18 19:30:54 +02:00
Linus Rath 98879802ae feat: add Pro interface 2026-05-18 19:17:39 +02:00
Linus Rath b2d24670ff fix: scope iCal subscriptions per JMAP account and fix refresh/clear 2026-05-18 16:39:02 +02:00
Linus Rath 40f36baf94 fix: iCal subscription refresh, rollback, and URL normalization 2026-05-18 16:31:16 +02:00
Linus Rath 313a1fcce9 fix: stop persisting S/MIME passphrases in sessionStorage 2026-05-18 15:32:04 +02:00
Linus Rath 48aa607b56 feat: lock down plugin runtime in sandbox + signing + approval 2026-05-18 12:44:23 +02:00
Linus Rath 088810bd20 feat: harden plugin sandbox and migrate in-tree plugins 2026-05-18 12:17:54 +02:00
Linus Rath 4221c9a50f fix: strip Stalwart master-user '%' suffix from displayed account 2026-05-16 19:07:10 +02:00
Linus Rath 482493a10d fix: register app-top-banner in plugin-store SLOT_NAMES 2026-05-16 18:53:06 +02:00
Linus Rath 0e1036eb49 fix: adopt orphan session cookie on first SPA load 2026-05-16 18:45:30 +02:00
Linus Rath 8dbb538c98 feat: sync onboarding status across devices #285 2026-05-15 15:09:42 +02:00
Linus Rath c646c87030 fix: standardize punctuation in tooltips and comments across multiple locales and code files 2026-05-14 21:44:24 +02:00
Lucas GaitzschandLinus Rath 3f444a8912 Feature/protocol handlers
* Added account selection for protocol links when multiple connected accounts are available, including mailto: links
* Added support for handling mailto: links in an already-open PWA/session instead of always opening a new tab
* Added webcal: protocol handling for calendar links
* Added account selection for webcal: links when multiple calendar-capable accounts are connected
* Added an import-or-subscribe choice for detected webcal calendars
* Added protocol handler settings for registering mail and calendar handlers and choosing the open mode
* Added service worker/session coordination for passing protocol requests between browser/PWA contexts
* Added tests and translations for the new protocol handler flows
2026-05-12 20:49:05 +02:00
Linus Rath f9f8af2f11 fix: preserve signature styling and reactivity in above-quote mode #272 2026-05-12 16:03:10 +02:00
Linus Rath 5f3d2d3e4a feat: signature above quoted text option #266 2026-05-11 17:05:59 +02:00
Linus Rath 2c513129f2 feat: add Reading Pane at Bottom mail layout #262 2026-05-11 15:35:43 +02:00
Linus Rath b3dc2e32b8 feat: implement prefetching of initial email data 2026-05-11 15:17:30 +02:00
Augustin MarcinandLinus Rath b0640c9ecc feat(compose): From override + catch-all auto-reply (fixes #246)
Adds an Override toggle in the composer's From row. When enabled, name
and address become free-text inputs. Mail is still submitted through the
selected identity, but the outgoing message's From: header — and the
SMTP envelope MAIL FROM when different — is set from the override.

The existing "Auto-select Reply Address" setting is extended: if the
incoming message was addressed to an alias on a domain that matches one
of your identities but isn't itself an identity (classic domain catch-
all), it now auto-enables Override and pre-fills the alias. Quick reply
honors the same resolution. The setting is relabeled to reflect the
broader behavior.

JMAP: client.sendEmail gains an optional envelopeMailFrom; when set, the
EmailSubmission includes an explicit envelope with that mailFrom and the
to/cc/bcc as rcptTo so header-From and envelope can diverge (JMAP §7.3).

S/MIME: override is incompatible with sign/encrypt and is refused with a
clear error — signing a different visible From from the identity's
certificate Subject would produce messages clients reject.

Tests: resolveReplyFrom covers exact match, sub-address stripping,
catch-all detection, identity preference, and foreign-domain null.
2026-05-11 12:13:47 +02:00
Linus Rath 2d7e24b513 perf: parallelize login round-trips and drop redundant JMAP re-verify 2026-05-11 11:04:13 +02:00
Linus Rath 5f464d4ee2 feat: lift 5-account cap on HTTP/2 2026-05-07 12:28:33 +02:00