Files
Checkmate/server/service/emailService.js
T

159 lines
4.4 KiB
JavaScript
Raw Normal View History

2025-04-20 11:29:53 -07:00
import { fileURLToPath } from "url";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const SERVICE_NAME = "EmailService";
/**
* Represents an email service that can load templates, build, and send emails.
*/
class EmailService {
static SERVICE_NAME = SERVICE_NAME;
2025-05-15 15:16:36 +02:00
2025-04-20 11:29:53 -07:00
/**
* Constructs an instance of the EmailService, initializing template loaders and the email transporter.
* @param {Object} settingsService - The settings service to get email configuration.
* @param {Object} fs - The file system module.
* @param {Object} path - The path module.
* @param {Function} compile - The Handlebars compile function.
* @param {Function} mjml2html - The MJML to HTML conversion function.
* @param {Object} nodemailer - The nodemailer module.
* @param {Object} logger - The logger module.
*/
constructor(settingsService, fs, path, compile, mjml2html, nodemailer, logger) {
this.settingsService = settingsService;
this.fs = fs;
this.path = path;
this.compile = compile;
this.mjml2html = mjml2html;
this.nodemailer = nodemailer;
this.logger = logger;
2025-05-09 14:52:44 -07:00
this.init();
}
2025-04-20 11:29:53 -07:00
2025-05-09 14:52:44 -07:00
init = async () => {
2025-04-20 11:29:53 -07:00
/**
* Loads an email template from the filesystem.
*
* @param {string} templateName - The name of the template to load.
* @returns {Function} A compiled template function that can be used to generate HTML email content.
*/
this.loadTemplate = (templateName) => {
try {
const templatePath = this.path.join(
__dirname,
`../templates/${templateName}.mjml`
);
const templateContent = this.fs.readFileSync(templatePath, "utf8");
return this.compile(templateContent);
} catch (error) {
this.logger.error({
message: error.message,
service: SERVICE_NAME,
method: "loadTemplate",
stack: error.stack,
});
}
};
/**
* A lookup object to access preloaded email templates.
* @type {Object.<string, Function>}
* TODO Load less used templates in their respective functions
*/
this.templateLookup = {
welcomeEmailTemplate: this.loadTemplate("welcomeEmail"),
employeeActivationTemplate: this.loadTemplate("employeeActivation"),
noIncidentsThisWeekTemplate: this.loadTemplate("noIncidentsThisWeek"),
serverIsDownTemplate: this.loadTemplate("serverIsDown"),
serverIsUpTemplate: this.loadTemplate("serverIsUp"),
passwordResetTemplate: this.loadTemplate("passwordReset"),
hardwareIncidentTemplate: this.loadTemplate("hardwareIncident"),
2025-05-09 14:52:44 -07:00
testEmailTemplate: this.loadTemplate("testEmailTemplate"),
2025-04-20 11:29:53 -07:00
};
/**
* The email transporter used to send emails.
* @type {Object}
*/
2025-05-09 14:52:44 -07:00
};
2025-04-20 11:29:53 -07:00
2025-06-18 10:44:59 +08:00
buildEmail = async (template, context) => {
try {
const mjml = this.templateLookup[template](context);
const html = await this.mjml2html(mjml);
return html.html;
} catch (error) {
this.logger.error({
message: error.message,
service: SERVICE_NAME,
method: "buildEmail",
stack: error.stack,
});
}
};
sendEmail = async (to, subject, html, transportConfig) => {
2025-05-16 15:02:07 -07:00
let config;
if (typeof transportConfig !== "undefined") {
config = transportConfig;
} else {
2025-05-23 12:22:05 -07:00
config = await this.settingsService.getDBSettings();
2025-05-16 15:02:07 -07:00
}
2025-04-20 11:29:53 -07:00
const {
systemEmailHost,
systemEmailPort,
2025-06-12 00:39:47 +05:30
systemEmailSecure,
systemEmailPool,
2025-04-20 11:29:53 -07:00
systemEmailUser,
systemEmailAddress,
systemEmailPassword,
2025-05-15 15:16:36 +02:00
systemEmailConnectionHost,
2025-06-11 15:11:28 +05:30
systemEmailTLSServername,
systemEmailIgnoreTLS,
systemEmailRequireTLS,
systemEmailRejectUnauthorized,
2025-05-16 15:02:07 -07:00
} = config;
2025-04-20 11:29:53 -07:00
2025-06-12 00:39:47 +05:30
const emailConfig = {
2025-04-20 11:29:53 -07:00
host: systemEmailHost,
2025-06-11 14:11:49 +05:30
port: Number(systemEmailPort),
2025-06-12 00:39:47 +05:30
secure: systemEmailSecure,
2025-04-20 11:29:53 -07:00
auth: {
user: systemEmailUser || systemEmailAddress,
pass: systemEmailPassword,
},
2025-06-13 12:22:28 +05:30
name: systemEmailConnectionHost || "localhost",
2025-05-09 14:52:44 -07:00
connectionTimeout: 5000,
2025-06-12 00:39:47 +05:30
pool: systemEmailPool,
2025-06-13 12:22:28 +05:30
tls: {
rejectUnauthorized: systemEmailRejectUnauthorized,
ignoreTLS: systemEmailIgnoreTLS,
requireTLS: systemEmailRequireTLS,
servername: systemEmailTLSServername,
},
2025-04-20 11:29:53 -07:00
};
this.transporter = this.nodemailer.createTransport(emailConfig);
2025-06-18 10:44:59 +08:00
try {
const info = await this.transporter.sendMail({
to: to,
from: systemEmailAddress,
subject: subject,
html: html,
});
return info?.messageId;
} catch (error) {
this.logger.error({
message: error.message,
service: SERVICE_NAME,
method: "sendEmail",
stack: error.stack,
});
}
2025-04-20 11:29:53 -07:00
};
}
2025-05-15 15:16:36 +02:00
2025-04-20 11:29:53 -07:00
export default EmailService;