From 26aec1c5afc397bf7da5c6cbb7854c3fa8a8e76f Mon Sep 17 00:00:00 2001 From: rasm-its Date: Sat, 22 Aug 2026 22:50:31 +0200 Subject: [PATCH] graph: sender display name from panel (address stays sender, no Send-As) --- src/modules/email/graphAdapter.ts | 35 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/modules/email/graphAdapter.ts b/src/modules/email/graphAdapter.ts index 3b71902..ccf1ab4 100644 --- a/src/modules/email/graphAdapter.ts +++ b/src/modules/email/graphAdapter.ts @@ -115,18 +115,19 @@ export const graphAdapter = return { error: 'Graph is not configured (missing env vars).', sent: false } } - // The panel's from-address is used as Reply-To, NOT as the message From. + // Display name on the From, WITHOUT triggering Send-As. // - // Why: app-only Graph sends from GRAPH_SENDER's mailbox. If we also set a - // `from` that differs from that mailbox, Exchange demands "Send As" - // permission on it and rejects with ErrorSendAsDenied otherwise. So we - // never override `from` — Graph stamps the mail as GRAPH_SENDER (the - // mailbox we legitimately own) — and route replies to the panel address - // via Reply-To. Recipients see the mail from forms@… but replying reaches - // the real destination. No Send-As needed. + // The trick: we may set a `from` as long as its ADDRESS stays the sender + // mailbox (GRAPH_SENDER) — only the display NAME changes. Exchange only + // demands Send-As when the from ADDRESS differs from the mailbox, so a + // same-address / custom-name From is allowed and gives each project its + // own sender label (e.g. "Kancelaria Kędzierski") over the shared mailbox. + // + // The panel's from-address becomes Reply-To (so replies reach the client), + // and the panel's from-name becomes the sender display name. const panel = await getSiteIntegrations(payload) const replyToAddress = panel.smtpFromAddress || undefined - const replyToName = panel.smtpFromName || undefined + const senderName = panel.smtpFromName || undefined const to = toRecipients(message.to) if (to.length === 0) { @@ -142,14 +143,7 @@ export const graphAdapter = const replyTo = message.replyTo ? toRecipients(message.replyTo as SendEmailOptions['to']) : replyToAddress - ? [ - { - emailAddress: { - address: replyToAddress, - ...(replyToName ? { name: replyToName } : {}), - }, - }, - ] + ? [{ emailAddress: { address: replyToAddress } }] : [] const graphMessage: Record = { @@ -158,7 +152,12 @@ export const graphAdapter = toRecipients: to, ...(message.cc ? { ccRecipients: toRecipients(message.cc) } : {}), ...(message.bcc ? { bccRecipients: toRecipients(message.bcc) } : {}), - // NO `from` — Graph uses GRAPH_SENDER's own mailbox, so no Send-As. + // From with the sender's OWN address (no Send-As) plus an optional + // display name from the panel. Omit entirely when no name is set — + // Graph then uses the mailbox's default name. + ...(senderName + ? { from: { emailAddress: { name: senderName, address: env.sender } } } + : {}), ...(replyTo.length > 0 ? { replyTo } : {}), }