Extend the cross-account blob routing beyond download/preview to every blob
fetch in the message viewer, so a message opened from a different account in the
unified / All-Mail view renders and exports correctly instead of 404ing against
the active account:
- inline cid: images, drag-to-desktop, attachment thumbnails, the "download all"
zip bundle, and the S/MIME / TNEF / embedded-rfc822 blob reads now use a
resolved blobClient (getClientForAccount(sourceClientAccountId)) and the owner
blobAccountId (sourceAccountId), computed once from the open message's source;
- fetchBlobAsObjectUrl / fetchBlobArrayBuffer / fetchBlob calls pass the
accountId (the client methods gained the param in the previous commit);
- non-cross-account behaviour is unchanged (blobClient === active client).
Extends 10-attachments with an inline-image case (verified to fall back to the
placeholder without the routing). The SMTP helper can now send multipart/related
inline images.
Blobs are scoped per JMAP account, but the attachment download/preview path
always used the active account's client and accountId. Opening a message from a
different account in the unified / All-Mail view and downloading (or previewing)
an attachment therefore 404'd against the active account.
Route the blob fetch to the message's source instead:
- resolveBlobSource() picks the owning login's client
(getClientForAccount(sourceClientAccountId)) and the owner accountId
(sourceAccountId) for delegated/shared blobs, in the unified view;
- handleDownloadAttachment + the attachment-preview handlers use it;
- downloadBlob / fetchBlobAsObjectUrl / fetchBlobArrayBuffer gain an accountId
param (getBlobDownloadUrl/fetchBlob already had one).
Adds 10-attachments: an attachment on another account's All-Mail message
downloads with the correct bytes (verified to fail without the routing).
Add an end-to-end integration harness that runs the webmail against a real
Stalwart mail server in Docker and drives it with Playwright, focused on the
mail/folder synchronisation behaviour (unread/total counters, folder-list
sync, account-scoped Unified Mailbox) that the unified-mailbox work touches.
- integration/ stack: Stalwart (declarative bootstrap: alice/bob/carol,
submission + IMAP listeners, permissive CORS) + webmail (dev mode, so the
browser's plaintext cross-origin JMAP calls aren't blocked by the prod CSP).
- Helpers: dependency-free SMTP submit client, JMAP client for seeding /
inspecting server state, and page helpers (login, add/switch account,
locale-independent folder-counter reads).
- Specs: login, single-account sync (receive/read/move/delete/folder-create/
burst) and multi-account (per-account isolation + cross-account Unified
Inbox aggregation + background-account delivery). 12 tests, all green.
- Add focused data-testid hooks to the mail UI (folder rows + counters, email
list items, account switcher, composer) for stable selectors.
- Exclude examples/ and integration/ from tsconfig/eslint/.dockerignore.