OAuth authorization-server metadata lives at the origin root (RFC 8414), but
getRequiredConfig() derived the discovery URL straight from JMAP_SERVER_URL. When
that is the session URL (for example https://mail.example.com/jmap/session, a
common setup so the client can skip the 307 redirect a preflighted CORS request
cannot follow), discoverOAuth fetched
https://mail.example.com/jmap/session/.well-known/oauth-authorization-server,
got a 404, and token refresh failed with "OAuth token endpoint not found", so the
session was dropped after one access-token lifetime.
Strip a trailing session path (/jmap/session or /.well-known/jmap, plus any query
or fragment) before discovery. A plain server root is unchanged, and only the
session suffix is removed, so a real base path prefix is kept.
Adds oauth-discovery-base.test.ts driving getRequiredConfig; the normalization
cases fail without the fix.
The same missing dir="auto" as the read view, in the two other places
that build an email document.
thread-conversation-view builds a full document for each card's iframe
and its <body> had no direction, so a thread of right-to-left mail read
left-to-right in the one view that shows several messages at once.
eml-preview hands srcDoc a fragment rather than a document, so the
<body> is the browser's implicit one and cannot be annotated at all.
The wrapper the fragment already needs carries dir="auto" instead: a
<div> around sanitized HTML, and the existing <pre> for plain text.
Neither changes layout - the implicit body and its default margin stay
exactly as they were.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KwXZEwxijHRbfobfXmcK2
On a shared, group or aliased mailbox every reply, reply-all and forward
went out as `identities[0]` - the account owner - whichever mailbox was
open. `autoSelectReplyIdentity` fused two behaviours: matching one of the
user's OWN identities, which never rewrites `From:`, and the domain
catch-all, which puts an address they have not configured into `From:`.
Only the first is safe for everyone, so it is now unconditional; the
rewrite stays behind the setting, which is what its description promises.
`findReplyIdentityId` already implemented that match and was referenced
only from tests.
`forward` is admitted to the match - it was excluded, so a forward from a
shared mailbox went out as the owner - but never takes the rewrite: a reply
continues a thread whose participants know the addressing, while a forward
introduces a rewritten From to a recipient the user just typed. Quick reply
matches own identities only, having no From row to show or correct a
rewrite, and now falls back to the primary's signature as the composer
does, so a shared-mailbox quick reply is still signed.
`findReplyIdentityId` now scans recipients in To, Cc, Bcc order rather than
scanning identities, and prefers an untagged identity over a differently
tagged sibling. Scanning identities let their order decide, and
`sortIdentities` puts the login's own address first - so `To: team@,
Cc: you@` replied as you, the case this is meant to fix.
Automatic selection is restricted to the active account: `composerClient`
follows the chosen identity, and a reply or forward still carries blobIds
only its own account's server can resolve. The dropdown still offers every
account's identities to pick by hand.
New messages are deliberately left gated: `composeFromAccountEmail` falls
back to `AccountEntry.email`, written once at first login, so resolving it
unconditionally would override a user-chosen default sender identity (#507).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`ProComposeTabBody` rendered `<EmailComposer>` without
`composeFromAccountEmail`; only the standard shell in
`components/mail/mail-app.tsx` passed it, so `mode === 'compose'` resolved
`findComposeIdentityId(identities, undefined)` to null and every new message
in the Pro shell defaulted to the account owner even with a shared folder
open. That covered the whole compose surface there, since the Pro shell
hoists every "show composer" intent - `mailto:` links included - into a tab.
Resolved exactly as the standard shell does, so both share one rule, but
read once at mount: a tab body stays mounted while the tab lives, so
subscribing to the mailbox list would re-render the composer and its editor
on every counter refresh.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>