Commit Graph
2286 Commits
Author SHA1 Message Date
Linus Rath d7cb895ebf Merge branch 'feat/assistant-everywhere' into feat/assistant-d
# Conflicts:
#	lib/__tests__/plugin-permission-coverage.test.ts
2026-11-03 01:19:42 +01:00
Linus Rath 55d9c81210 Merge more actions for the assistant (package C) 2026-11-03 01:13:47 +01:00
Linus Rath 6c3e68ce4e Merge branch 'feat/assistant-everywhere' into feat/assistant-d 2026-11-03 01:01:29 +01:00
Linus Rath d68970126e feat: tell plugins when the open message's attachments can't be read from this login 2026-11-03 00:33:59 +01:00
Linus Rath 9ce4d01807 fix: keep the reader still while the list changes, and give Pro tabs no list ticks 2026-11-03 00:30:56 +01:00
Linus Rath 08bc05a20b Merge branch 'feat/assistant-everywhere' into feat/assistant-b 2026-11-03 00:24:50 +01:00
Linus Rath 267ca40522 Merge branch 'feat/assistant-everywhere' into feat/assistant-c 2026-11-03 00:24:12 +01:00
Linus Rath 12dc2ce3c8 feat: let plugins find, read, attach, save and create files in Files 2026-11-03 00:17:46 +01:00
Linus Rath 6edf7f80a5 fix: let plugins stop an attachment saved to Files, as they can stop an upload 2026-11-03 00:17:45 +01:00
Linus Rath 363c797178 feat: let a plugin dialog fill the window's visible height, so a chat fits above a phone's keyboard 2026-11-02 23:59:57 +01:00
Linus Rath ad36f8d382 fix: show the side panel only where the plugin does, and keep it steady
- The button and the panel of Calendar, Contacts, Files and Settings
  show only when the plugin's shouldShow says yes, so a plugin switched
  off for these views (admin, user or no service) leaves no button that
  opens an empty panel, and no extra rows in Contacts and Settings.
- Files: while the details are open the panel steps aside there only;
  the other views keep it as the user left it. With both stored open the
  details fold when the page loads.
- Resizing stops where the view keeps its 480 px, so a drag or the arrow
  keys no longer fold the panel away (and the handle keeps the focus).
- Settings and Contacts render the same element with or without the
  panel, so a form keeps what was typed when the panel starts docking.
- Contacts on a phone: the panel button sits over an open contact too.
- The panel buttons of the reader and the views have one name, "Plugin
  panel", with aria-pressed, and name the plugin's panel shortcut in
  their title; the open panels are named landmarks.

The reader tests look the button up by its new name and pressed state
(viewer-toolbar-over-side-panel, reader-plugin-surfaces,
viewer-plugin-panel-width), since "Show/Hide plugin panel" is gone.
2026-11-02 23:54:53 +01:00
Linus Rath 8905d31b38 fix: show the admin's locks for plain text and the reply identity on the composing page 2026-11-02 23:14:21 +01:00
Linus Rath 7dd5fe41c3 refactor: answer invitations from one place the reader's banner and plugins share 2026-11-02 23:14:21 +01:00
Linus Rath 8139214aea feat: tell the reader panel which messages are ticked in the list 2026-11-02 22:12:01 +01:00
Linus Rath 8fcd647215 feat: let plugins show a side panel next to Calendar, Contacts, Files and Settings 2026-11-02 21:59:36 +01:00
Linus Rath bda9e11d37 fix: give the Files details panel the same header height as the other side panels 2026-11-02 21:02:05 +01:00
Linus Rath 6db1f3d373 fix: give the composer's side panels the reader's button and header 2026-11-02 20:59:53 +01:00
Linus Rath c3da79e7d5 fix: keep the assistant panel's button in the same place with no message open 2026-11-02 20:55:26 +01:00
Linus Rath 55f1875f20 refactor: take quick reply plugin recipients from the quick reply envelope #1445 2026-11-01 18:18:48 +01:00
Linus Rath 5caf3378b2 Merge pull request #1445 from illuwa-soft/feat/upstream-quick-reply-actions
feat: offer composer plugin actions in quick reply
2026-11-01 18:15:18 +01:00
Linus Rath dd94a2b7c8 refactor: keep composer snapshot comments in English #1443 2026-11-01 18:15:13 +01:00
Linus Rath 4a597eb0dc Merge pull request #1443 from illuwa-soft/feat/upstream-composer-read-api
feat: add composer snapshots and conditional edits

# Conflicts:
#	lib/__tests__/plugin-sandbox-runtime-host-gate.test.ts
#	lib/plugin-sandbox/host-api.ts
2026-11-01 18:13:10 +01:00
Linus Rath c48b4428fa Merge pull request #1489 from VasilisNtovolos/fix/discard-pending-uploads
fix: cancel pending attachment uploads when discarding a draft
2026-11-01 18:10:50 +01:00
Linus Rath e4338ac47d feat: add the Search in setting to Message list settings #1485 2026-11-01 17:44:15 +01:00
Linus Rath aaafe428fe test: expect the full send options in the Pro compose draft account test #523 2026-11-01 17:40:53 +01:00
Linus Rath 300d49a917 test: give the push prompt test's settings store mock the calendar sync bridge 2026-11-01 17:38:58 +01:00
Linus Rath 1b2281a4fc fix: stop the sidebar re-rendering on every message open #1486 2026-11-01 17:36:29 +01:00
VasilisNtovolos 2a9a02b782 fix: cancel pending attachment uploads when discarding a draft 2026-11-01 18:00:10 +02:00
Linus Rath 4b60fcc1e6 fix: make the offline outbox never send twice, never lose mail silently and never skip a plugin #523
The review of offline mode found ways to send a message twice, to lose
unsent mail without a word, and to send mail without its signing,
encryption or check plugin. This fixes them and the smaller findings:

- each outbox message is taken for sending in one database transaction
  under a Web Lock per account; only a failure before the submission
  request (SendNotStartedError from the client) puts it back, any other
  one marks it "may have gone out"; read-backs after the submission no
  longer fail a send; a send of a closed tab turns uncertain after a minute
- every sign-out the user didn't confirm names the deleted messages on
  the sign-in page, or in a toast when another account stays signed in
- nothing is queued while an enabled plugin isn't running (after a start
  without the network none can); the composer says why
- the outbox waits for a fresh policy and holds messages the rules have
  since made stricter (a required label, a required send check)
- another tab switching offline mode off sticks: only switching it on
  may create the database
- only attachments of kept messages are kept, filed with their message,
  deleted with it and under the cap between syncs; file names and types
  are sealed; folders that went away leave the scope, and a folder that
  couldn't be asked keeps its mail without holding the others back
- a group scope that forbids offline mode waits until the account's
  groups are known; one server down no longer holds another's mail
- an offline start only when the server is really unreachable, and the
  real sign-in follows by itself once it answers
- the service worker files pages and chunks under the build that served
  them, and the shell list of another build isn't kept under this one
- a raw send counts as the composer's only from the plugin running its
  takeover, for that identity
- errors and refusals are in all languages; the banner tells "offline"
  from "server can't be reached"; outbox buttons name their message;
  changes and messages go in the order they were made
2026-11-01 14:19:54 +01:00
Linus Rath 52188f54d6 Merge branch 'feat/enterprise-pack' into feat/enterprise-pack-f 2026-11-01 13:50:22 +01:00
Linus Rath e9b235bab2 Merge branch 'main' into feat/enterprise-pack
# Conflicts:
#	components/admin/admin-shell.tsx
#	lib/admin/outgoing-hosts-registry.ts
#	lib/admin/reachable-hosts.ts
#	scripts/lite/build.mjs
#	stores/policy-store.ts
2026-11-01 13:46:59 +01:00
Linus Rath 8b23c81372 fix: let the new build's service worker take over once a tab runs that build #523 2026-11-01 12:38:59 +01:00
Linus Rath da4c880c5f fix: open the offline outbox from the banner without leaving the page #523 2026-11-01 12:14:50 +01:00
Linus Rath 5fa1722392 feat: let admins forbid offline mode 2026-11-01 11:46:11 +01:00
Linus Rath db5ac82f53 feat: keep recent mail on this device and send mail written offline #523
Settings > Backup & reset gets "Keep mail on this device", off until the
user turns it on in this browser. While it is on:

- the JMAP client hands the server's answers to an encrypted cache in
  IndexedDB (AES-GCM, non-extractable key) and answers from it when the
  network is gone: the folder list, the last 30 days of the Inbox and of
  the folders the user opened, bodies and attachments, at most 250 MB,
  oldest out first; a background sync keeps it current
- read, flag, tags and moves made offline are queued and sent in order
  when the server answers again; deleting for good and emptying a folder
  are refused offline
- the composer, quick reply and the S/MIME and PGP plugins' sends that
  complete the composer's go to an outbox once every step up to the
  transport ran (checks, label, signature, plugin send checks); only the
  finished send waits, with files attached offline
- the service worker keeps this build's app shell, so the app also
  starts offline from the kept session and the last policy
- a full sign-out, the idle sign-out and signing one account out delete
  it, a sign-out the user starts asks first when mail is unsent, and the
  login page names what an automatic sign-out deleted; a policy fetch
  that forbids it (devices.noOffline) wipes that account

Not in Lite.
2026-11-01 11:46:11 +01:00
Linus Rath 91be465cbc feat: version the service worker by build and offer a reload after a deploy 2026-11-01 11:13:31 +01:00
Linus Rath a480ddb6d1 Merge branch 'feat/enterprise-pack-e' 2026-11-01 10:52:08 +01:00
Linus Rath 465320dbfb test: say no plugin checks sends in the composer draft-login test
The test's mocked onBeforeEmailSend had no size, so the composer took
it for a listening send check and built the check's message, which
reads the sending login's identities from a client the test mocks
without getIdentities; the send stopped there. The real bus without a
plugin has size 0, which the mock now says too.
2026-11-01 10:51:54 +01:00
Linus Rath 0401352e6e Merge branch 'feat/enterprise-pack-d'
# Conflicts:
#	components/email/thread-conversation-view.tsx
#	lib/admin/outgoing-hosts-registry.ts
2026-11-01 10:48:21 +01:00
Linus Rath 27e4f0cbac test: cover the file type the composer tells upload checks 2026-11-01 10:09:20 +01:00
Linus Rath 0c8d4ad93e fix: hold sends until required send checks have started, and check what really goes out
- The message for send checks is built after waiting for required
  checks that are still starting: a send right after sign-in gave them
  no external recipients and no file types.
- A plugin's forward is held too while a required check is down, also
  with no plugin listening.
- A plugin the admin forces on that hasn't reached this browser yet (a
  new device, a failed plugin sync) counts as starting.
- A check that stopped working says to reload or tell the admin.
- The files that were checked are the ones sent, and recipients a
  plugin adds after the check are checked again.
- A file Bulwark couldn't read is marked unreadable; a text file
  starting with "MZ" is text, Java and Android apps are told from ZIPs.

Changed assertions: runPluginSendCheck takes a builder and reports
guard-loading or guard-failed instead of guard-down; the composer test
of an auto-disabled guard expects the stopped_working text; the sniff
tests give programs a zero byte, as real ones have, and expect
unreadable on a file that can't be read.
2026-11-01 10:02:58 +01:00
Linus Rath fbf85972c5 fix: check links in plain-text mail and the address the browser really opens
Plain-text bodies render in the page, not in the body iframe, so their
links opened without the link check. Plugins now get each link as the
browser parses it (new URL(href).href) and that same string opens, so a
link check can't judge one host while another opens. With no link check
listening, clicks and middle-clicks stay with the browser as before.
2026-11-01 09:51:00 +01:00
Linus Rath c11d8ade44 test: cover the plugin, .eml preview, drag-out, export file and install banner paths of the device policies 2026-11-01 09:50:35 +01:00
Linus Rath a4b140b651 fix: keep out-of-office dates right when the time zone setting arrives or changes after the page opened 2026-11-01 09:48:58 +01:00
Linus Rath 9f8d134e85 fix: keep pictures in messages and the Files image preview from being saved under No downloads, and say the mobile app's notifications aren't covered yet 2026-11-01 09:47:28 +01:00
Linus Rath b58dc1d66b fix: apply the device policy and retention line of the account whose folder is open, and keep Copy to account from moving mail out of a restricted account 2026-11-01 09:42:19 +01:00
Linus Rath 61733d839f fix: show an announcement that arrives after its start, once in the Pro shell, and keep it closed when only its times move
- The banner judged its start and end by the time it was mounted, so an
  announcement fetched later than its start never showed in that tab.
- The Pro shell shows it once above its panes; email and folder tabs had
  none and split panes showed it twice.
- Screen readers get it from a live region that fills a moment after it
  is in the page; text present when a live region appears isn't read out
  reliably. The tests that checked the strip's role now check that region.
- Moving the start or end no longer shows a closed announcement again;
  the lib test that expected a new end time to reset it now expects the
  opposite.
2026-11-01 09:39:36 +01:00
Linus Rath e80f5ade81 feat: let admins turn off downloads, export, printing and the install prompt, and add a watermark
Organisation > Devices now sets policy.json `organisation.devices`, each
switch off by default and scoped per domain or group:

- No downloads: attachments and files only preview (reader, conversation
  view, Pro tab, list chips, .eml previews, the Files app). Download,
  Download all, Open in new tab, Save to Files, drag-out, the browser's
  PDF viewer (pdf.js instead) and media download controls go away.
- No export: no .eml export, View source, message drag-out, or folder and
  account export; a running export stops and its file is deleted when
  the switch turns on. Import stays.
- No printing: no Print buttons in mail, calendar and contacts; Ctrl+P
  prints a note; the reader frame prints blank.
- No install prompt: no card, and the browser's own banner is held back.
- Watermark: the user's address and the date over the reader,
  previews and every printout (mail, calendar, contacts, plugins).

A message follows its own account's policy; what isn't about one message
follows the strictest signed-in account. Every user path hides its
button, and the anchor and new-tab helpers refuse as a backstop
(lib/download-guard.ts), never the blob readers. The plugin APIs
`ui.downloadFile` and `ui.print` refuse too, and the office editor frame
loses `allow-downloads`.

Two assertions in components/mail/__tests__/blob-routing.test.tsx now
expect `{ kind: 'export' }` as the fifth argument of downloadBlob for an
.eml export: the export says what it is, so the backstop checks "No
export" rather than "No downloads" for it.
2026-11-01 08:52:34 +01:00
Linus Rath e73a1b375f feat: let link-check plugins reach an admin-set service with no third-party traffic
The plugin host tests compared api.host.features with an object of two
flags; they now include the new noThirdPartyTraffic flag.
2026-11-01 08:39:35 +01:00
Linus Rath b3369c7e78 feat: send every link click through the link check 2026-11-01 08:31:27 +01:00