From 80dbc53f89283f1249e0296da0b800e4e729dca4 Mon Sep 17 00:00:00 2001 From: ignatiusm Date: Tue, 4 Aug 2026 15:57:30 +1200 Subject: [PATCH 1/2] Add test for HOSTNAME parsing in mailer --- .../src/controllers/MailerController.test.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/application/backend/src/controllers/MailerController.test.ts b/application/backend/src/controllers/MailerController.test.ts index 86d41ac7..57f1e4f0 100644 --- a/application/backend/src/controllers/MailerController.test.ts +++ b/application/backend/src/controllers/MailerController.test.ts @@ -92,3 +92,33 @@ describe('MailerController', () => { }) }) }) + +// Test due to nodemailer moving to more strict sender address parsing +describe('Mailer Configuration', () => { + const originalHostname = process.env.HOSTNAME + + beforeEach(() => { + jest.resetModules() + }) + + afterEach(() => { + process.env.HOSTNAME = originalHostname + }) + + it('should strip http:// and ports from HOSTNAME in fromAddress', async () => { + // non RFC-compliant environment variable + process.env.HOSTNAME = 'http://localhost:5173' + + const mailerModule = await import('../utils/mailer') + + expect(mailerModule!.fromAddress).toBe('CTRL ') + }) + + it('should handle plain domains without protocols', async () => { + process.env.HOSTNAME = 'production-domain.com' + + const mailerModule = await import('../utils/mailer') + + expect(mailerModule!.fromAddress).toBe('CTRL ') + }) +}) From f8be9180f5ae87e6880eec558ec3610892a18494 Mon Sep 17 00:00:00 2001 From: ignatiusm Date: Tue, 4 Aug 2026 16:07:47 +1200 Subject: [PATCH 2/2] Update mailer.ts to match nodemailers more strict address parsing --- application/backend/src/utils/mailer.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/application/backend/src/utils/mailer.ts b/application/backend/src/utils/mailer.ts index 23534c1d..0b1e0e0e 100644 --- a/application/backend/src/utils/mailer.ts +++ b/application/backend/src/utils/mailer.ts @@ -1,7 +1,24 @@ import nodemailer from 'nodemailer' import config from '../config' -export const fromAddress = `CTRL ` +if (!process.env.HOSTNAME) { + throw new Error('process.env.HOSTNAME is required but was not provided.') +} + +const hostnameEnvVar = process.env.HOSTNAME +let mailDomain: string + +if (/^https?:\/\//i.test(hostnameEnvVar)) { + try { + mailDomain = new URL(hostnameEnvVar).hostname + } catch (err: any) { + throw new Error(`HOSTNAME deployment variable not configured. ${err}`) + } +} else { + mailDomain = hostnameEnvVar +} + +export const fromAddress = `CTRL ` export async function createMailerTransporter() { if (process.env.STUB_MAILER == 'true') {