doEmailGet asked the signed-in account for every id, so a message in a
folder shared from another account came back as null even though it was
in the list. A message in the loaded list is now read from the account
that owns it, through resolveEmailBlobContext like attachment downloads.
getAttachment and getRaw keep reading from the signed-in account only.
Fixes#1273
Expanding a conversation in the message list (row click, expand chevron,
or the `x` shortcut) and clicking a row in a Pro folder tab marked the
messages read straight away. They ignored "Mark as read: Never" and any
delay, which the reading pane and the conversation view follow.
Route them through one helper, scheduleAutoMarkAsRead: -1 never marks,
0 marks at once, any other value marks after that many milliseconds and
returns a cancel function.
- New store action autoMarkExpandedThreadAsRead keeps one pending timer
per thread key. Collapsing the thread, or collapsing all threads, drops
it. Both expansion paths (EmailList and the `x` handler in MailApp) use
it.
- MailApp's handleEmailSelect drops the pending mark of every expanded
thread other than the one the newly opened message belongs to, through
cancelAutoMarkThreadAsRead. Moving on with `j`/`k` or a click no longer
lets the delayed mark land on a conversation the user has left. The
thread stays expanded.
- ProFolderTabBody schedules the row mark through the helper and drops a
pending one when another row is opened or the tab unmounts.
markThreadAsRead resolved each message through resolveEmailActionContext
but kept only the client and dropped the accountId, so batchMarkAsRead
always wrote to the reaching client's own account.
That hit two cases where the client and the owning account differ:
- a shared mailbox opened directly from the "Shared" sidebar section,
whose owner comes from the selected shared folder;
- a shared source in the unified view, whose messages are stamped with
sourceAccountId but reached through the login client.
The Email/set then went to the login's own account. The shared messages
stayed unread, and since JMAP ids are only unique within an account, a
message in the user's own account with the same id could be marked read
instead.
Group the ids by client and owning account, and pass the accountId to
batchMarkAsRead, as the batch and single-message paths already do.
With several accounts connected, the composer treated every account's
identities as "own" when deciding whether a message was self-sent (#703).
A message that account B sent to account A therefore looked self-sent
when replying from A, so the reply was addressed to the original To -
account A itself - and From was switched to B.
Self-sent now means "sent by the account holding the original":
buildReplyRecipients takes an optional selfSentEmails list (defaulting to
ownEmails, so single-account behaviour is unchanged), and the composer
passes the source account's identities there and to the From selection.
Reply-all still drops every connected account's addresses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>