devmailer
vundefined
Published
devmailer =========
Readme
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: '[email protected]', name: 'Mick', subject: 'Hello Mick', from: '[email protected]' }
]
}, 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: '[email protected]', name: 'Mick', subject: 'Hello Mick', from: '[email protected]' } // Gets the subject Hello Mick
{ to: '[email protected]', name: 'Jan', from: '[email protected]' } // 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*/
...