@ -1,6 +1,7 @@
const nodemailer = require ( "nodemailer" ) ;
const NotificationProvider = require ( "./notification-provider" ) ;
const { DOWN } = require ( "../../src/util" ) ;
const { Liquid } = require ( "liquidjs" ) ;
class SMTP extends NotificationProvider {
@ -39,76 +40,86 @@ 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 } \n Time ( ${ 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 !== "" ) {
// Replace "MACROS" with corresponding variable
let replaceName = new RegExp ( "{{NAME}}" , "g" ) ;
let replaceHostnameOrURL = new RegExp ( "{{HOSTNAME_OR_URL}}" , "g" ) ;
let replaceStatus = new RegExp ( "{{STATUS}}" , "g" ) ;
// Lets 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" ;
}
// Break replace to one by line for better readability
customSubject = customSubject . replace ( replaceStatus , serviceStatus ) ;
customSubject = customSubject . replace ( replaceName , monitorName ) ;
customSubject = customSubject . replace ( replaceHostnameOrURL , monitorHostnameOrURL ) ;
subject = customSubject ;
const tpl = engine . parse ( customSubject ) ;
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 } \n Time ( ${ 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 : body TextContent ,
text : body ,
} ) ;
return "Sent Successfully." ;
}
/ * *
* Generate context for LiquidJS
* @ param { string } msg the message that will be included in the context
* @ param { ? object } monitorJSON Monitor details ( For Up / Down / Cert - Expiry only )
* @ param { ? object } heartbeatJSON Heartbeat details ( For Up / Down only )
* @ returns { { STATUS : string , status : string , HOSTNAME _OR _URL : string , hostnameOrUrl : string , NAME : string , name : string , monitorJSON : ? object , heartbeatJSON : ? object , msg : string } } the context
* /
generateContext ( msg , monitorJSON , heartbeatJSON ) {
// Let's start with dummy values to simplify code
let monitorName = "Monitor Name not available" ;
let monitorHostnameOrURL = "testing.hostname" ;
if ( monitorJSON !== null ) {
monitorName = monitorJSON [ "name" ] ;
if ( monitorJSON [ "type" ] === "http" || monitorJSON [ "type" ] === "keyword" || monitorJSON [ "type" ] === "json-query" ) {
monitorHostnameOrURL = monitorJSON [ "url" ] ;
} else {
monitorHostnameOrURL = monitorJSON [ "hostname" ] ;
}
}
let serviceStatus = "⚠️ Test" ;
if ( heartbeatJSON !== null ) {
serviceStatus = ( heartbeatJSON [ "status" ] === DOWN ) ? "🔴 Down" : "✅ Up" ;
}
return {
// for v1 compatibility, to be removed in v3
"STATUS" : serviceStatus ,
"NAME" : monitorName ,
"HOSTNAME_OR_URL" : monitorHostnameOrURL ,
// variables which are officially supported
"status" : serviceStatus ,
"name" : monitorName ,
"hostnameOrURL" : monitorHostnameOrURL ,
monitorJSON ,
heartbeatJSON ,
msg ,
} ;
}
}
module . exports = SMTP ;