This commit is contained in:
rgrgogu
2026-05-05 23:18:47 +08:00
parent 5aeb959e92
commit a8f10a25d7
38 changed files with 5992 additions and 2 deletions
+99
View File
@@ -0,0 +1,99 @@
/***********************************************************************************************************************************************************************
* File Name: email.service.js
* Type of Program: Service
* Description: Nodemailer-based email service.
* Provides:
* - sendOTPEmail() → sends a 6-digit OTP verification email
* - sendWelcomeEmail() → sent after successful email verification
* Author: rgrgogu
* Date Created: Oct. 6, 2025
***********************************************************************************************************************************************************************
* HOW TO USE:
* const emailService = require('../services/email.service');
* await emailService.sendOTPEmail(user.email, otp);
***********************************************************************************************************************************************************************/
const nodemailer = require('nodemailer');
const { emailTemplates } = require('../data/email_body.data')
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
const buildEmailTemplate = ({ title, body }) => {
return `
<div style="font-family:Arial,sans-serif;max-width:520px;margin:auto;border:1px solid #e5e7eb;border-radius:10px;overflow:hidden">
<!-- LOGO -->
<div style="padding:20px;text-align:center;background:#232f3e">
<img src="${process.env.APP_LOGO_URL}" alt="Philproperties" style="height:42px" />
</div>
<!-- CONTENT -->
<div style="padding:26px">
<h2 style="color:#111827;margin-bottom:14px">${title}</h2>
${body}
<!-- FORMAL CLOSING -->
<div style="margin-top:24px">
<p style="margin:0">Regards,</p>
<p style="margin:4px 0 0;font-weight:600;color:#111827">
Philproperties IT Team
</p>
</div>
</div>
<!-- FOOTER -->
<div style="padding:14px;text-align:center;font-size:12px;color:#6b7280;border-top:1px solid #e5e7eb">
This is an automated message from STARR System. Please do not reply.
</div>
</div>
`;
};
/**
* Sends a 6-digit OTP to the given email address.
* @param {string} to - recipient email
* @param {string} otp - 6-digit code
* @param {number} expiryMinutes
*/
const sendEmail = async ({ to, type, data = {} }) => {
try {
const templateFn = emailTemplates[type];
if (!templateFn) {
throw new Error(`Email template "${type}" not found`);
}
const { subject, title, body } = templateFn(data);
const html = buildEmailTemplate({ title, body });
return await new Promise((resolve, reject) => {
transporter.sendMail(
{
from: {
name: "STARR System",
address: "do-not-reply@philproperties.com",
},
to,
subject,
html,
},
(err, info) => {
if (err) return reject(err);
resolve(info);
}
);
});
} catch (err) {
throw new Error(err.message);
}
};
module.exports = sendEmail;