Skip to main content

Implementing email sending functionality with AWS SES

Greetings

Emailing is a ubiquitous feature in modern applications that requires a reliable service to meet our email needs. Luckily, AWS Simple Email Service (SES) offers a cost-effective and secure solution.

AWS Simple Email Service

AWS SES is an email solution that relieves us of all operational responsibilities. It is an email platform that offers a convenient and affordable method for sending and receiving emails using your own email addresses and domains.

Can I do "that"?

When considering the use of such a service, we typically contemplate these functionalities. Personally, I experienced these aspects when incorporating AWS SES into our recent email feature.
  • Sending simple emails
  • Sending fancy HTML emails
  • Send emails in bulk
  • Send dynamic emails
  • Store template somewhere
  • Use list
  • Use conditions
  • Send attachments
  • Send to multiple recipients
Absolutely! SES indeed supports all of these features. Moreover, it can also be utilized for automatic responses, enabling it to not only send but also receive emails.

AWS SES configuration

AWS imposes restrictions on the usage of unverified email addresses within its email systems. As users of the free tier setup, we are required to confirm the "from" and "to" email addresses beforehand. However, if desired, the restriction can be lifted by contacting AWS for assistance.

Follow the verification steps before proceeding.
https://aws.amazon.com/getting-started/hands-on/send-an-email/

Start small, send a simple email

To simplify matters, let's consider a scenario where we aim to send an email using an application that we have developed.
npm init -y
npm i @aws-sdk/client-ses
import { SendEmailCommand } from "@aws-sdk/client-ses";
import { SESClient } from "@aws-sdk/client-ses";

const REGION = "us-east-1";
const sesClient = new SESClient({ region: REGION });

const createSendEmailCommand = () => {
  return new SendEmailCommand({
    Source: "from@example.com",
    Destination: { ToAddresses: ["to@example.com"] },
    Message: {
      Subject: {
        Data: "Test Email",
      },
      Body: {
        Text: {
          Data: "Hello from AWS SES!",
        },
      },
    },
  });
};

const sendSimpleEmail = async () => {
  try {
    console.log("Sending a simple email.");
    const sendEmailCommand = createSendEmailCommand();
    const result = await sesClient.send(sendEmailCommand);
    console.log("Simple email sent", result);
  } catch (e) {
    console.error("Failed to send email.");
    return e;
  }
};

sendSimpleEmail();
node send-simple-email.js
Review your email inbox where you should find the email sent via SES.

Sending a styled email

Sending raw emails has lost its appeal, particularly in marketing contexts. AWS SES offers extensive capabilities to meet such requirements, allowing us to create dynamic and visually appealing HTML emails. Let's proceed with sending an email resembling the following example.

Within SES, we have the ability to create templates and store them directly in SES. Therefore, let's start by creating the template and uploading it to SES. It's worth noting that I'll be using a combination of values and iterations to showcase the capabilities of SES.

In this example, we use `{{}}` placeholders for dynamic content. 
  • The {{name}} placeholder is replaced with the name we provide. 
  • The {{#each lineItems}} {{/each}} tag creates a loop to iterate through an array of items. Inside the loop, we can access the properties of each item, such as {{name}} and {{price}}. 
  • The {{#if promocode}} {{/if}} tag conditionally displays the promocode section if a promocode value is provided.
Here is the HTML template I created.
<html>
  <head>
    <title>AWS SES E-Mail</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 20px;
      }

      p {
        color: #666666;
        line-height: 1.5;
      }

      table {
        width: 100%;
        border-collapse: collapse;
      }

      th,
      td {
        padding: 8px;
        text-align: left;
        border-bottom: 1px solid #dddddd;
      }

      th {
        background-color: #f2f2f2;
      }

      tr:nth-child(even) {
        background-color: #f9f9f9;
      }

      tr:nth-child(odd) {
        background-color: #ffffff;
      }
    </style>
  </head>
  <body>
    <p>Hi {{name}},</p>
    <p>Here are the shopping items:</p>

    <table>
      <tr>
        <th>Item</th>
        <th>Quantity</th>
        <th>Price</th>
      </tr>
      {{#each lineItems}}
      <tr>
        <td>{{name}}</td>
        <td>{{quantity}}</td>
        <td>{{price}}</td>
      </tr>
      {{/each}}
    </table>

    {{#if promocode}}
    <p>
      Use the code <strong>{{promocode}}</strong> to get a special discount on your next purchase.
    </p>
    {{/if}}

    <p class='footer'>Thank you for shopping with us!</p>
  </body>
</html>
I utilized an online tool to convert HTML into formatted JSON, which allowed me to escape the necessary characters. (https://www.freeformatter.com/json-escape.html)
{
  "Template": {
    "TemplateName": "MyTemplate",
    "SubjectPart": "Greetings, {{name}}!",
    "HtmlPart": "<html>\r\n  <head>\r\n    <title>AWS SES E-Mail<\/title>\r\n    <style>\r\n      body {\r\n        font-family: Arial, sans-serif;\r\n      }\r\n\r\n      body {\r\n        font-family: Arial, sans-serif;\r\n        margin: 0;\r\n        padding: 20px;\r\n      }\r\n\r\n      p {\r\n        color: #666666;\r\n        line-height: 1.5;\r\n      }\r\n\r\n      table {\r\n        width: 100%;\r\n        border-collapse: collapse;\r\n      }\r\n\r\n      th,\r\n      td {\r\n        padding: 8px;\r\n        text-align: left;\r\n        border-bottom: 1px solid #dddddd;\r\n      }\r\n\r\n      th {\r\n        background-color: #f2f2f2;\r\n      }\r\n\r\n      tr:nth-child(even) {\r\n        background-color: #f9f9f9;\r\n      }\r\n\r\n      tr:nth-child(odd) {\r\n        background-color: #ffffff;\r\n      }\r\n    <\/style>\r\n  <\/head>\r\n  <body>\r\n    <p>Hi {{name}},<\/p>\r\n    <p>Here are the shopping items:<\/p>\r\n\r\n    <table>\r\n      <tr>\r\n        <th>Item<\/th>\r\n        <th>Quantity<\/th>\r\n        <th>Price<\/th>\r\n      <\/tr>\r\n      {{#each lineItems}}\r\n      <tr>\r\n        <td>{{name}}<\/td>\r\n        <td>{{quantity}}<\/td>\r\n        <td>{{price}}<\/td>\r\n      <\/tr>\r\n      {{\/each}}\r\n    <\/table>\r\n\r\n    {{#if promocode}}\r\n    <p>\r\n      Use the code <strong>{{promocode}}<\/strong> to get a special discount on your next purchase.\r\n    <\/p>\r\n    {{\/if}}\r\n\r\n    <p class='footer'>Thank you for shopping with us!<\/p>\r\n  <\/body>\r\n<\/html>\r\n"
  }
}
Push the template to aws
aws ses create-template --cli-input-json file://my-aws-ses-template.json --region us-east-1
 aws ses list-templates --region us-east-1
After creating the template in SES, we can proceed to choose this template when sending an email and provide the necessary data as a JSON payload.
import { SendTemplatedEmailCommand } from "@aws-sdk/client-ses";
import { SESClient } from "@aws-sdk/client-ses";

const REGION = "us-east-1";
const sesClient = new SESClient({ region: REGION });

const createSendEmailCommand = (items) => {
  return new SendTemplatedEmailCommand({
    Source: "from@example.com",
    Destination: { ToAddresses: ["to@example.com"] },
    Template: "MyTemplate",
    TemplateData: JSON.stringify(items)
  });
};

const sendEmail = async () => {
  try {
    console.log("Sending templated email.");
    const emailJson = {
      name: "Manjula Jayawardana",
      lineItems: [
        { name: "Apple", quantity: 100, price: 1000.00 },
        { name: "Pomergranate", quantity: 50, price: 2000.00 },
        { name: "Mango", quantity: 200, price: 1500.00 }
      ],
      promocode: "SUMMER100"
    };
    const sendEmailCommand = createSendEmailCommand(emailJson);
    const result = await sesClient.send(sendEmailCommand);
    console.log("Simple email sent", result);
  } catch (e) {
    console.error("Failed to send email.", e);
  }
};

sendEmail();
node send-template-email.js
That's it, folks! Incorporate SES into your project and experience its tremendous benefits. It is an incredibly valuable tool that can greatly assist you along the way.

Happy learning ☺

References


Comments