AWS SES: How to send a mail with an attachment in Node.js

By Sateesh Gandipadala

November 6th, 2020

image

In this article, I will explain how to send attachments using AWS SES and this article is for the people who already know how to send a simple email using SES.

SES allows sending attachments only through ***sendRawEmail ***method.

sendRawEmail accepts Multipurpose Internet Mail Extensions (MIME) type email body as data, so let's see how to prepare MIME type email content.

A typical MIME email looks like the above example, it is a multipart email with the content in both HTML format and text format and it contains a text file as an attachment.

We can create a string like the above example and send as data to sendRawEmail, but it will be very confusing to format this long string. To simplify the MIME body creation we can use npm module like mimemessage. Install the mimemessage npm module as shown below.

npm i mimemessage

mimemessage module helps us in creating the email with less hassle. First, we need to create mailContent using mimemessage factory method as shown below. All the mail content will be attached to this object.

var mimemessage = require('mimemessage');

var mailContent = mimemessage.factory({contentType: 'multipart/mixed',body: []});

Now, let us add the headers to this.

mailContent.header('From', 'Sender Name <sender@example.com>');
mailContent.header('To','recipient@example.com');
mailContent.header('Subject', 'Customer service contact info');

Now, we added the headers, let us add the mail content. Using MIME email type we can add both text and HTML variation of the same email content. To have both variations first we need to create a *multipart/alternative *object.

var alternateEntity = mimemessage.factory({
    contentType: 'multipart/alternate',
    body: []
});

Now we need to create both HTML and text entities and add to the above alternateEntity.

var htmlEntity = mimemessage.factory({
   contentType: 'text/html;charset=utf-8',
   body:  '   <html>  '  + 
          '   <head></head>  '  + 
          '   <body>  '  + 
          '   <h1>Hello!</h1>  '  + 
          '   <p>Please see the attached file for a list of    customers to contact.</p>  '  + 
          '   </body>  '  + 
          '  </html>  ' 
 });

var plainEntity = mimemessage.factory({
   body: 'Please see the attached file for a list of    customers to contact.'
});

alternateEntity.body.push(htmlEntity);
alternateEntity.body.push(plainEntiFirstty);

Now we need to add this alternateEntity to the *mailContent *body

mailContent.body.push(alternateEntity);

How to attach a file to the mail

We will be adding attachment also as a part to the main mailContent object. First, we need to read the file and convert the file content into a base64 string, add it as the body of this entity. As shown below, we need to specify the type of content and the encoding used. We need to add a header called *Content-Disposition *with the relevant details.

var data = fs.readFileSync('customers.txt');

var attachmentEntity = mimemessage.factory({
contentType: 'text/plain',
contentTransferEncoding: 'base64',
body: data.toString('base64').replace(/([^**\0**]{76})/g, "$1\n")
});

attachmentEntity.header('Content-Disposition', 'attachment ;filename="customers.txt"');

Now attach this entity to the main mailContent.

mailContent.body.push(attachmentEntity);

Finally, our mail object is ready, we need to pass this to SES sendRawEmail method as shown below.

ses.sendRawEmail({
    RawMessage: { Data: mailContent.toString() }
}, (err, sesdata, res) => {

});

If we configure properly we will receive a success message in the callback.

Note: SES allows only 10MB file as an attachment



Continue Learning