Skip to content

Instantly share code, notes, and snippets.

@foxbunny
Created July 29, 2011 14:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foxbunny/1113923 to your computer and use it in GitHub Desktop.
Save foxbunny/1113923 to your computer and use it in GitHub Desktop.
Nodemailer wrapper
var fs = require('fs'),
path = require('path'),
nodemailer = require('nodemailer'),
template = require('template'),
cache = {},
config = require('../config');
function MailerError(msg) {
this.msg = msg;
}
MailerError.prototype.toString = function() {
return this.msg;
};
// Configure the mailer
if (!config.email || !config.email.mailer) {
throw new MailerError('Missing mailer configuration');
} else {
nodemailer.SMTP = config.email.mailer;
}
// Loads template from the template directory specified in config
//
// Filenames are expected to reside in the specified directory, and to have a
// ``.email`` extension. Relative paths are also supported. For exampple, to
// load an email template that is in ``notifications`` subdirectory, you can
// call loadTemplate like so:
//
// loadTemplate('notifications/reset', function(err, data) {
// // Do something with the template here
// });
//
// The extension can be changed using the configuration option in the config
// module.
//
// @param name, name of the tempate, including any path prefixes
// @param next, callback to be executed after loaded (expects err, data)
// @api private
function loadTemplate(name, next) {
var extension = config.email.extension || '.email',
filename = path.join(config.email.templates, name + extension);
if (cache[filename]) {
next(null, cache[filename]);
} else {
fs.readFile(filename, function(err, data) {
if (!err) {
cache[filename] = template.create(data.toString());
next(null, cache[filename]);
} else {
next(err, null);
}
});
}
}
// Send out email using node mailer
//`
// Send out templated email using node mailer. The supplied data will be
// interpolated into the specified template automatically.
//
// HTML template is not required. If the HTML template is not found, it will
// not be used. HTML templates are expected to have a '.html.email' extension,
// and be called the same as plain-text body template.
//
// Other than standard node mailer options, you can specify a few additional
// options: ``options.template``, and ``options.data``. You don't need to
// specify separate templates for plain-text and HTML templates. It is
// assumed that the HTML template is called the same as plain-text one, but
// with '.html.email' extension instead of just '.email'. Data is a JavaScript
// object that is passed to the template prior to rendering.
//
// Some of the node mailer options will be overriden by sendEmail function.
// Notably, subject will be prefixed by ``config.email.subjectPrefix`` string
// if one is set, and sender will be overridden by ``config.email.sender``
// option. If sender option is not specified, ``config.email.mailer.user``
// will be used instead. Reply-to field will be discarded, and body, and html
// fields will be set using the specified templates.
//
// @parm options, email options (same as those for node mailer)
// @param next, callback to be executed once the email is sent
exports.sendEmail = function(options, next) {
var realOptions = {};
realOptions.data = options.data || {};
realOptions.template = options.template;
if (!realOptions.template) {
throw new MailerError('Cannot send email without template');
}
realOptions.subject = config.email.subjectPrefix + ' ' + options.subject;
realOptions.sender = config.email.sender || config.email.mailer.user;
realOptions.bcc = options.bcc;
// Load plain-text template
loadTemplate(realOptions.template, function(err, tmpl) {
if (err) {
throw new MailerError('Could not load template ' + realOptions.template);
} else {
realOptions.body = tmpl(realOptions.data);
// Load HTML template
loadTemplate(realOptions.template + '.html', function(err1, tmpl1) {
if (!err1) {
realOptions.html = tmpl1(realOptions.data);
}
// Send email
nodemailer.send_mail(realOptions, next);
});
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment