diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js index 9ccf9de60b..bbecd29d1b 100644 --- a/server/notification-providers/smtp.js +++ b/server/notification-providers/smtp.js @@ -37,76 +37,80 @@ class SMTP extends NotificationProvider { pass: notification.smtpPassword, }; } - // Lets start with default subject and empty string for custom one - let subject = msg; - // Change the subject if: - // - The msg ends with "Testing" or - // - Actual Up/Down Notification + // default values in case the user does not want to template + let subject = msg; + let body = msg; + if (heartbeatJSON) { + body = `${msg}\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`; + } + // subject and body are templated if ((monitorJSON && heartbeatJSON) || msg.endsWith("Testing")) { - let customSubject = ""; + // cannot end with whitespace as this often raises spam scores + const customSubject = notification.customSubject?.trim() || ""; + const customBody = notification.customBody?.trim() || ""; - // Our subject cannot end with whitespace it's often raise spam score - // Once I got "Cannot read property 'trim' of undefined", better be safe than sorry - if (notification.customSubject) { - customSubject = notification.customSubject.trim(); - } - - // If custom subject is not empty, change subject for notification + const context = this.generateContext(msg, monitorJSON, heartbeatJSON); + const engine = new Liquid(); if (customSubject !== "") { - - // Let's start with dummy values to simplify code - let monitorName = "Test"; - let monitorHostnameOrURL = "testing.hostname"; - let serviceStatus = "⚠️ Test"; - - if (monitorJSON !== null) { - monitorName = monitorJSON["name"]; - - if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword" || monitorJSON["type"] === "json-query") { - monitorHostnameOrURL = monitorJSON["url"]; - } else { - monitorHostnameOrURL = monitorJSON["hostname"]; - } - } - - if (heartbeatJSON !== null) { - serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up"; - } - - // Initialize LiquidJS and parse the custom Body Template - const engine = new Liquid(); const tpl = engine.parse(customSubject); - - // Insert templated values into Body - subject = await engine.render(tpl, - { - "STATUS": serviceStatus, - "NAME": monitorName, - "HOSTNAME_OR_URL": monitorHostnameOrURL, - }); + subject = await engine.render(tpl, context); + } + if (customBody !== "") { + const tpl = engine.parse(customBody); + body = await engine.render(tpl, context); } - } - - let transporter = nodemailer.createTransport(config); - - let bodyTextContent = msg; - if (heartbeatJSON) { - bodyTextContent = `${msg}\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`; } // send mail with defined transport object + let transporter = nodemailer.createTransport(config); await transporter.sendMail({ from: notification.smtpFrom, cc: notification.smtpCC, bcc: notification.smtpBCC, to: notification.smtpTo, subject: subject, - text: bodyTextContent, + text: body, }); return "Sent Successfully."; } + + /** + * Generate context for LiquidJS + * @param msg {string} + * @param monitorJSON {Object|null} + * @param heartbeatJSON {Object|null} + * @returns {{STATUS: string, HOSTNAME_OR_URL: string, NAME: string, monitorJSON: Object|null, heartbeatJSON: Object|null, msg: string}} + */ + generateContext(msg, monitorJSON, heartbeatJSON) { + // Let's start with dummy values to simplify code + let monitorName = "Monitor Name not available"; + let monitorHostnameOrURL = "testing.hostname"; + let serviceStatus = "⚠️ Test"; + + if (monitorJSON !== null) { + monitorName = monitorJSON["name"]; + + if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword" || monitorJSON["type"] === "json-query") { + monitorHostnameOrURL = monitorJSON["url"]; + } else { + monitorHostnameOrURL = monitorJSON["hostname"]; + } + } + + if (heartbeatJSON !== null) { + serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up"; + } + return { + "STATUS": serviceStatus, + "NAME": monitorName, + "HOSTNAME_OR_URL": monitorHostnameOrURL, + monitorJSON, + heartbeatJSON, + msg, + }; + } } module.exports = SMTP; diff --git a/src/components/notifications/SMTP.vue b/src/components/notifications/SMTP.vue index 1c48313cc6..e985e1ec2b 100644 --- a/src/components/notifications/SMTP.vue +++ b/src/components/notifications/SMTP.vue @@ -59,6 +59,28 @@ +

+ + {{ $t("documentation") }} + + {{NAME}}: {{ $t("emailTemplateServiceName") }}
+ {{msg}}: {{ $t("emailTemplateMsg") }}
+ {{STATUS}}: {{ $t("emailTemplateStatus") }}
+ {{heartbeatJSON}}: {{ $t("emailTemplateHeartbeatJSON") }}{{ $t("emailTemplateLimitedToUpDownNotification") }}
+ {{monitorJSON}}: {{ $t("emailTemplateMonitorJSON") }} {{ $t("emailTemplateLimitedToUpDownNotification") }}
+ {{HOSTNAME_OR_URL}}: {{ $t("emailTemplateHostnameOrURL") }}
+

+
+ + +
{{ $t("leave blank for default subject") }}
+
+
+ + +
{{ $t("leave blank for default body") }}
+
+ {{ $t("documentation") }} @@ -89,17 +111,6 @@ - -
- - -
- (leave blank for default one)
- {{NAME}}: Service Name
- {{HOSTNAME_OR_URL}}: Hostname or URL
- {{STATUS}}: Status
-
-
diff --git a/src/lang/en.json b/src/lang/en.json index 772e572997..f9a89a301c 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -479,7 +479,19 @@ "secureOptionTLS": "TLS (465)", "Ignore TLS Error": "Ignore TLS Error", "From Email": "From Email", + "emailCustomisableContent": "Customisable content", + "smtpLiquidIntroduction": "The following two fields are templatable via the Liquid templating Language. Please refer to the {0} for usage instructions. These are the avaliable variables:", "emailCustomSubject": "Custom Subject", + "leave blank for default subject": "leave blank for default subject", + "emailCustomBody": "Custom Body", + "leave blank for default body": "leave blank for default body", + "emailTemplateServiceName": "Service Name", + "emailTemplateHostnameOrURL": "Hostname or URL", + "emailTemplateStatus": "Status", + "emailTemplateMonitorJSON": "object describing the monitor", + "emailTemplateHeartbeatJSON": "object describing the heartbeat", + "emailTemplateMsg": "message of the notification", + "emailTemplateLimitedToUpDownNotification": "only available for UP/DOWN heartbeats, otherwise null", "To Email": "To Email", "smtpCC": "CC", "smtpBCC": "BCC",