diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index fda1d125..0c5a51a4 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -1551,6 +1551,7 @@ export default function Home() { mode={pendingDraft?.mode ?? composerMode} replyTo={pendingDraft?.replyTo ?? (selectedEmail ? { from: selectedEmail.from, + replyToAddresses: selectedEmail.replyTo, to: selectedEmail.to, cc: selectedEmail.cc, bcc: selectedEmail.bcc, diff --git a/components/email/email-composer.tsx b/components/email/email-composer.tsx index a32d2845..fe07bc4a 100644 --- a/components/email/email-composer.tsx +++ b/components/email/email-composer.tsx @@ -77,6 +77,7 @@ interface EmailComposerProps { mode?: 'compose' | 'reply' | 'replyAll' | 'forward'; replyTo?: { from?: { email?: string; name?: string }[]; + replyToAddresses?: { email?: string; name?: string }[]; to?: { email?: string; name?: string }[]; cc?: { email?: string; name?: string }[]; bcc?: { email?: string; name?: string }[]; @@ -107,13 +108,15 @@ export function EmailComposer({ // Initialize with reply/forward data if provided const getInitialTo = () => { if (!replyTo) return ""; + // RFC 5322: use Reply-To header if present, otherwise fall back to From + const replyTarget = replyTo.replyToAddresses?.length + ? replyTo.replyToAddresses.filter(r => r.email).map(r => r.email).join(", ") + : replyTo.from?.[0]?.email || ""; if (mode === 'reply') { - const email = replyTo.from?.[0]?.email || ""; - return email ? email + ', ' : ""; + return replyTarget ? replyTarget + ', ' : ""; } else if (mode === 'replyAll') { - const from = replyTo.from?.[0]?.email || ""; const originalTo = replyTo.to?.filter(r => r.email).map(r => r.email).join(", ") || ""; - const combined = [from, originalTo].filter(Boolean).join(", "); + const combined = [replyTarget, originalTo].filter(Boolean).join(", "); return combined ? combined + ', ' : ""; } return ""; diff --git a/lib/jmap/client.ts b/lib/jmap/client.ts index 154d4125..b3ecc7e3 100644 --- a/lib/jmap/client.ts +++ b/lib/jmap/client.ts @@ -1648,19 +1648,28 @@ export class JMAPClient implements IJMAPClient { } let finalIdentityId = identityId; - if (!finalIdentityId) { + let identityReplyTo: EmailAddress[] | undefined; + { const identityResponse = await this.request([ ["Identity/get", { accountId: this.accountId }, "0"] ]); - finalIdentityId = this.accountId; + if (!finalIdentityId) { + finalIdentityId = this.accountId; + } if (identityResponse.methodResponses?.[0]?.[0] === "Identity/get") { - const identities = (identityResponse.methodResponses[0][1].list || []) as { id: string; email: string }[]; + const identities = (identityResponse.methodResponses[0][1].list || []) as Identity[]; if (identities.length > 0) { - const target = fromEmail || this.username; - const matchingIdentity = identities.find((id) => id.email === target) - || (!target.includes('@') ? identities.find((id) => id.email.split('@')[0] === target) : undefined); - finalIdentityId = matchingIdentity?.id || identities[0].id; + if (!identityId) { + const target = fromEmail || this.username; + const matchingIdentity = identities.find((id) => id.email === target) + || (!target.includes('@') ? identities.find((id) => id.email.split('@')[0] === target) : undefined); + finalIdentityId = matchingIdentity?.id || identities[0].id; + identityReplyTo = matchingIdentity?.replyTo || identities[0].replyTo; + } else { + const matchedIdentity = identities.find((id) => id.id === identityId); + identityReplyTo = matchedIdentity?.replyTo; + } } } } @@ -1668,6 +1677,7 @@ export class JMAPClient implements IJMAPClient { // Always create a new email with the final body content const emailCreate: Record = { from: [{ ...(fromName ? { name: fromName } : {}), email: fromEmail || this.username }], + replyTo: identityReplyTo?.length ? identityReplyTo : undefined, to: to.map(email => ({ email })), cc: cc?.map(email => ({ email })), bcc: bcc?.map(email => ({ email })),