Transactional Email & Templated Email for NodeJS done right
Clear Separation of Concerns
Supports any Template Engine (e.g. Underscore Templates)
Mailing.compile(mailDir, {templateEngine: engine});Supports any Mail Provider (e.g Mandrill)
Mailing.compile(mailDir, {mailProvider: require('transacemail-mandrill')('apikey')});Supports any number of CSS files for each email. CSS is automatically inlined for free thanks to Juice
Supports any file extension
Mailing.Mail.DEFAULT_HTML_EXT = ".html";Mailing.Mail.DEFAULT_TEXT_EXT = ".text";Mailing.Mail.DEFAULT_META_EXT = ".meta.js";See the working example code . We accept pull-requests!
My name is Francois-Guillaume Ribreau, I discover, share (twitter), learn (blog), code (github), do.
| Option name | Type | Description |
|---|---|---|
| path | String | Path to mails folder |
| options | Object | Option object option parameters are: templateEngine : Set the Template Engine mailProvider : Set the Mail Provider |
Mailing Factory
Mailing.compile = function(path, options){
var mailing = new Mailing(options);
return mailing._reset(path);
};
| Option name | Type | Description |
|---|---|---|
| args... | Variadic | Any number of arguments that will be forwarded to each email `.sendIf` |
Send emails that comply with .sendIf(args, ...)
Mailing.prototype.sendIf = function(){
var deferred = Q.defer();
var args = _.toArray(arguments);
function mailChecker(mail, fn){
mail.sendIf.apply(mail, args.concat(this._sendThroughProvider.bind(this, function(err, ok){
// We must silent the error otherwise forEachLimit will be stopped
fn(null, ok);
}, mail)));
}
async.forEachLimit(
this.mails,
Mailing.MAIL_INTERNAL_CONCURRENT_LIMIT,
mailChecker.bind(this),
deferred.makeNodeResolver());
return deferred.promise;
};
Mailing.prototype.getMail = function(name){
return _.find(this.mails, function(mail){
return mail.getName() === name;
});
};
Helper to send one email (beware the sendIf function must accept the parameters)
Mailing.prototype.sendMail = function(templateName
args... , fn
){
var args = _.toArray(arguments).slice(1);
var fn = args.pop();
if(!_.isFunction(fn)){throw new Error(".sendMail: last parameter must be a function");}
var mail = this.getMail(templateName);
if(!mail){return fn(new Error("Template not found"));}
args.push(this._sendThroughProvider.bind(this, fn, mail));
mail.sendIf.apply(mail, args);
};
Default mail provider
Mailing.mailProvider = {
send: function(fn, mail){
throw new Error(Mailing.MAIL_PROVIDER_ERR);
}
};
Default template engine (Underscore template)
Mailing.templateEngine = {
compile:function(templateString){
return _.template(templateString, null, {
evaluate: /\{\{#([\s\S]+?)\}\}/g, // {{# console.log("blah") }}
interpolate: /\{\{[^#\{]([\s\S]+?)[^\}]\}\}/g, // {{ title }}
escape: /\{\{\{([\s\S]+?)\}\}\}/g // {{{ title }}}
});
},
exec: function(compiledTemplate, data){
return compiledTemplate(data);
}
};