/**
* @module controllers/sendaid
* @author jesse reichler <mouser@donationcoder.com>
* @copyright 11/24/19
* @description
* This module does some generic message sending (email, etc.)
* @see <a href="https://www.npmjs.com/package/rate-limiter-flexible"></a>
*/
"use strict";
// modules
const assert = require("assert");
// mail
const nodemailer = require("nodemailer");
// requirement service locator
const jrequire = require("../helpers/jrequire");
// helpers
const jrdebug = require("../helpers/jrdebug");
const JrResult = require("../helpers/jrresult");
const jrhMisc = require("../helpers/jrh_misc");
const jrlog = require("../helpers/jrlog");
// controllers
const arserver = jrequire("arserver");
// constants
const appdef = jrequire("appdef");
/**
* Provides support functions for sending emails/sms/etc.
*
* @class SendAid
*/
class SendAid {
//---------------------------------------------------------------------------
async setupMailer(mailTransportConfigObj, defaultFrom, flagDebugMode) {
// setup the mailer system
// see https://nodemailer.com/about/
// see https://medium.com/@SeanChenU/send-mail-using-node-js-with-nodemailer-in-2-mins-c3f3e23f4a1
this.mailTransport = nodemailer.createTransport(mailTransportConfigObj);
this.defaultFrom = defaultFrom;
this.flagDebugMode = flagDebugMode;
assert(defaultFrom);
jrdebug.cdebugf("misc", "Setting up mail transport through %s.", mailTransportConfigObj.host);
// verify it?
if (jrdebug.getDebugTagEnabled("mail")) {
await this.getMailTransport().verify();
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
getMailTransport() {
// return previously created transport
return this.mailTransport;
}
addSendmailRetvToContext(jrContext, sendMailResult, mailobj) {
let msg;
if (sendMailResult.rejected.length === 0) {
// success!
if (mailobj.revealEmail) {
msg = "Mail sent to " + jrhMisc.stringArrayToNiceString(sendMailResult.accepted) + ".";
} else {
msg = "Mail sent.";
}
jrContext.pushSuccess(msg);
return;
}
// error
if (mailobj.revealEmail) {
msg = "Failed to send email to " + jrhMisc.stringArrayToNiceString(sendMailResult.rejected) + ".";
} else {
msg = "Failed to send email.";
}
jrContext.pushError(msg);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/**
* Send a message to a recipient
* The mechanism is usually email, but could be sms, etc. based on recipient object
*
* @param {JrContext} jrContext
* @param {object} recipient
* @param {string} subject
* @param {string} message
* @param {object} extraData
* @param {boolean} flagBypassRateLimitChecks
*/
async sendMessage(jrContext, recipient, subject, message, extraData, flagBypassRateLimitChecks) {
if (!flagBypassRateLimitChecks) {
// ATTN: TODO rate limiting checks here
}
// add extra data
if (!jrhMisc.isObjectEmpty(extraData)) {
// pretty print extra data into message
message += "\n" + jrhMisc.objToString(extraData, false);
}
if (recipient.email) {
// there's an email address
const mailobj = {
revealEmail: true,
subject,
text: message,
to: recipient.email,
};
await this.sendMail(jrContext, mailobj);
}
// other things we might check for would be sms
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
/**
* Send an email object
*
* @param {object} mailobj - suitable for sending to mailTransport.sendMail
* @returns jrResult holding success or error
*/
async sendMail(jrContext, mailobj) {
// add from field
if (!mailobj.from) {
mailobj.from = this.defaultFrom;
}
if (this.flagDebugMode) {
// don't actually mail, instead just log it to console and file
jrdebug.debug("Config flag mailer:DEBUG set, so mail with subject \"" + mailobj.subject + "\" to \"" + mailobj.to + "\" not actually sent (sending mail to debug log instead).");
await arserver.logr(jrContext, appdef.DefLogTypeDebug + ".mailer", "mailer:DEBUG option preventing mail from being sent", mailobj);
jrContext.pushSuccess("Mail sent (but only to log because of mail debug flag).");
return;
}
const sendMailResult = await this.mailTransport.sendMail(mailobj);
jrdebug.cdebugObj("misc", sendMailResult, "Result from sendMail.");
// convert sendmail response to our internal result format of success or error
this.addSendmailRetvToContext(jrContext, sendMailResult, mailobj);
}
//---------------------------------------------------------------------------
}
// export the class as the sole export
module.exports = new SendAid();