diff --git a/README.md b/README.md index be172a2..8be98a4 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Email helper for KeystoneJS and Node.js Applications. Makes it easy to send dyna Features include: * Express-like template system (including support for any express-compatible template engine) -* Support for different email sending services (Mandrill and Mailgun are available now, more may be added) +* Support for different email sending services (Mandrill, Mailgun and AWS SES are available now, more may be added) * Understands Keystone User models, making it easy to send emails to the results of a query * Automatically transforms user variables into the correct format for each email service, for mail-merge style variable use * CSS Stylesheets are automatically inlined for robust email client compatibility @@ -110,6 +110,21 @@ The following `send()` options are applicable when using `nodemailer` as the tra See [the Nodemailer README](https://github.com/nodemailer/nodemailer) for more information about supported transports and plugins. +## Usage with AWS SES + +The following `send()` options are applicable when using `awsses` as the transport: + +- `apiKey` (required, String) Your API Key, defaults to `process.env.AWS_SES_API_KEY` +- `apiSecret` (required, String) Your Secret Key, defaults to `process.env.AWS_SES_SECRET_KEY` +- `region` (required, String) Your Sending Region i.e., us-east-1, defaults to `process.env.AWS_SES_REGION` +- `from` (String or Object) The name and email to send from (see below) +- `inline_css` (Boolean) inline CSS classes in your template, defaults to `true` +- `to` (String, Object or Array) The recipient(s) of the email (see below) +- `cc` (String, Object or Array) The CC recipient(s) of the email (same format as `to`, see below) +- `bcc` (String, Object or Array) The BCC recipient(s) of the email (same format as `to`, see below) + +See [the AWS SES API Docs](http://docs.aws.amazon.com/ses/latest/APIReference/API_SendEmail.html) for the full set of supported options. + ## From option The `from` option can be a String (email address), or Object containing `name` and `email`. In the object form, `name` can also be an object containing `first` and `last` (which will be concatenated with a space). This simplifies usage with `User` models in KeystoneJS. For example: @@ -181,6 +196,10 @@ You could previously use a directory as the template name, and Keystone.Email wo Keystone would previous return errors if the subject, contents, recipient(s) or the sender address were invalid. This is no longer handled by the library, please make sure you validate these options before sending the emails. If the transport validates these options, errors will be passed directly to the callback. +### AWS SES limitations + +AWS SES does not support click tracking + ## License MIT Licensed. Copyright (c) 2016 Jed Watson. diff --git a/lib/transports/awsses/getSendOptions.js b/lib/transports/awsses/getSendOptions.js new file mode 100644 index 0000000..af683bd --- /dev/null +++ b/lib/transports/awsses/getSendOptions.js @@ -0,0 +1,31 @@ +var assign = require('object-assign'); + +var getRecipientsAndVars = require('../mailgun/getRecipientsAndVars'); +var processAddress = require('../../util/processAddress'); + +var defaultOptions = { + accessKeyId: process.env.AWS_SES_API_KEY, + secretAccessKey: process.env.AWS_SES_SECRET_KEY, + region: process.env.AWS_SES_REGION || 'us-east-1', +}; + +function getSendOptions (options) { + // default options + options = assign({ Destination: {} }, defaultOptions, options); + // process from name and email + options.Source = processAddress(options.from).address; + // process recipients, including cc and bcc + options.Destination.ToAddresses = getRecipientsAndVars(options.to).recipients; + // handle cc + if (options.cc && options.cc.length > 0) { + options.Destination.CcAddresses = getRecipientsAndVars(options.cc).recipients; + } + // handle bcc + if (options.bcc && options.bcc.length > 0) { + options.Destination.BccAddresses = getRecipientsAndVars(options.bcc).recipients; + } + // return + return options; +} + +module.exports = getSendOptions; diff --git a/lib/transports/awsses/index.js b/lib/transports/awsses/index.js new file mode 100644 index 0000000..a64cfa9 --- /dev/null +++ b/lib/transports/awsses/index.js @@ -0,0 +1,39 @@ +var assign = require('object-assign'); +var aws = require('aws-sdk'); +var juice = require('juice'); +var getSendOptions = require('./getSendOptions'); + +function send (email, options, callback) { + // init options + options = assign({ Message: { Subject: {}, Body: { Html: {} } } }, getSendOptions(options), email); + + // validate + if (!options.Destination.ToAddresses.length) { + return callback(new Error('No recipients to send to')); + } + + // handle html body + options.Message.Body.Html.Data = options.inlineCSS ? juice(options.html) : options.html; + + // add subject + if (options.subject) { + options.Message.Subject.Data = options.subject; + } + + // init aws + aws.config.accessKeyId = options.apiKey; + aws.config.secretAccessKey = options.apiSecret; + aws.config.region = options.region; + + // init ses + var ses = new aws.SES({ apiVersion: '2010-12-01' }); + + // send emails + ses.sendEmail({ + Message: options.Message, + Destination: options.Destination, + Source: options.Source, + }, callback); +} + +module.exports = send; diff --git a/package.json b/package.json index a45ed6a..8d82f7d 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "Email helper for KeystoneJS Apps", "main": "index.js", "dependencies": { + "aws-sdk": "^2.7.11", "debug": "^3.1.0", "html-to-text": "^4.0.0", "juice": "^4.3.1", @@ -24,11 +25,11 @@ "pug": "^2.0.3" }, "scripts": { - "test": "npm run lint && npm run test-unit", - "test-unit": "mocha tests", - "coverage": "istanbul cover _mocha tests", "codeclimate": "codeclimate-test-reporter < coverage/lcov.info", - "lint": "eslint . --ignore-path .gitignore" + "coverage": "istanbul cover _mocha tests", + "lint": "eslint . --ignore-path .gitignore", + "test": "npm run lint && npm run test-unit", + "test-unit": "mocha tests" }, "repository": { "type": "git", @@ -38,8 +39,10 @@ "email", "keystone", "keystonejs", - "mandrill", - "mailgun" + "mailgun", + "ses", + "aws", + "mandrill" ], "author": "Jed Watson", "license": "MIT", diff --git a/tests/index.js b/tests/index.js index 32b58e0..b0991b9 100644 --- a/tests/index.js +++ b/tests/index.js @@ -51,8 +51,10 @@ describe('utils', function () { it('should return transport if transport is found', function () { var res1 = getTransport('mailgun'); var res2 = getTransport('mandrill'); + var res3 = getTransport('awsses'); assert.equal(typeof res1, 'function'); assert.equal(typeof res2, 'function'); + assert.equal(typeof res3, 'function'); }); });