Category Archives: NodeJS

Creating a Deliverable HTML Email on AWS Lambda with SES

Creating deliverable rich html emails is a great goal for many web applications, communicating with your customers, and helping to send the messages that are beautiful and make your marketing/designers happy.

As discussed in this send grid article, there are quite a number of approaches for doing this, but one of the best options for ensuring that images in emails with images. The leaders today in 2017 are using cid and referencing attachments, and using data urls.

According to the comments in this Campaign Monitor blog post, the cid method is supported by all the major clients today. (ironically the post is talking about using the cooler approach of data urls for images).

With this background, the question is how to do this with AWS Lambda and SES.

Thankfully it’s really straight forward.

The simple steps are:

  • create a simple html email that references images using cid: as the protocol.
  • create a raw rfc822 email string that can be sent with the SES api.
  • use the ses.sendRawEmail method to send the email.

1 Create a simple html email

For example:

<html><body><p>Hello world</p><img src=”cid:world”></body></html>

Note that the source of the image is of the format cid:world, this cid will be what you specify when attaching the image to the blog post

2 Create a raw rfc822 email string

The mailcomposer  package a part of Nodemail(https://nodemailer.com/extras/mailcomposer/) provides a great simple easy to use api for creating rfc822 emails with attachments. When creating attachments you can specify cids to refer to them by, and you can specify the contents of the attachment with a local filename, a buffer, or even a http resource. It’s a great api.  Take a look at the npm page to see more. One example of using this package is:

let from = 'from@example.com';
let to = 'to@example.com';
let subject = 'Subject';
let htmlMessage = '<html><body><p>Hello world</p><img src="cid:world"></body></html>';
let mail = new MailComposer({
  from: from, to: to, subject: subject, html: htmlMessage,
  attachments: [{
    filename: 'hello-world.jpg',
    path: 'https://cdn.pixabay.com/photo/2015/10/23/10/55/business-man-1002781_960_720.jpg',
    cid: 'world'
  }]
});
mail.build(function(err, res) {console.log(res.toString())});

3 Send the email with SES

Take the buffer that you create and send it with SES.

let sesParams = {
  RawMessage: {
    Data: message
  },
};
ses.sendRawEmail(sesParams, function(err, res){console.log(err, res)});

Full example using promises

Let’s put it all together, and pull in some of the promise code that I talked about in an earlier blog post(http://www.rojotek.com/blog/2017/04/11/create-a-promise-wrapper-for-a-standand-node-callback-method/)

function createEmail(){
  let from = 'from@example.com';
  let to = 'to@example.com';
  let subject = 'Subject';
  let htmlMessage = '<html><body><p>Hello world</p><img src="cid:world"></body></html>';
  let mail = new MailComposer({
    from: from, to: to, subject: subject, html: htmlMessage,
    attachments: [{
      filename: 'hello-world.jpg',
      path: 'https://cdn.pixabay.com/photo/2015/10/23/10/55/business-man-1002781_960_720.jpg',
      cid: 'world'
    }]
  });

  return new Promise((resolve, reject) => {
    mail.build(function(err, res) {
      err ? reject(err) : resolve(res);
    });
  });
}
createEmail().then(message =>{
  let sesParams = {
    RawMessage: {
      Data: message
    },
  };
  return ses.sendRawEmail(sesParams).promise();
});

Creating emails that include attachments is really quite easy with node, lambda and ses. Doing this is a great step to delivering rich emails that look like what your designers want.

 

Create a Promise Wrapper For a Standand Node Callback Method

JavaScript Promises are the future, and a great pattern for doing asynchronous javascript code (allegedly async await is an awesome way to do async javascript as well, but I’m not there yet). There are great APIs for working with promises, and many standard libraries for working with Promises.

Unfortunately not all libraries support promises. Fortunately it isn’t hard to wrap a standard javascript callback pattern api in a promisified version.

The Node.js way is to have callbacks with an error first callback. These are apis which are passed a callback function with the signature function(error, success);. For a good description see this decent blog post The Node.js Way – Understanding Error-First Callbacks.

The classic example they provide is read file:

fs.readFile('/foo.txt', function(error, data) {
  // TODO: Error Handling Still Needed!
  console.log(data);
});

To convert this to a promise, create a new promise object, which calls reject with the error, and resolve with the data. If this is wrapped in a function, you’ll end up with a nice promisified readFile as per the following:

const fs=require('fs');

function readFilePromise(fileName) {
  return new Promise(function(resolve, reject){
    fs.readFile(fileName, function(err, data){
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

For extra cool kid points, use arrow functions:

const fs=require('fs');

let readFilePromise = fileName => {
  new Promise((resolve, reject) => {
    fs.readFile(fileName, (err, data)=> {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    })
  })
}

 

or to shrink it a little bit more:

const fs=require('fs');

let readFilePromise = fileName => {
  return new Promise((resolve, reject) => {fs.readFile(fileName, (err, data)=> {err ? reject(err) : resolve(data)})})
}

or to go a bit crazy with the inlining, and make your javascript look almost like haskell 🙂

const fs=require('fs');

let readFilePromise = fileName => new Promise((res, rej) => fs.readFile(fileName, (e, d) => e ? rej(e) : res(d)));

So it’s easy to see that any asynchronous node callback style api can be wrapped in a promise api with 10 lines of readable code, or 1 line of terse javascript.