Skip to content

Instantly share code, notes, and snippets.

@joenoon
Created October 9, 2017 00:59
Show Gist options
  • Save joenoon/9c35954b9065f67464926e713191fc4a to your computer and use it in GitHub Desktop.
Save joenoon/9c35954b9065f67464926e713191fc4a to your computer and use it in GitHub Desktop.
This is a simple wrapper around mailgun.send that adds easy templating and forces tags to be used.
//
// MailgunSender
// Copyright 2017 Joe Noon <[email protected]>
// MIT License
//
// This is a simple wrapper around mailgun.send that adds easy templating and forces
// tags to be used.
//
// Initialize a MailgunSender with the path to your templates, and instance of mailgun:
//
// const mailgunSender = new MailgunSender({
// path: require('path').join(__dirname, './templates/'),
// mailgun: require('mailgun-js')({ apiKey: "key-xyz", domain: 'mydomain.local' }),
// });
//
// The template path should be structured like this:
// ./
// - news.html
// - news.txt
// - welcome.html
// - bye.txt
//
// If both an html and txt are given for the same name, both parts will be sent to mailgun.
// Otherwise only the part you provide will be sent.
//
// Send mail
//
// const res = await mailgunSender.send({
// from: 'Me <[email protected]>',
// to: '[email protected]',
// subject: 'Hello',
// tags: ['tag1', 'tag2'],
// template: 'news',
// });
//
// Required: `from`, `to`, `subject`, `tags`
// `template` OR one or both of `html`, `text`
// Optional: `template_locals` - passed to ejs template
//
const ejs = require('ejs');
const _path = require('path');
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
const readdir = util.promisify(fs.readdir);
function MailgunSender ({path,mailgun}) {
const templates = {};
let loaded = false;
const load_templates = async () => {
if (loaded) return;
loaded = true;
const files = await readdir(path, 'utf8');
for (const file of files) {
const content = await readFile(_path.join(path, file), 'utf8');
const template = ejs.compile(content);
const parts = _path.parse(file);
const {name,ext} = parts;
templates[name] = {
...templates[name],
[ext]: template,
}
}
};
this.send = async ({from,to,subject,tags,template,template_locals,...rest}) => {
if (!from) throw new Error('from required');
if (!to) throw new Error('to required');
if (!subject) throw new Error('subject required');
if (!tags) throw new Error('tags required');
const opts = {
from,
to,
subject,
'o:tag': tags,
...rest
};
if (template) {
await load_templates();
const tparts = templates[template] || {};
const html_t = tparts['.html'];
if (html_t) opts.html = html_t(template_locals);
const text_t = tparts['.txt'];
if (text_t) opts.text = text_t(template_locals);
}
if (!opts.html && !opts.text) throw new Error(`no html or text rendered. check that template '${template}' is defined.`);
const res = await mailgun.messages().send(opts);
return res;
}
}
module.exports = MailgunSender;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment