/** * Copyright (c) 2026 Niolla * All rights reserved. * * This source code is proprietary and confidential. * Unauthorized copying, modification, distribution, or use * of this file, via any medium, is strictly prohibited. */ // app/utils/mailer.util.js const nodemailer = require("nodemailer"); const fs = require("fs"); const path = require("path"); const mailConfig = require("../config/mail.config"); const transporter = nodemailer.createTransport({ host: mailConfig.host, port: mailConfig.port, secure: mailConfig.secure, auth: mailConfig.auth, }); if (process.env.NODE_ENV !== "test" && process.env.ENABLE_MAIL === "true") { transporter.verify((err) => { if (err) console.error("Mail server connection failed", { message: err.message }); else console.log("Mail server ready"); }); } // Utility to load template and replace placeholders const loadTemplate = (templateName, variables = {}) => { if (!/^[a-zA-Z0-9_-]+$/.test(templateName)) throw new Error("Invalid email template"); const templatePath = path.join(__dirname, "../templates/emails", `${templateName}.html`); let template = fs.readFileSync(templatePath, "utf-8"); Object.keys(variables).forEach((key) => { const regex = new RegExp(`{{${key}}}`, "g"); const escaped = String(variables[key] ?? "").replace(/[&<>"']/g, (char) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[char]); template = template.replace(regex, escaped); }); return template; }; const send = async ({ to, subject, templateName, templateVars = {}, text }) => { if (process.env.ENABLE_MAIL !== "true") { throw new Error("Email functionality is not enabled"); } const html = templateName ? loadTemplate(templateName, templateVars) : undefined; const mailOptions = { from: mailConfig.from, to, subject, text, html, }; try { const info = await transporter.sendMail(mailOptions); console.log("Email sent:", info.messageId); return info; } catch (err) { console.error("Error sending email:", err); throw err; } }; const sendMail = async (options) => { const today = new Date(); // Full formatted date: "January 1, 2026" const formattedDate = today.toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", }); // Only year: "2026" const currentYear = today.getFullYear(); const templateVars = { ...options.templateVars, // keep existing vars currentDate: formattedDate, currentYear: currentYear, }; return send({ ...options, templateVars }); }; module.exports = { sendMail, loadTemplate };