• Published 11 years ago

devmailer v

Weekly downloads
-
License
-
Repository
-
Last release
11 years ago

API

Some tools for easier generating transactional mail. Built to work with SendGrid & MailChimp. More services will be added if demand presents it self.

Configuration

var devmailer = new require('devmailer').Devmailer({
  tmpDir: __dirname+'/tmp', // devmailer needs access to the filesystem to support partials
  sendgrid: {
    user: 'YOUR USER',
    password: 'YOUR PASSWORD'
  }
});

// Alternatively:
var devmailer = new (require('devmailer')).Devmailer({ ... });

Messages

General re-useable templates for transactional email

var message = new devmailer.Message({
  template: {url: 'http://some.host/email.jade'},
  templatePartials: [
    {url: 'http://some.host/email_header.jade', name: 'header'}
    {url: 'http://some.host/email_footer.jade', name: 'footer'}
  ],
  stylesheet: {url: 'http://some.host/email.css'},
});

devmailer.Message is aliased as devmailer.MessageTemplate

Templates and Stylesheets

Templates and stylesheets can be passed to messages in a few different ways. Templates and stylesheets can be supplied either with a src or a url, if using src or a non-extension url, supply a type aswell. Currently we support jade, mustache and html for templates and css and sass/compass for stylesheets.

For compass/sass support you need to have it installed as a binary (via rubygems). Support via node modules is not a priority currently.

var template;
var stylesheet;

/* Basic HTML with a source */
template = {type: 'html', src: '<p><a href="#"></a></p>'};

/* Basic HTML via a url (with proper extension) */
template = {url: 'http://some.host/email.html'};

/* Basic HTML via a url (without identifying extension) */
template = {type: 'html' url: 'http://some.host/email.template'};

/* Basic HTML via a path (without identifying extension) */
template = { path: '/usr/dev/email.html'};

/* Basic HTML via a path (without identifying extension) */
template = {type: 'html' path: '/usr/dev/email.template'};

/* Basic CSS with a source */
stylesheet = {type: 'css', src: 'p { font-family: Arial}'};

/* Basic CSS via a url (with proper extension) */
stylesheet = {url: 'http://some.host/email.css'};

/* Basic CSS via a url (without identifying extension) */
stylesheet = {type: 'css' url: 'http://some.host/email.stylesheet'};

The types can then be swapped for your specific needs. When supplying templates or stylesheets to a Message they will be wrapped by devmailer.ContentTemplate and devmailer.ContentStylesheet respectively. You can also wrap them yourself, but currently there is no added benefit to this.

CSS Inlining

When supplying the Message with stylesheets we will (after compilation) inline the stylesheet into the markup using juice.

Note: Juice uses jsdom in its inlining proces, which requires you to have a relatively welformed markup. If you get error messages along the lines of cannot read property 'contains' of null or cannot read property 'compareDocumentPosition' of null you are probably missing an <html> or <body> tag.

Partials/Includes

Partials for both templates are supported. They are passed in as regular templates via the option templatePartials. Partials need to be referenced by name, so you can give them a name property in the template options. Partial support for stylesheets will not be supported for the first releases, but might be a thing for the future.

Note: If you have several instances of devmailer.Message, it is not possible to have different partials with the same name in them. E.g., this is not possible:

var message1 = new devmailer.Message({
  template: {url: 'http://some.host/email.jade'},
  templatePartials: [
    {url: 'http://some.host/email_header.jade', name: 'header'}
  ]
};

var message2 = new devmailer.Message({
  template: {url: 'http://some.host/another_email.jade'},
  templatePartials: [
    {url: 'http://some.host/a_totally_different_header.jade', name: 'header'}
  ]
};

Depending on the order in which the partials are loaded asynchronously, either email_header or a_totally_different_header will be injected in both templates when you include header.

Subject and from

Subject and from fields can be specified both on a global or per recipient basis. If you want to specify per recipient, simply add subject and/or from to the recipient object, like this:

message.generate({
  recipients: [
    { to: 'mh@innofluence.com', name: 'Mick', subject: 'Hello Mick', from: 'info@innofluence.com' }
  ]
}, function (err, res) {
  ...
});

If all messages generated from a template should have the same subject / from you can specify it when instantiating Message:

new devmailer.Message({
  template: {
    type: 'mustache',
    src: '<html><p>Hi {{name}}</p></html>'
  },
  subject: 'Hello'
});

If you want all messages from the current batch (current call to send or generate) to have the same subject / from you can specify the as globals:

message.generate({
  globals: {
    subject: 'Hello'
  },
  recipients: [
    { to: 'mh@innofluence.com', name: 'Mick', subject: 'Hello Mick', from: 'info@innofluence.com' } // Gets the subject Hello Mick
    { to: 'mh@innofluence.com', name: 'Jan', from: 'info@innofluence.com' } // Get the subject Hello
  ]
}, function (err, res) {
  ...
});

You can also combine the above, so that some messages use the global values, and some use their own subject / from field. The lookup order is: recipient, globals, message-defaults.

It is also possible to generate subjects and senders from a function, that is passed each recipient. The function can be both synchronous and asynchronous. If the number of arguments to the function is 1, it will be treated as a sync function, otherwise it will be treated as an async function. Async functions are passed recipient data and a callback:

// Sync
new devmailer.Message({
  template: {
    type: 'mustache',
    src: '<html><p>Hi {{name}}</p></html>'
  },
  subject: function (data) {
    return 'Hello '+data.name;
  }
});

// Async
new devmailer.Message({
  template: {
    type: 'mustache',
    src: '<html><p>Hi {{name}}</p></html>'
  },
  subject: function (data, callback) {
    callback(null, 'Hello '+data.name);
  }
});

Transport

Currently devmailer supports sendgrid and custom transport as methods of sending your email:

Sendgrid

devmailer = new Devmailer({
  sendgrid: {
    user: "",
    pass: ""
  }
});

Custom transport

You can provide at custom transport object to override the default transport method. This can be used e.g. to stub sending, so emails are saved to a database instead of being sent. The example below shows usings a custom transport to save messages to redis. A transport object must implement the ´sendMail´ and ´close´ methods.

var redis = require('redis'),
  client = redis.createClient();

client.select(1);
transport = {
  sendMail: function (options, callback) {
    options.timestamp = Math.floor(Date.now() / 1000);
    client.lpush("stub_email:"+options.to, JSON.stringify(options), function (err) {
      callback(err, { message: "Saved to redis as stub_email:"+options.to});
    });
  },
  close: function () {

  }
};

devmailer = new Devmailer({
  transport: transport
});

Usage

var message = new devmailer.Message({
  template: {url: 'http://some.host/email.jade'},
  templatePartials: [
    {url: 'http://some.host/email_header.jade', name: 'header'}
    {url: 'http://some.host/email_footer.jade', name: 'footer'}
  ],
  stylesheet: {url: 'http://some.host/email.css'},
});

/* Send emails */
...

/* Testing */
...

/* Generate email content - mostly for unit tests*/
...