From 5541c0553c01beb9687aa4ecc4c6e8860af964d4 Mon Sep 17 00:00:00 2001 From: Timo Knuth Date: Thu, 13 Aug 2026 19:33:05 +0200 Subject: [PATCH] refactor: derive email sender address dynamically from SMTP_USER --- src/lib/email.ts | 58 ++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/src/lib/email.ts b/src/lib/email.ts index 2a254e9..102991f 100644 --- a/src/lib/email.ts +++ b/src/lib/email.ts @@ -48,6 +48,20 @@ async function waitForRateLimit() { lastEmailSent = Date.now(); } +function getEmailFrom(name = 'Timo from QR Master'): string { + const address = process.env.SMTP_USER || 'timo@qrmaster.net'; + return `${name} <${address}>`; +} + +function getEmailFromSecurity(): string { + const address = process.env.SMTP_USER || 'noreply@qrmaster.net'; + return `QR Master Security <${address}>`; +} + +function getEmailReplyTo(): string { + return process.env.SMTP_USER || 'support@qrmaster.net'; +} + /** * Password Reset Email - Security focused with clear urgency */ @@ -58,8 +72,8 @@ export async function sendPasswordResetEmail(email: string, resetToken: string) try { await resend.emails.send({ - from: 'QR Master Security ', - replyTo: 'support@qrmaster.net', + from: getEmailFromSecurity(), + replyTo: getEmailReplyTo(), to: email, subject: '🔐 Reset Your QR Master Password (Expires in 1 Hour)', html: ` @@ -190,8 +204,8 @@ export async function sendNewsletterWelcomeEmail(email: string) { try { await resend.emails.send({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: '🎉 You\'re In! Here\'s What Happens Next (AI QR Features)', html: ` @@ -362,8 +376,8 @@ export async function sendAIFeatureLaunchEmail(email: string) { try { await resend.emails.send({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: '🚀 They\'re Live! Your AI QR Features Are Ready', html: ` @@ -568,8 +582,8 @@ export async function sendEmailVerificationEmail(email: string, name: string, ve const firstName = name.trim().split(/\s+/)[0] || 'there'; await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: 'Confirm your QR Master email address', html: `
QR MASTER

Confirm your email address

Hi ${escapeHtml(firstName)},

Click the button below to finish creating your QR Master account.

CONFIRM EMAIL

This link expires in 24 hours. If you did not create an account, you can ignore this email.

`, @@ -586,8 +600,8 @@ export async function sendDesignerAnnouncementEmail(email: string, unsubscribeUr const transport = createSmtpTransport(); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: 'Your QR codes can now look like your brand', html: ` @@ -652,8 +666,8 @@ export async function sendNewsletterEmail({ const transport = createSmtpTransport(); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject, html: `
QR MASTER
${body}
You are receiving this email from QR Master.
Unsubscribe from product updates
`, @@ -929,8 +943,8 @@ export async function sendWelcomeEmail(email: string, name: string) { `); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: 'Your QR Master account is ready', html, @@ -1066,8 +1080,8 @@ export async function sendActivationNudgeEmail(email: string, name: string) { `); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: "Your 3 free codes are still sitting there", html, @@ -1237,8 +1251,8 @@ export async function sendUpgradeNudgeEmail(email: string, name: string, qrCount `); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: 'You just hit the free limit', html, @@ -1413,8 +1427,8 @@ export async function sendThirtyDayNudgeEmail( `); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: `${firstName}, your codes were scanned ${scanCount} time${scanCount !== 1 ? 's' : ''} this month`, html, @@ -1528,8 +1542,8 @@ export async function sendFirstScanEmail( `); await transport.sendMail({ - from: 'Timo from QR Master ', - replyTo: 'support@qrmaster.net', + from: getEmailFrom(), + replyTo: getEmailReplyTo(), to: email, subject: 'Your QR code was just scanned for the first time', html,