UNPKG

dataflo.ws

Version:

Zero-code JSON config-based dataflow engine for Node, PhoneGap and browser.

223 lines (184 loc) 6.04 kB
var util = require('util'), path = require('path'), nodemailer = require('nodemailer'), emailTemplates = require('email-templates'), task = require('./base'); /** * Batch sending of emails * - supports templates * - doesn't support guaranteed delivery of emails * - doesn't support guaranteed sending of emails (sends to smtp transport) * however, notifies transport errors to console as warnings. * * The task is completed as soon as all required fields for email sending are * present and all emails are forwarded to smtp transport for sending. * * The task is failed or skipped (depends on @cfg {Boolean} important) if there are problems * with template/contents or recepients list. * * * @cfg {Object} email - basic email data, may be fully or partially generated from template * and list of recepients * * email = { * from: {String}, // optional, defaults to consumerConfig value : sender OR SMTP.auth.user * to: {String}, // can be also named "email" * cc: {String}, * bcc: {String}, * subject: {String}, * text: {String}, * html : {String}, * } * * * @cfg {String} template - name of template * template is ejs based, generates Text and HTML * templates are to be located in <project_root>/templates/email * see details: https://github.com/niftylettuce/node-email-templates * * ! template OR text OR html OR subject MUST be provided * * * @cfg {Array} recepients - list for batch sending * * recepients = ["<email>", "<email>",...] * recepients = [{ * email: {String}, // can be named "to" or otherwise (see below) substitutes email.to * // name,... - other fields used in template * }] * * @cfg {String} emailField - if present recepients[emailField] whill be taken as email.to * * ! email.to OR recepients MUST be provided * */ var mailConfig = project.config.consumerConfig.mail, transport = nodemailer.createTransport("SMTP", mailConfig.SMTP), templatesDir = 'templates/email'; var render = { simple : function (email, recepient, callback) { callback && callback(null, email); }, template : function (template, templateName) { return function (email, recepient, callback) { template(templateName, recepient, function(err, html, text) { if (!err) { util.extend(email, { text: text, html: html }); callback && callback(null, email); } else callback(err); }); }; } }; var mailTask = module.exports = function (config) { this.request = config.request; this.init(config); }; util.inherits (mailTask, task); util.extend (mailTask.prototype, { run: function () { var self = this; var err = false; email = self.email, recepients = self.recepients, template = self.template; if (!email && !template) { return self._err('Neither email object nor template not provided'); } else { if (!email) { email = { to: null, from: null, subject: "" }; } email.to = email.to || email.email; email.sender = email.sender || email.from; if (!email.to && !recepients) return self._err('email.to OR recepients MUST be provided'); if (!email.subject && !email.text && !template) return self._err('email.subject OR email.text OR template MUST be provided'); if (!email.sender) email.sender = mailConfig.sender || mailConfig.from|| mailConfig.SMTP.auth.user; // normalize recepients if (!recepients) { recepients = [{ email : email.to }]; } else { if (!recepients.push) recepients = [recepients]; recepients = recepients.map(function (item) { if (typeof(item) !== 'object') item = { email : item }; return item; }); } if (self.verbose) self.emit('log', 'Starting email job'); console.log('Template ', template, ' Recepients ', recepients); self._prepareRender( template, function () { if (self.verbose) self.emit('log', 'Render ready'); self._batchSend(email, recepients); } ); } }, _err : function (msg, type) { var self = this; type = type || 'error'; self.emit('warn', msg); if (self.type === 'error') if (self.important) self.failed(msg); else self.skipped(msg); }, _prepareRender : function (templateName, callback, errback) { var self = this; if (self.verbose) self.emit('log', 'Preparing render'); if (!templateName) { self._render = render.simple; if (self.verbose) self.emit('log', 'Render simple'); callback && callback(); } else { if (self.verbose) self.emit('log', 'Render template - getting'); emailTemplates(templatesDir, function (err, template) { if (typeof(template) !== 'function') err = 'Incorrect template' + template; if (err) self._err(err); else { if (self.verbose) self.emit('log', 'Render template - OK'); self._render = render.template(template, templateName); callback && callback(); } }); } }, _batchSend : function (email, recepients) { var self = this, emailField = self.emailField || "email"; console.log('Email setup:', email); console.log('SMTP setup:', mailConfig.SMTP); var sendMail = function (err, email) { self._sendMail(err, email); }; for (var i = 0; i < recepients.length; i++) { var recepient = recepients[i]; email.to = recepient[emailField] || recepient.email || recepient.to; if (!email.to || email.length < 6 || email.to.indexOf('@')<0) continue; // ugly skip bad emails self._render(email, recepient, sendMail); } // TODO: track individual mail delivery if needed, for example if 'important' flag is set self.emit('log', 'Emails sent to transport. Actual sending not guaranteed. See further log.'); self.completed(true); }, _sendMail : function (err, email) { var self = this; if (err) return self._err(err, 'warning'); self.emit('log', 'Sending email to ' + email.to); transport.sendMail(email, function (error, response) { if (error) self._err(error, 'warning'); else self.emit('log', 'OK: Email sent to ' + email.to); }); } });