From c62a335424c541dad26a95275d28deadf81ee13f Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 19 Feb 2026 13:45:20 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20email=20links=20using=20relative=20paths?= =?UTF-8?q?=20=E2=80=94=20prepend=20baseUrl=20for=20absolute=20URLs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Relative linkUrl paths (e.g. /jury/competitions) were passed as-is to email templates, causing email clients to interpret them as local file protocols (x-webdoc:// on macOS). Now prepends NEXTAUTH_URL to any relative path before sending. Co-Authored-By: Claude Opus 4.6 --- src/server/services/in-app-notification.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/server/services/in-app-notification.ts b/src/server/services/in-app-notification.ts index 7ce271b..43f6434 100644 --- a/src/server/services/in-app-notification.ts +++ b/src/server/services/in-app-notification.ts @@ -426,6 +426,10 @@ async function maybeSendEmailWithSetting( return } + // Ensure linkUrl is absolute for emails (relative paths break in email clients) + const baseUrl = process.env.NEXTAUTH_URL || 'https://portal.monaco-opc.com' + const absoluteLinkUrl = linkUrl && linkUrl.startsWith('/') ? `${baseUrl}${linkUrl}` : linkUrl + await sendStyledNotificationEmail( user.email, user.name || 'User', @@ -433,7 +437,7 @@ async function maybeSendEmailWithSetting( { title, message, - linkUrl, + linkUrl: absoluteLinkUrl, metadata, }, emailSetting.emailSubject || undefined