Files
webmail/lib/offline/lost.ts
T
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

43 lines
1.2 KiB
TypeScript

/**
* Messages of the offline outbox (#523) that a sign-out deleted unsent.
* Every sign-out the user didn't confirm for that (the idle and maximum
* session limits, a refused token renewal, an account removed in another
* way) names them: on the sign-in page, or in a toast when another account
* stays signed in. Kept in sessionStorage (this tab only, gone with it), and
* only the subjects.
*/
const KEY = 'bulwark-offline-lost';
const MAX = 20;
export function rememberLost(subjects: string[]): void {
if (subjects.length === 0) return;
try {
const before = readLost();
window.sessionStorage.setItem(KEY, JSON.stringify([...before, ...subjects].slice(-MAX)));
} catch {
/* storage unavailable */
}
}
function readLost(): string[] {
try {
const raw = window.sessionStorage.getItem(KEY);
const parsed = raw ? JSON.parse(raw) : [];
return Array.isArray(parsed) ? parsed.filter((s): s is string => typeof s === 'string') : [];
} catch {
return [];
}
}
/** The subjects, once (the sign-in page shows them and they go). */
export function consumeLost(): string[] {
const lost = readLost();
try {
window.sessionStorage.removeItem(KEY);
} catch {
/* storage unavailable */
}
return lost;
}