open311-smtp
Version:
smtp mail transport for open311 messages
338 lines (269 loc) • 7.18 kB
JavaScript
;
/**
* @module open311-smtp
* @version 0.1.0
* @description smtp mail transport for open311-messages
* @see {@link https://github.com/CodeTanzania/open311-messages}
* @see {@link https://github.com/nodemailer/nodemailer}
* @author lally elias <lallyelias87@gmail.com>
* @public
*/
//dependencies
const _ = require('lodash');
const async = require('async');
const kue = require('kue');
const messages = require('open311-messages');
const nodemailer = require('nodemailer');
const striptags = require('striptags');
const noop = function () {};
/**
* @name defaults
* @description default configuration options
* @type {Object}
* @since 0.1.0
* @private
*/
exports.defaults = {
//default queue time to wait to shutdown
timeout: 5000,
//default number of worker to spawn on processing mails
concurrency: 10,
//default mail sender if non provided during send
from: 'codetanzania@gmail.com',
//default smtp port to connect
port: 465,
//default smtp server hostname or IP address to connect
host: 'smtp.gmail.com',
//defines if the connection should use SSL
secure: true,
// default authentication data
auth: {
user: 'codetanzania@gmail.com', //username
pass: 'code@tanzania' //password for the user
}
};
/**
* @name queueName
* @description name of the queue that will be used by smtp transport
* to enqueue message for sending
* @type {String}
* @since 0.1.0
* @public
*/
exports.queueName = 'smtp';
/**
* @name transport
* @description name of the transport provided by smtp.
*
* This must be name of node module or file path pointing to
* a node module implement `send()`.
*
* @type {String}
* @since 0.1.0
* @public
*/
exports.transport = 'open311-smtp';
/**
* transport message send mode
*/
// exports.mode;
/**
* transport message type i.e email, sms, push etc
*/
// exports.type;
/**
* @name init
* @description initialize smtp internals
* @since 0.1.0
* @private
* @see {@link exports.defaults}
* @example
*
* const smtp = require('open311-smtp');
* smtp.options = {
* port: <your_smtp_server_port>,
* host: <your_smtp_host>,
* auth:{
* user:<your_smtp_account_username>,
* password:<your_smtp_account_password>
* }
* };
* smtp.init();
*
*/
exports.init = function () {
//merge options
exports.options = _.merge({}, exports.defaults, exports.options);
//initialize open311-messages
if (!exports.Message) {
//instantiate open311-messages
exports.Message = messages(exports.options);
//sent send mode
exports.mode = exports.Message.SEND_MODE_PUSH;
//set message type
exports.type = exports.Message.TYPE_EMAIL;
}
//initialize worker processing queue
//for internal usage
if (!exports._queue) {
exports._queue = kue.createQueue(exports.options);
}
//initiate nodemailer smtp transport
//@see {@link https://nodemailer.com/smtp/}
if (!exports.smtp) {
exports.smtp = nodemailer.createTransport(exports.options);
}
};
/**
* @name queue
* @description queue message instance for sending
* @param {Message} message valid instance of open311-message
* @since 0.1.0
* @public
* @example
*
* const Message = require('open311-messages')(<your_options>);
* const smtp = require('open311-smtp');
* const message = new Message(<details>);
* smtp.queue(message);
*
*/
exports.queue = function (message) {
//ensure is already initialized
exports.init();
//update message with transport details
message.transport = exports.transport;
message.queueName = exports.queueName;
message.mode = exports.mode;
message.type = exports.type;
//ensure from is set-ed
if (!message.from) {
message.from = exports.options.from;
}
message.queue();
};
/**
* @name _send
* @description send email message
* @param {Message} message valid open311-message instance
* @param {Function} done a callback to invoke on success or failure
* @type {Function}
* @since 0.1.0
* @private
*/
exports._send = function (message, done) {
async
.waterfall([
function verifyTransport(next) {
exports.smtp.verify(next);
},
function sendEmail(transportReady, next) {
// TODO validate emails
//convert message to nodemailer email payload
let email = message.toObject();
// set mail html body
if (message.mime === exports.Message.MIME_HTML) {
email.html = email.body;
}
//always set mail text body
email.text = striptags(email.body || email.subject);
exports.smtp.sendMail(email, next);
}
], done);
};
/**
* @name send
* @description implementation of open311 message send to allow send message
* as an email using nodemailer smtp transport
* @param {Message} message valid open311 message instance
* @param {Function} done a callback to invoke on success or failure
* @return {Object|Error} result or error during sending email message
* @type {Function}
* @since 0.1.0
* @public
* @example
*
* const Message = require('open311-messages')(<your_options>);
* const smtp = require('open311-smtp');
* const message = new Message(<details>);
* smtp.send(message, function(error, response){
* ...
* });
*/
exports.send = function (message, done) {
//ensure already initialized
exports.init();
//obtain message additional send options
const options = message.options;
//simulate send
if (options && options.fake) {
done(null, {
message: 'success'
});
}
//send actual email
else {
exports._send(message, done);
}
};
/**
* @name stop
* @description gracefull shutdown kue
* @see {@link https://github.com/Automattic/kue#graceful-shutdown}
* @param {Function} [done] a callback to invoke on succes or failure
* @type {Function}
* @since 0.1.0
* @public
* @example
*
* const smtp = require('open311-smtp');
* smtp.stop();
*
*/
exports.stop = function stop(done) {
//ensure callback
if (!done && !_.isFunction(done)) {
done = noop;
}
//ensure queue safe shutdown
if (exports._queue) {
if (exports._queue.shuttingDown) {
done();
} else {
const { timeout } = exports.options;
exports._queue.shutdown(timeout, done);
}
} else {
done();
}
};
/**
* @name start
* @description setup smtp message(s) worker and start to process
* `smtp` jobs
* @type {Function}
* @since 0.1.0
* @public
* @example
*
* const smtp = require('open311-smtp');
* smtp.start();
*
*/
exports.start = function () {
//ensure already initialized
exports.init();
//reference open311-message model
const Message = exports.Message;
//register worker for processing message
//and send it as email notification
const { concurrency } = exports.options;
exports._queue.process(exports.queueName, concurrency, Message.process);
//listen for process termination
//and gracefull shutdown email worker queue
process.once('SIGTERM', function ( /*signal*/ ) {
exports._queue.shutdown(function ( /*error*/ ) {
process.exit(0);
});
});
};