diff --git a/server/controllers/authController.js b/server/controllers/authController.js index b05a9635a..a1a35e616 100755 --- a/server/controllers/authController.js +++ b/server/controllers/authController.js @@ -96,21 +96,28 @@ class AuthController { const token = this.issueToken(userForToken, appSettings); - this.emailService - .buildAndSendEmail( - "welcomeEmailTemplate", - { name: newUser.firstName }, - newUser.email, - "Welcome to Uptime Monitor" - ) - .catch((error) => { - logger.error({ - message: error.message, - service: SERVICE_NAME, - method: "registerUser", - stack: error.stack, - }); + try { + const html = await this.emailService.buildEmail("welcomeEmailTemplate", { + name: newUser.firstName, }); + this.emailService + .sendEmail(newUser.email, "Welcome to Uptime Monitor", html) + .catch((error) => { + this.logger.warn({ + message: error.message, + service: SERVICE_NAME, + method: "registerUser", + stack: error.stack, + }); + }); + } catch (error) { + logger.warn({ + message: error.message, + service: SERVICE_NAME, + method: "registerUser", + stack: error.stack, + }); + } res.success({ msg: this.stringService.authCreateUser, @@ -300,15 +307,16 @@ class AuthController { const name = user.firstName; const { clientHost } = this.settingsService.getSettings(); const url = `${clientHost}/set-new-password/${recoveryToken.token}`; - const msgId = await this.emailService.buildAndSendEmail( - "passwordResetTemplate", - { - name, - email, - url, - }, + + const html = await this.emailService.buildEmail("passwordResetTemplate", { + name, email, - "Checkmate Password Reset" + url, + }); + const msgId = await this.emailService.sendEmail( + email, + "Checkmate Password Reset", + html ); return res.success({ diff --git a/server/controllers/inviteController.js b/server/controllers/inviteController.js index bce40dfa1..3b2212769 100755 --- a/server/controllers/inviteController.js +++ b/server/controllers/inviteController.js @@ -71,24 +71,25 @@ class InviteController { const inviteToken = await this.db.requestInviteToken({ ...req.body }); const { clientHost } = this.settingsService.getSettings(); - this.emailService - .buildAndSendEmail( - "employeeActivationTemplate", - { - name: firstname, - link: `${clientHost}/register/${inviteToken.token}`, - }, - req.body.email, - "Welcome to Uptime Monitor" - ) - .catch((error) => { - logger.error({ - message: error.message, - service: SERVICE_NAME, - method: "issueInvitation", - stack: error.stack, - }); + + try { + const html = await this.emailService.buildEmail("employeeActivationTemplate", { + name: firstname, + link: `${clientHost}/register/${inviteToken.token}`, }); + await this.emailService.sendEmail( + req.body.email, + "Welcome to Uptime Monitor", + html + ); + } catch (error) { + logger.warn({ + message: error.message, + service: SERVICE_NAME, + method: "sendInviteEmail", + stack: error.stack, + }); + } return res.success({ msg: this.stringService.inviteIssued, diff --git a/server/controllers/monitorController.js b/server/controllers/monitorController.js index 6c6136fb5..e1d087c74 100755 --- a/server/controllers/monitorController.js +++ b/server/controllers/monitorController.js @@ -580,12 +580,8 @@ class MonitorController { const subject = this.stringService.testEmailSubject; const context = { testName: "Monitoring System" }; - const messageId = await this.emailService.buildAndSendEmail( - "testEmailTemplate", - context, - to, - subject - ); + const html = await this.emailService.buildEmail("testEmailTemplate", context); + const messageId = await this.emailService.sendEmail(to, subject, html); if (!messageId) { return res.error({ diff --git a/server/controllers/settingsController.js b/server/controllers/settingsController.js index b9faa1c32..cbdd73adf 100755 --- a/server/controllers/settingsController.js +++ b/server/controllers/settingsController.js @@ -90,26 +90,21 @@ class SettingsController { const subject = this.stringService.testEmailSubject; const context = { testName: "Monitoring System" }; - const messageId = await this.emailService.buildAndSendEmail( - "testEmailTemplate", - context, - to, - subject, - { - systemEmailHost, - systemEmailPort, - systemEmailUser, - systemEmailAddress, - systemEmailPassword, - systemEmailConnectionHost, - systemEmailSecure, - systemEmailPool, - systemEmailIgnoreTLS, - systemEmailRequireTLS, - systemEmailRejectUnauthorized, - systemEmailTLSServername, - } - ); + const html = await this.emailService.buildEmail("testEmailTemplate", context); + const messageId = await this.emailService.sendEmail(to, subject, html, { + systemEmailHost, + systemEmailPort, + systemEmailUser, + systemEmailAddress, + systemEmailPassword, + systemEmailConnectionHost, + systemEmailSecure, + systemEmailPool, + systemEmailIgnoreTLS, + systemEmailRequireTLS, + systemEmailRejectUnauthorized, + systemEmailTLSServername, + }); if (!messageId) { return res.error({ diff --git a/server/service/emailService.js b/server/service/emailService.js index 09123ef93..89bd4d50f 100755 --- a/server/service/emailService.js +++ b/server/service/emailService.js @@ -80,24 +80,28 @@ class EmailService { */ }; - /** - * Asynchronously builds and sends an email using a specified template and context. - * - * @param {string} template - The name of the template to use for the email body. - * @param {Object} context - The data context to render the template with. - * @param {string} to - The recipient's email address. - * @param {string} subject - The subject of the email. - * @returns {Promise} A promise that resolves to the messageId of the sent email. - */ - buildAndSendEmail = async (template, context, to, subject, transportConfig) => { - // TODO - Consider an update transporter method so this only needs to be recreated when smtp settings change + 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) => { let config; if (typeof transportConfig !== "undefined") { config = transportConfig; } else { config = await this.settingsService.getDBSettings(); } - const { systemEmailHost, systemEmailPort, @@ -131,45 +135,24 @@ class EmailService { servername: systemEmailTLSServername, }, }; - this.transporter = this.nodemailer.createTransport(emailConfig); - const buildHtml = 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: "buildAndSendEmail", - stack: error.stack, - }); - } - }; - - const sendEmail = async (to, subject, html) => { - try { - const info = await this.transporter.sendMail({ - to: to, - from: systemEmailAddress, - subject: subject, - html: html, - }); - return info; - } catch (error) { - this.logger.error({ - message: error.message, - service: SERVICE_NAME, - method: "sendEmail", - stack: error.stack, - }); - } - }; - const html = await buildHtml(template, context); - const info = await sendEmail(to, subject, html); - return info?.messageId; + 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, + }); + } }; } diff --git a/server/service/notificationService.js b/server/service/notificationService.js index 77bd31aee..dcd629d53 100755 --- a/server/service/notificationService.js +++ b/server/service/notificationService.js @@ -218,7 +218,16 @@ class NotificationService { const template = "hardwareIncidentTemplate"; const context = { monitor: monitor.name, url: monitor.url, alerts }; const subject = `Monitor ${monitor.name} infrastructure alerts`; - this.emailService.buildAndSendEmail(template, context, address, subject); + const html = await this.emailService.buildEmail(template, context); + this.emailService.sendEmail(address, subject, html).catch((error) => { + this.logger.warn({ + message: error.message, + service: this.SERVICE_NAME, + method: "sendHardwareEmail", + stack: error.stack, + }); + }); + return true; } @@ -231,17 +240,22 @@ class NotificationService { const subject = this.stringService.testEmailSubject; const context = { testName: "Monitoring System" }; - const messageId = await this.emailService.buildAndSendEmail( - "testEmailTemplate", - context, - to, - subject - ); + try { + const html = await this.emailService.buildEmail("testEmailTemplate", context); + const messageId = await this.emailService.sendEmail(to, subject, html); - if (messageId) { - return true; + if (messageId) { + return true; + } + } catch (error) { + this.logger.warn({ + message: error.message, + service: this.SERVICE_NAME, + method: "sendTestEmail", + stack: error.stack, + }); + return false; } - return false; }; /** @@ -259,7 +273,17 @@ class NotificationService { const template = prevStatus === false ? "serverIsUpTemplate" : "serverIsDownTemplate"; const context = { monitor: monitor.name, url: monitor.url }; const subject = `Monitor ${monitor.name} is ${status === true ? "up" : "down"}`; - this.emailService.buildAndSendEmail(template, context, address, subject); + + const html = await this.emailService.buildEmail(template, context); + this.emailService.sendEmail(address, subject, html).catch((error) => { + this.logger.warn({ + message: error.message, + service: this.SERVICE_NAME, + method: "sendEmail", + stack: error.stack, + }); + }); + return true; }