Node TransacEmail

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!

compile

method
Mailing.compile() -> Mailing

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);
};

sendIf

method
Mailing.prototype.sendIf() -> Promise

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;
  });
};

sendMail

method
Mailing.prototype.sendMail()

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);
};

mailProvider

property
Mailing.mailProvider

Default mail provider

Mailing.mailProvider = {
  send: function(fn, mail){
    throw new Error(Mailing.MAIL_PROVIDER_ERR);
  }
};

templateEngine

property
Mailing.templateEngine

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);
  }
};