From e904e9634548e47d611bdcbb88d7b180b927fd5f Mon Sep 17 00:00:00 2001 From: JustZvan Date: Fri, 6 Feb 2026 12:16:40 +0100 Subject: feat: initial commit! --- src/email/confirm.ts | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/email/email.ts | 66 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 src/email/confirm.ts create mode 100644 src/email/email.ts (limited to 'src/email') diff --git a/src/email/confirm.ts b/src/email/confirm.ts new file mode 100644 index 0000000..b885438 --- /dev/null +++ b/src/email/confirm.ts @@ -0,0 +1,75 @@ +/** Generates the HTML template for email verification messages */ +export function verificationEmailHtml(verificationCode: string): string { + return ` + + + + + + Buddy Email Verification + + + + + + +
+ + + + + + + + + + + + + + + + + +
+

+ 🐶 Buddy +

+

+ Verification code +

+
+

+ Enter this code to verify your account: +

+ +
+ + ${verificationCode} + +
+ +

+ Code expires soon. Didn't request this? Ignore it. +

+ +

+ Buddy Team +

+
+ © ${new Date().getFullYear()} Buddy +
+
+ + +`; +} diff --git a/src/email/email.ts b/src/email/email.ts new file mode 100644 index 0000000..61ec18a --- /dev/null +++ b/src/email/email.ts @@ -0,0 +1,66 @@ +import nodemailer from "nodemailer"; +import { logger } from "../lib/pino"; + +let transporter: nodemailer.Transporter | null = null; + +/** + * Gets or creates the nodemailer transporter instance. + * Configuration is loaded from SMTP environment variables. + */ +export function getTransporter(): nodemailer.Transporter { + if (!transporter) { + try { + if (!process.env.SMTP_HOST) { + logger.error("SMTP_HOST environment variable not set"); + throw new Error("SMTP_HOST is required"); + } + + if (!process.env.SMTP_PORT) { + logger.error("SMTP_PORT environment variable not set"); + throw new Error("SMTP_PORT is required"); + } + + if (!process.env.SMTP_USER) { + logger.error("SMTP_USER environment variable not set"); + throw new Error("SMTP_USER is required"); + } + + if (!process.env.SMTP_PASS) { + logger.error("SMTP_PASS environment variable not set"); + throw new Error("SMTP_PASS is required"); + } + + const port = Number(process.env.SMTP_PORT); + if (isNaN(port) || port <= 0 || port > 65535) { + logger.error( + { port: process.env.SMTP_PORT }, + "Invalid SMTP_PORT value", + ); + throw new Error("SMTP_PORT must be a valid port number"); + } + + transporter = nodemailer.createTransport({ + host: process.env.SMTP_HOST, + port, + secure: process.env.SMTP_SECURE == "1", + auth: { + user: process.env.SMTP_USER, + pass: process.env.SMTP_PASS, + }, + }); + + logger.info( + { + host: process.env.SMTP_HOST, + port, + secure: process.env.SMTP_SECURE == "1", + }, + "Email transporter created successfully", + ); + } catch (error) { + logger.error({ error }, "Failed to create email transporter"); + throw error; + } + } + return transporter; +} -- cgit v1.2.3