Commit Graph
1260 Commits
Author SHA1 Message Date
Linus Rath a3d4853974 fix: hide out of office when the account lacks the vacation permission #1488 2026-11-01 17:48:11 +01:00
Linus Rath 3c2eb9bffa feat: let a new search look only in the open folder #1485 2026-11-01 17:43:51 +01:00
Linus Rath 42a09f573d fix: let the Lite host scan accept the licence links in the PST worker 2026-11-01 17:26:31 +01:00
Linus Rath 9ce7927627 fix: keep the old build's offline files from coming back after a deploy #523 2026-11-01 14:49:14 +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 b196455720 test: give the plugin vacation API test the client methods the out-of-office calendar sync reads
The out-of-office calendar block (package B) syncs from the vacation store, so the plugin vacation API now reaches client.getAccountId and supportsCalendars. The real client has both; the test's mock client didn't, so two cases threw. The mock gains them; no assertion changed.
2026-11-01 13:25:01 +01:00
Linus Rath 1769de5b93 fix: let a new build's service worker take over while the old one still fetches the offline shell #523 2026-11-01 13:08:59 +01:00
Linus Rath 0b51a06fbc fix: take over with the new build's service worker also when it was still installing #523 2026-11-01 12:56:28 +01:00
Linus Rath eb26219b3c feat: send telemetry error counts within a minute when an admin turns on instant mode 2026-11-01 12:55:58 +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 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 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 2cd1baa594 feat: let plugin frames run work they can stop in a worker 2026-11-01 10:07:41 +01:00
Linus Rath 6b3a220d44 fix: let only a server the admin typed through with no third-party traffic 2026-11-01 10:06:00 +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 6e931a731c fix: keep the server-side device policies on when a login's session or the policy can't be read 2026-11-01 09:44:03 +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 50bb4e4c37 fix: keep secret plugin settings out of plugins when the user is also signed in as admin 2026-11-01 08:40:32 +01:00
Linus Rath 140db2cf8f feat: turn printing and export off in the office editor under the device policies 2026-11-01 08:40:03 +01:00
Linus Rath adbec718ef feat: let admins keep sender and subject out of push notifications, enforced by the server
The push preview route now reads the device policy of the login it
serves (its scopes worked out from the login's own JMAP session, every
non-personal account counted as a group) and under
`pushWithoutContent` asks the mail server for the message's ids only,
so sender, subject and text never reach the notification. The service
worker shows "New mail" for such an answer. A policy that can't be read
counts as on.

The three existing push preview route tests now mock the config manager
with the default policy: without it the route can't read a policy in the
test environment and holds the text back, which those tests didn't mean
to cover. No assertion changed.
2026-11-01 08:40:02 +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 c004587158 feat: keep sending blocked while a required send check isn't running 2026-11-01 08:22:32 +01:00
Linus Rath edf619a19d feat: give send-check plugins the authored text, external recipients and attachment types 2026-11-01 08:16:39 +01:00
Linus Rath 47784cc07a feat: offer admin out-of-office templates and show the absence dates in the user's time zone 2026-11-01 08:02:39 +01:00
Linus Rath b99003956a feat: show an admin announcement across the apps 2026-11-01 07:51:46 +01:00
Linus Rath 2a952f4b72 Merge branch 'feat/enterprise-pack-c'
# Conflicts:
#	lib/sign-out-cleanup.ts
2026-11-01 07:39:30 +01:00
Linus Rath ebb33619a0 Merge branch 'feat/enterprise-pack-a' 2026-11-01 07:36:59 +01:00
Linus Rath 1bb2a85de4 fix: translate the turned-off link note and tidy the label and phishing texts
The VS-NfD warning test now expects "BSI-approved products", the corrected wording.
2026-11-01 07:14:10 +01:00
Linus Rath 13c57414a2 fix: report phishing per account from every view and keep a reported message's links off everywhere
- Pro tabs stamp a message of another login or a shared account with
  where it came from, so the report and the move use its account.
- A selection across accounts names every address its reports go to,
  and Undo says how many messages came back.
- A message the list doesn't hold runs the plugins' spam hooks too, and
  every open view shows a reported message as reported at once.
- A reported message hides its unsubscribe banner, and links are off in
  its attachment previews.
- Search results and All mail don't offer reporting the user's own sent
  mail; the Mountain View selection bar offers it.
- The focus goes back to the button that opened the menu.
- ARF names the delivered-to address (or leaves it out), says binary for
  bare line breaks and long lines, and refuses a message bigger than the
  server's upload limit before downloading it.

The phishing tests that compared one address now compare the list of
addresses, and the ARF builder test passes the encoding, not a flag.
2026-11-01 07:07:30 +01:00
Linus Rath cbd23db2fe fix: give mail import and export their own settings section and name the upload limit as the server does
- Settings > Backup & reset gets a Mail files section for Import mail
  and Export all mail, instead of sitting under settings backup.
- The pause message names Stalwart's 50000000-byte quota as 50 MB, not
  48 MB, and the dialog and settings texts mention .ost files.
- The old import's leftovers go: expandImportableEmails and
  EML_IMPORT_ACCEPT in lib/eml-import.ts, and the strings
  email_viewer.import_email, mailbox_context_menu.import_email and
  notifications.import_email_success/_error in all 30 locales.

lib/__tests__/eml-import.test.ts loses the tests of the removed
functions; its #891 checks that an .eml and an .eml in a ZIP keep their
Date header now run against the import's own sources.
2026-11-01 07:05:02 +01:00
Linus Rath f3440d127b fix: share free/busy only with an address the directory names as a group 2026-11-01 06:57:24 +01:00
Linus Rath 85deb006a8 fix: keep plugin raw sends from dropping or forging the classification label
Raw sends (api.jmap.sendRaw and submitRaw) now always lose label headers
a plugin wrote while the organisation uses labels. A crypto takeover is
matched to its raw send by a labelToken the composer puts in the
onComposeSend request (plugins that don't pass it back are matched by
identity, and refused when two takeovers are open), not by comparing
subjects. A raw send outside a takeover gets the default label, or is
refused when a label is required. The extra header is folded on the raw
path. The takeover code moves to lib/outgoing/classification-raw.ts;
the old test that let a raw send outside a takeover through unlabelled
now expects the forged header to be removed.
2026-11-01 06:52:44 +01:00
Linus Rath 870881c57e fix: fetch a company calendar once for everyone at a time and pause after a failure 2026-11-01 06:51:17 +01:00
Linus Rath 3ef16f602e fix: keep a message's label through Undo send and take over labels only from internal senders
A sent message brought back by Undo, Cancel and edit or edit-as-new
reopened with the default label, because only drafts carried the
X-Bulwark-Label marker; it now falls back to the SIO-Label it went out
with. A reply, quick reply or plugin forward takes over the original's
label only when an internal sender set it and never one below the
default, since anyone outside can write the header. The tests written
for the earlier rule (any received label counts) now pass an internal
sender, which is why their originals changed.
2026-11-01 06:48:01 +01:00
Linus Rath 88a5c3e5d5 fix: take company calendar events away when the feed is gone or the account signs out 2026-11-01 06:44:57 +01:00
Linus Rath cbae82b2f0 fix: keep the out-of-office event in step when the reply changes on another device
The event counted as Bulwark's only while its times matched the record
in this browser's settings, so a reply switched off on a phone, by a
delegate, in Lite or with settings sync off left colleagues seeing a
busy event for a cancelled absence. It now also counts as Bulwark's
when it sits on the reply's dates from before the change, and it
carries the keyword bulwark-out-of-office so a device without a record
takes it over when the reply is loaded. Each account gets its own
pending sync.
2026-11-01 06:42:37 +01:00
Linus Rath c89c1cb36c fix: fetch company calendars for the active account when several are signed in 2026-11-01 06:37:50 +01:00
Linus Rath 8d48f98261 fix: keep failed messages for the next import run and stop an import that can't go on
A message that failed for a passing reason (a dropped connection, a
server error, an expired token) used to count as done, so continuing
the import skipped it for good, and a slow upload followed by a cancel
imported the messages after it twice.

- The checkpoint keeps every message that is done, also past a gap,
  and the next run of the same import tries only the rest again.
- Ten failures in a row, a full mailbox (overQuota) or a refusal
  (forbidden) stop the import with a message instead of going through
  the whole file.
- An upload without an answer pauses the import instead of failing the
  message: 30 seconds, then until the upload window ends.
- Email/import, the export's Blob/get and folder listing pass the
  client's own 429 pause by, and a 429 on them doesn't pause the rest
  of the app.
- Signing out stops the job of that account only, writes no checkpoint
  and imports nothing more afterwards; another account's sign-out
  leaves the job alone.
- One tab imports a file at a time (Web Locks), and Import waits until
  the dialog knows whether an earlier run can be continued.

The import dialog tests now wait for the Import button to be enabled
before clicking it, since it stays off during that lookup.
2026-11-01 06:37:08 +01:00
Linus Rath 0fcdc2ece4 fix: reach a company calendar on a private address only when its host names the intranet 2026-11-01 06:35:56 +01:00
Linus Rath 9c60140e49 fix: write the SIO-Label header without a doubled space after the colon 2026-11-01 06:01:20 +01:00
Linus Rath 36160f9fbd fix: answer for a group mailbox as the group when the group address is one of your identities #634 2026-11-01 06:00:43 +01:00
Linus Rath 3bd8e83d60 feat: show company calendars set by the admin 2026-11-01 05:41:34 +01:00
Linus Rath 1c7f81bcc6 feat: pick a classification label in the composer and stamp it on sent mail 2026-11-01 05:33:12 +01:00
Linus Rath 15f0bd198c feat: export a folder or the whole account as mbox or ZIP 2026-11-01 05:28:58 +01:00
Linus Rath a8f9d81337 feat: block the calendar while the out-of-office reply is on 2026-11-01 05:19:07 +01:00
Linus Rath 877198a4bf feat: answer invitations in a calendar shared with you as its owner #634 2026-11-01 05:05:12 +01:00