From 0906e883c52ec054dad22cd5da5ab81e445341b8 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 16 May 2025 15:01:06 -0700 Subject: [PATCH 1/5] add test email controller method --- server/controllers/settingsController.js | 58 +++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/server/controllers/settingsController.js b/server/controllers/settingsController.js index 21f0050ba..58e8ce9f4 100755 --- a/server/controllers/settingsController.js +++ b/server/controllers/settingsController.js @@ -1,13 +1,14 @@ import { updateAppSettingsBodyValidation } from "../validation/joi.js"; import { handleValidationError, handleError } from "./controllerUtils.js"; - +import { sendTestEmailBodyValidation } from "../validation/joi.js"; const SERVICE_NAME = "SettingsController"; class SettingsController { - constructor(db, settingsService, stringService) { + constructor({ db, settingsService, stringService, emailService }) { this.db = db; this.settingsService = settingsService; this.stringService = stringService; + this.emailService = emailService; } getAppSettings = async (req, res, next) => { @@ -55,6 +56,59 @@ class SettingsController { next(handleError(error, SERVICE_NAME, "updateAppSettings")); } }; + + sendTestEmail = async (req, res, next) => { + try { + await sendTestEmailBodyValidation.validateAsync(req.body); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } + + try { + const { + to, + systemEmailHost, + systemEmailPort, + systemEmailAddress, + systemEmailPassword, + systemEmailUser, + systemEmailConnectionHost, + } = req.body; + + 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, + } + ); + + if (!messageId) { + return res.error({ + msg: "Failed to send test email.", + }); + } + + return res.success({ + msg: this.stringService.sendTestEmail, + data: { messageId }, + }); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } + }; } export default SettingsController; From bea8ddb330e22780bceac3717698bb0832050848 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 16 May 2025 15:01:34 -0700 Subject: [PATCH 2/5] add a test email route to settings routes --- server/routes/monitorRoute.js | 4 ++-- server/routes/settingsRoute.js | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/server/routes/monitorRoute.js b/server/routes/monitorRoute.js index f9ef460c6..6d1db90ad 100755 --- a/server/routes/monitorRoute.js +++ b/server/routes/monitorRoute.js @@ -4,8 +4,8 @@ import multer from "multer"; import { fetchMonitorCertificate } from "../controllers/controllerUtils.js"; const upload = multer({ - storage: multer.memoryStorage() // Store file in memory as Buffer - }); + storage: multer.memoryStorage(), // Store file in memory as Buffer +}); class MonitorRoutes { constructor(monitorController) { diff --git a/server/routes/settingsRoute.js b/server/routes/settingsRoute.js index a5501aaf3..f293fd660 100755 --- a/server/routes/settingsRoute.js +++ b/server/routes/settingsRoute.js @@ -15,6 +15,11 @@ class SettingsRoutes { isAllowed(["admin", "superadmin"]), this.settingsController.updateAppSettings ); + this.router.post( + "/test-email", + isAllowed(["admin", "superadmin"]), + this.settingsController.sendTestEmail + ); } getRouter() { From d71181e65b21b4094f8e0eb569704899eb921402 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 16 May 2025 15:01:45 -0700 Subject: [PATCH 3/5] add test-email body validation --- server/validation/joi.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/validation/joi.js b/server/validation/joi.js index 3dfee80c4..c16843fcd 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -591,6 +591,16 @@ const createAnnouncementValidation = joi.object({ userId: joi.string().required(), }); +const sendTestEmailBodyValidation = joi.object({ + to: joi.string().required(), + systemEmailHost: joi.string(), + systemEmailPort: joi.number(), + systemEmailAddress: joi.string(), + systemEmailPassword: joi.string(), + systemEmailUser: joi.string(), + systemEmailConnectionHost: joi.string(), +}); + export { roleValidatior, loginValidation, @@ -654,4 +664,5 @@ export { triggerNotificationBodyValidation, webhookConfigValidation, createAnnouncementValidation, + sendTestEmailBodyValidation, }; From f6a2a663867c90f8285fde9626b4774e19622a24 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 16 May 2025 15:02:07 -0700 Subject: [PATCH 4/5] allow optional transport params --- server/service/emailService.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/server/service/emailService.js b/server/service/emailService.js index b3e087046..6e6a70684 100755 --- a/server/service/emailService.js +++ b/server/service/emailService.js @@ -89,8 +89,16 @@ class EmailService { * @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) => { + buildAndSendEmail = async (template, context, to, subject, transportConfig) => { // TODO - Consider an update transporter method so this only needs to be recreated when smtp settings change + let config; + + if (typeof transportConfig !== "undefined") { + config = transportConfig; + } else { + config = this.settingsService.getDBSettings(); + } + const { systemEmailHost, systemEmailPort, @@ -98,7 +106,7 @@ class EmailService { systemEmailAddress, systemEmailPassword, systemEmailConnectionHost, - } = await this.settingsService.getDBSettings(); + } = config; const baseEmailConfig = { host: systemEmailHost, From 5872879c9ab45fbcd64be4d7b082eab458f17008 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 16 May 2025 15:02:26 -0700 Subject: [PATCH 5/5] inject email service into settings controller --- server/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server/index.js b/server/index.js index f299b32e9..192f25c5a 100755 --- a/server/index.js +++ b/server/index.js @@ -241,11 +241,12 @@ const startApp = async () => { ServiceRegistry.get(EmailService.SERVICE_NAME) ); - const settingsController = new SettingsController( - ServiceRegistry.get(MongoDB.SERVICE_NAME), - ServiceRegistry.get(SettingsService.SERVICE_NAME), - ServiceRegistry.get(StringService.SERVICE_NAME) - ); + const settingsController = new SettingsController({ + db: ServiceRegistry.get(MongoDB.SERVICE_NAME), + settingsService: ServiceRegistry.get(SettingsService.SERVICE_NAME), + stringService: ServiceRegistry.get(StringService.SERVICE_NAME), + emailService: ServiceRegistry.get(EmailService.SERVICE_NAME), + }); const checkController = new CheckController( ServiceRegistry.get(MongoDB.SERVICE_NAME),