From 48c3b6689a98b4d03fb689911289c149b7a9fea3 Mon Sep 17 00:00:00 2001 From: Remi <73385395+itsrubberduck@users.noreply.github.com> Date: Wed, 17 Sep 2025 16:21:11 +0200 Subject: [PATCH] Add password reset flow --- server/utils/notifications.ts | 77 ++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/server/utils/notifications.ts b/server/utils/notifications.ts index 8eaf7d8..af5da7b 100644 --- a/server/utils/notifications.ts +++ b/server/utils/notifications.ts @@ -2,15 +2,27 @@ const ADMIN_EMAIL_FALLBACK = 'opensquawk@faktorxmensch.com' const RESEND_ENDPOINT = 'https://api.resend.com/emails' -async function sendViaResend(subject: string, text: string) { +interface MailOptions { + to: string + subject: string + text: string + from?: string +} + +interface MailPayload extends MailOptions { + from: string +} + +function resolveFrom(from?: string) { + return from || process.env.NOTIFY_EMAIL_FROM || 'OpenSquawk ' +} + +async function sendViaResend(payload: MailPayload) { const apiKey = process.env.NOTIFY_RESEND_API_KEY if (!apiKey) { return false } - const to = process.env.NOTIFY_EMAIL_TO || ADMIN_EMAIL_FALLBACK - const from = process.env.NOTIFY_EMAIL_FROM || 'OpenSquawk ' - try { const response = await fetch(RESEND_ENDPOINT, { method: 'POST', @@ -18,28 +30,23 @@ async function sendViaResend(subject: string, text: string) { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, - body: JSON.stringify({ - from, - to, - subject, - text, - }), + body: JSON.stringify(payload), }) if (!response.ok) { const errorText = await response.text().catch(() => '') - console.error('Failed to send notification via Resend API', response.status, errorText) + console.error('Failed to send email via Resend API', response.status, errorText) return false } return true } catch (error) { - console.error('Error while sending notification via Resend API', error) + console.error('Error while sending email via Resend API', error) return false } } -async function sendViaSmtp(subject: string, text: string) { +async function sendViaSmtp(payload: MailPayload) { const host = process.env.NOTIFY_SMTP_HOST if (!host) { return false @@ -64,13 +71,10 @@ async function sendViaSmtp(subject: string, text: string) { return false } - const to = process.env.NOTIFY_EMAIL_TO || ADMIN_EMAIL_FALLBACK - const from = process.env.NOTIFY_EMAIL_FROM || 'OpenSquawk ' - try { const transporter = nodemailer.createTransport({ host, - port: Number.isNaN(port) ? secure ? 465 : 587 : port, + port: Number.isNaN(port) ? (secure ? 465 : 587) : port, secure, auth: { user, @@ -78,26 +82,51 @@ async function sendViaSmtp(subject: string, text: string) { }, }) - await transporter.sendMail({ from, to, subject, text }) + await transporter.sendMail({ + from: payload.from, + to: payload.to, + subject: payload.subject, + text: payload.text, + }) return true } catch (error) { - console.error('Failed to send notification via SMTP', error) + console.error('Failed to send email via SMTP', error) return false } } -export async function sendAdminNotification(subject: string, text: string) { - const sentViaResend = await sendViaResend(subject, text) +async function sendMailInternal(options: MailOptions) { + const payload: MailPayload = { + ...options, + from: resolveFrom(options.from), + } + + const sentViaResend = await sendViaResend(payload) if (sentViaResend) { return true } - const sentViaSmtp = await sendViaSmtp(subject, text) + const sentViaSmtp = await sendViaSmtp(payload) if (sentViaSmtp) { return true } - const to = process.env.NOTIFY_EMAIL_TO || ADMIN_EMAIL_FALLBACK - console.info(`[notify:fallback] ${subject}\nEmpfänger: ${to}\n${text}`) return false } + +export async function sendMail(options: MailOptions) { + const success = await sendMailInternal(options) + if (!success) { + console.info(`[mail:fallback] ${options.subject}\nEmpfänger: ${options.to}\n${options.text}`) + } + return success +} + +export async function sendAdminNotification(subject: string, text: string) { + const to = process.env.NOTIFY_EMAIL_TO || ADMIN_EMAIL_FALLBACK + const success = await sendMailInternal({ to, subject, text }) + if (!success) { + console.info(`[notify:fallback] ${subject}\nEmpfänger: ${to}\n${text}`) + } + return success +}