Commit Graph
224 Commits
Author SHA1 Message Date
Linus Rath 4d846cfc91 fix: read the whole deleted items archive newest first and only for the account shown #1319
Stalwart's x:ArchivedItem/query without calculateTotal scans ids
ascending, stops at 5000 and only then reverses them, so the newest
items of a large archive never showed, and admin accounts got every
account's items. The review of the branch also found gaps around
account switches, restores and focus.

- Read the archive in pages of 500 with calculateTotal, newest first,
  stop at a whole page older than the days limit, and offer
  "Show older" after 2000 items; detection asks for one item.
- Send the accountId filter and fall back without it on
  unsupportedFilter; keep only items of the account, never one without
  an account id.
- Ask nothing until config and policy are loaded and the policy is the
  current account's; the later check after a refusal is forced.
- Show the Trash link only when the archive holds a message inside the
  days limit; the Settings page shows whenever the server has the
  feature and says that archiving must be on in Stalwart.
- Restore: notFound leaves the list with a note, forbidden hides the
  page, results for another account are dropped, the button keeps focus.
- Forget what servers said at a full sign-out.
2026-10-28 09:08:44 +01:00
Linus Rath ba6e6af014 feat: recover deleted items from Stalwart's archive #1319 2026-10-28 07:27:47 +01:00
Linus Rath 795faceee7 Merge branch 'feat/org-thirdparty' into feat/org-features 2026-10-28 05:51:22 +01:00
Linus Rath 687cd89346 Merge branch 'feat/org-external' into feat/org-features
# Conflicts:
#	lib/outgoing/quick-reply.ts
#	lib/outgoing/send-pipeline.ts
2026-10-28 05:46:11 +01:00
Linus Rath 9e809a31db Merge branch 'feat/org-features' into feat/org-thirdparty 2026-10-28 05:27:58 +01:00
Linus Rath 823da8c810 Merge branch 'feat/org-features' into feat/org-external
# Conflicts:
#	components/email/email-viewer.tsx
#	components/mail/mail-app.tsx
2026-10-28 05:19:21 +01:00
Linus Rath 1202a13720 fix: judge external mail by the message's own account and the sending account in several-account setups 2026-10-28 05:11:24 +01:00
Linus Rath 2ace501871 Merge branch 'feat/org-features' into feat/org-signatures 2026-10-28 04:51:22 +01:00
Linus Rath d128503db5 fix: use the organisation policy of the account a message is sent from 2026-10-28 04:32:39 +01:00
Linus Rath a9c89ae7a2 fix: fail closed while the third-party switch is unknown or set as a string #903 2026-10-28 04:30:32 +01:00
Linus Rath 490818adee fix: keep signature plugins from changing a locked organisation signature 2026-10-28 04:18:01 +01:00
Linus Rath ecbbe137c4 fix: wait for sends and keep quick replies as drafts before an automatic sign-out 2026-10-28 04:06:05 +01:00
Linus Rath 3fbd5a7818 fix: check the signature and disclaimer in each part on its own so neither goes out twice 2026-10-28 04:00:25 +01:00
Linus Rath 1f1319d46e fix: hand the retired plugin's parts over one switch at a time and tell plugins about each switch 2026-10-28 03:54:47 +01:00
Linus Rath 65e3d0d2d4 feat: let admins set an organisation signature with user details per domain or group #908
Admins write an HTML and a plain-text signature with placeholders on
Organisation > Signatures, per scope. Users fill in the details it asks
for once, under Settings > Account. Without a lock it is the default for
addresses without a signature of their own; locked or hidden, it
replaces every signature.

- `lib/org-signature.ts` fills the templates: values escaped, lines whose
  placeholders are all empty dropped
- the composer applies it right before the plugin signature, so new mail,
  replies, forwards, re-opened drafts, plain text and identity swaps all
  take it the way they take an identity signature; quick reply too
- a send finaliser puts a locked signature back once when it was deleted
- the identity editor shows the filled-in signature read-only with "Set
  by your organisation" when locked, and no editor when hidden
- `signatureDetails` is a synced setting
2026-10-28 02:23:55 +01:00
Linus Rath 553f1e9149 feat: add a switch that stops all third-party traffic #903 2026-10-28 02:19:06 +01:00
Linus Rath 0738f6f999 feat: say "Set by your organisation" next to settings an admin locked 2026-10-28 00:29:03 +01:00
Linus Rath d610312483 fix: update the open calendar and show reminders on time when events change elsewhere #1349 2026-10-26 20:35:52 +01:00
Linus Rath 9de2efb722 fix: open a shared or group account's message from its link instead of the own message with the same id #1351 2026-10-26 20:01:11 +01:00
Linus Rath af536ac90a fix: keep the account and other query parameters of a mail link Lite replays after a 404 #1352 2026-10-26 20:01:10 +01:00
Linus Rath 8940f45baa fix: apply a custom calendar color picked in the system color dialog #1366 2026-10-26 20:01:09 +01:00
Linus Rath 3a225031bc fix: resize calendar events to the clock time the edge was dropped at on DST change days #1348 2026-10-26 20:01:07 +01:00
Linus Rath 87701c8c20 fix: keep the calendars shown or hidden in the Pro interface as the user set them 2026-10-26 15:15:58 +01:00
Linus Rath cf2c27157d Merge branch 'main' into feat/stalwart-1.0
# Conflicts:
#	components/contacts/contacts-app.tsx
#	components/email/__tests__/composer-discard.test.tsx
#	components/email/calendar-invitation-banner.tsx
#	components/email/email-composer.tsx
#	components/mail/mail-app.tsx
#	components/pro/pro-compose-tab-body.tsx
#	components/pro/pro-email-tab-body.tsx
#	components/ui/__tests__/avatar.test.tsx
#	components/ui/avatar.tsx
#	hooks/use-mailbox-drop.ts
#	lib/__tests__/calendar-alerts.test.ts
#	lib/__tests__/jmap-calendar-tasks.test.ts
#	lib/__tests__/jmap-send-threading.test.ts
#	lib/demo/demo-client.ts
#	lib/demo/fixtures/calendars.ts
#	lib/jmap/client-interface.ts
#	lib/jmap/client.ts
#	lib/web-push.ts
#	stores/__tests__/contact-store.test.ts
#	stores/__tests__/email-store-thread-key.test.ts
#	stores/calendar-store.ts
#	stores/contact-store.ts
#	stores/email-store.ts
2026-10-26 10:14:12 +01:00
Linus Rath f7a4087c91 feat: split the Mountain View inbox into Unread and Everything else, as Gmail's unread first 2026-10-25 13:13:46 +01:00
VasilisNtovolos 96ae3ce4df fix: reject incomplete email ZIP exports and allow retry 2026-10-21 13:11:41 +03:00
Linus Rath 8428219699 chore: drop the drag test notes from the test folder 2026-10-20 21:15:36 +02:00
Linus Rath eb6fb310da Merge branch 'main' into fix/message-drag-blob-routing 2026-10-20 21:15:36 +02:00
Linus Rath 10b4d2a9db feat: rework the admin panel around a settings-style sidebar and one URL per page
The old panel kept its active tab in a store, so every page sat at
/admin, the sidebar duplicated the webmail rail by hand, and each page
was a stack of boxed cards with their own save buttons. Plugin settings
were only reachable through a gear icon in a row of five.

- one catch-all route for the whole panel; pages switch through
  history.pushState, so `/admin/plugins/<id>`, the back button, bookmarks
  and connector links all work without a route transition
- sidebar laid out like the user settings: back to mail, search over
  pages and their sections, two group headings, change password and
  sign out at the bottom; the phone shows a list, then the page
- pages use SettingsSection rows instead of nested cards, with one page
  header, one flash message and one save bar at the bottom (Discard,
  Save, Ctrl+S); the unsaved-changes prompt still guards leaving
- plugins and themes are lists of rows with a toggle each; a row opens
  the extension's own page with its settings, force-on, permissions,
  kept versions and removal
- overview shows stat tiles, server facts and recent activity
- old `/admin?tab=x` links redirect; the tab store is gone and the
  connector registry resolves admin links to the page URL
- `NEXT_TURBOPACK_ROOT` overrides the Turbopack root so `next dev` runs
  from a worktree with a junctioned node_modules
2026-10-20 15:16:05 +02:00
VasilisNtovolos cfa16e1bc2 docs: clarify message drag routing verification 2026-10-20 15:49:05 +03:00
VasilisNtovolos 345fe64515 fix: route dragged emails by owning account 2026-10-20 15:45:47 +03:00
Linus Rath 2abe5eb078 fix: move dragged messages from merged views within their own account (GHSA-8x23-qw3w-mhrx) 2026-10-18 17:54:48 +02:00
Linus Rath 0ac7bcb385 feat: show the message list as columns with one-line conversation rows #262 2026-10-18 17:37:21 +02:00
Linus Rath 58eff0e879 Merge pull request #1258 from HOLOEYE-JZ/feat/archive-feature-gate
feat: admin policy gate to turn off archiving #1257
2026-10-18 14:29:27 +02:00
Linus Rath 107d731af7 feat: remove a message from just the open folder when it is in several #615 2026-10-17 19:18:25 +02:00
Linus Rath 03031fcb13 feat: jump to the next unread message with n #514 2026-10-17 19:18:20 +02:00
Linus Rath 3fd93df4b2 feat: extend the message selection with shift+arrow keys #992 2026-10-17 19:18:15 +02:00
Linus Rath ce60099523 fix: decrypt PGP and S/MIME messages inside conversations #902 2026-10-17 19:17:56 +02:00
Jacob ZeitzandClaude Opus 5.5 99b0bced3b feat: admin policy gate to turn off archiving #1257
A new feature gate, archiveActionEnabled (default on), lets the admin turn the
Archive action off for installations that archive mail elsewhere, such as a
mail gateway. With it off, Bulwark offers no Archive anywhere: the viewer's
button and its overflow entry, the context menu for one or several messages,
Mountain View's selection bar, the hover and swipe actions, the E shortcut and
its help row, archiving after an export, and the archive mode setting (also in
the settings search). With it off nothing creates an Archive folder:
ensureArchiveMailbox returns null. Existing Archive folders stay ordinary
folders, moving mail into them by hand still works, and the plugin API is
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 20:48:28 +02:00
Linus Rath 41a0716c50 Merge branch 'main' into feat/stalwart-1.0 2026-10-16 01:41:48 +02:00
lucletoffeandClaude Opus 5.5 8cf6783cdb feat(calendar): say whom a calendar is shared with
The sidebar showed the same people icon for any calendar with a share,
labelled "Share calendar", and the settings badge only gave a count, so
there was no way to tell from either who could see the calendar. A share
granted to a service account read like a share with other people.

Both now carry a hint listing the recipients ("Shared with
bot@example.com (Booking robot)"), resolved from the principals the
server lists. Until every recipient is known the hint falls back to the
count. Principals are fetched only when a calendar on screen is shared.

The per-client principal cache of the attendee availability check moves
to lib/jmap/principal-cache.ts so both use it. It no longer keeps an
empty or failed answer: the next caller asks again instead of seeing
no principals for the rest of the session.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 22:19:53 +02:00
Linus Rath 1cc949416c perf: load the mail view's code while the login form is shown 2026-10-15 03:24:05 +02:00
Linus Rath 97e13a199c perf: stop re-rendering every message row when the list changes 2026-10-15 02:24:58 +02:00
Linus Rath 47762bedf6 perf: re-render only the message rows that changed 2026-10-15 00:41:07 +02:00
Linus Rath b59e3520f8 perf: stop re-rendering the message rows and mail view on unrelated store changes 2026-10-15 00:00:28 +02:00
Linus Rath 8204678847 fix: stop reporting mail actions as done when a plugin stopped them 2026-10-14 19:44:54 +02:00
Linus Rath 86e593a752 feat: add a command palette on Ctrl+K where plugins can add their own commands 2026-10-14 05:10:10 +02:00
Linus Rath b8b7a4ed15 feat: let plugins add pages of their own with an entry in the navigation 2026-10-14 04:57:00 +02:00
Linus Rath 1307280fd8 Merge branch 'hooks/settings' into feat/plugin-system-audit 2026-10-14 04:05:47 +02:00
Linus Rath 74b194c3e5 feat: tell plugins about sender identity changes and the chosen From, and let them stop a change or rewrite the signature 2026-10-14 03:44:33 +02:00