Amazon Simple Email Service (SES)

What is Amazon SES ?

  • Amazon SES is an email platform that provides an easy, cost-effective way for you to send and receive email using your own email addresses and domains.With Amazon SES, you can send transactional email, marketing messages, or any other type of high-quality content to your customers.
  • Every Amazon SES account has its own set of sending limits. These limits are:
  • Sending quota—the maximum number of recipients that you can send email to in a 24-hour period.
  • Maximum send rate—the maximum number of recipients that you can send email per second.

Benefits:

  1. Integrate quickly
  2. Optimize your deliverability
  3. Send messages efficiently
  4. Scale securely
  5. You can use Amazon SES to send 62,000 emails every month at no additional charge.

Verification of email addresses and domains

Before you can send email using Amazon SES, You need to verify the email address or domain from which you want to send. The verification status of email addresses and domains also differs across AWS Regions. For example, if you verify a domain in the US West (Oregon) Region, you can’t use that domain to send email in the US East (N. Virginia) Region until you complete the verification process again for that Region. 

Amazon SES using configuration sets 

Configuration sets are the groups of rules that you can apply to your verified identities. A verified identity is a domain or email address you use to send email through Amazon SES When you apply a configuration set to an email, all of the rules of the configuration set are applied to the email.

Tracking deliveries, opens, clicks, failures and complaints for Amazon SES

There are various ways to monitor email sending events if you use Amazon Simple Email Service (SES). Email sending events refer to metrics related to emails you send from the service. These are:

  1. Sends – Emails that have reached Amazon SES
  2. Rejects – Emails Amazon SES did not attempt delivery on. A reason for this could be if it contained a virus for example.
  3. Bounces – Emails that were sent but rejected by the receiver’s mail server or SES. This could
  4. happen if the email address does not exist for example.
  5. Complaints – Emails marked as spam by recipient
  6. Deliveries – Emails successfully delivered
  7. Opens – Emails that have been opened
  8. Clicks – Link within email was clicked
  9. Rendering Failures – Template rendering issue with email. This will only happen if you are using Amazon SES Templates

Set up Amazon Simple Notification Service (Amazon SNS) to notify you of your emails that bounced, complained, or were successfully delivered to the recipient’s mail server. When you use Amazon SES to receive emails, your email content can be published to Amazon SNS topics

Below are the steps to follow to configure SNS notifications :

  1. Create Config Set
var params = {
        ConfigurationSet: { /* required */
            Name: csName /* required */
        }
    };

    ses.createConfigurationSet(params, function(err, data) {
        if (err) 
           console.log(err, err.stack); // an error occurred
        else 
           console.log(data); // successful response
    });
    

2. Create an SNS Topic

const snsTopic = sns.createTopic({
    Name: topicName,
    Attributes: {
        DisplayName: "Email Notification " + clientId,
    },
}).promise()

3. Subscribe to an SNS topic

const subscribePromise = sns.subscribe({
                Protocol: 'HTTPS',
                TopicArn: snsTopic.TopicArn,
                Endpoint: endPointUrl, ,
                ReturnSubscriptionArn: true
            }).promise();

4. Configure Event Destination

 //Add Event Destination Programmatically
 var params = {
    ConfigurationSetName: configureSetName,
    /* required */
    EventDestination: { /* required */
        MatchingEventTypes: [ /* required */
            "send", "reject", "bounce", "complaint", "delivery", "open", "click",
            /* more items */
        ],
        Name: eventDestinationName,
        /* required */
        Enabled: true,
        SNSDestination: {
            TopicARN: topicArn /* required */
        }
    }
};
ses.createConfigurationSetEventDestination(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else console.log(data); // successful response
});

5. Enable or Disable Reputation Metrics

var params = {
    ConfigurationSetName: csName,
    Enabled: enabled
};
ses.updateConfigurationSetReputationMetricsEnabled(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else console.log(data); // successful response
});

Creating the script to track the email notification

We need to confirm the endpoint before Amazon SES can send events data to it. Amazon will Post and SubscribeUrl parameter to the endpoint.We need to add these code for confirm the subscription of the Topic and for Notification

const express = require('express');
const app = express()
const http = require("http");
const port = 4000;
const bodyParser = require('body-parser');
const request = require('request');

app

    .use(express.json({ limit: "50mb", extended: true }))
    .use(express.static("public"))
    .use(
        express.urlencoded({
            extended: false,
            limit: "100mb"
        })
    )

app.use(function(req, res, next) {
    if (req.get('x-amz-sns-message-type')) {
        req.headers['content-type'] = 'application/json';
    }
    next();
});
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: false }));

app.post('/email_notification/', function(req, res) {

    if (req.body.Type === 'SubscriptionConfirmation') {

        const promise = new Promise((resolve, reject) => {
            const url = req.body.SubscribeURL

            request(url, (error, response) => {
                if (!error && response.statusCode == 200) {
                    console.log('Yess! We have accepted the confirmation from AWS')
                    return resolve()
                } else {
                    return reject()
                }
            })
        })

        promise.then(() => {
            return res.end("ok")
        })
    }


    const body = req.body.Message;

    // If there is no event type, then we've got nothing
    if (!body.eventType) { return res.end() }

    // What's the event?
    const event = body.eventType.toLowerCase();
    const eventData = body;

    console.log('========================eventType', eventType);
    const domain = eventData.mail.tags['ses:from-domain'][0]
    const messageId = eventData.mail.messageId
    const date = new Date(eventData.mail.timestamp)
    const email = eventData.mail.destination[0]
    const subject = eventData.mail.commonHeaders.subject

    // #todo: Verify event is from SES

    if (event == 'click') {
        const ua = eventData.click.userAgent
        const url = eventData.click.link
            // do stuff here
    } else if (event == 'open') {
        const ua = eventData.open.userAgent
            // do stuff here
    } else if (event == 'delivery') {
        // do stuff here
    } else if (event == 'complaint') {
        const ua = eventData.complaint.userAgent
            // do stuff here
    } else if (event == 'reject') {
        const ua = eventData.complaint.userAgent
        const reason = eventData.reject.reason
            // do stuff here
    } else if (event == 'bounce') {
        const description = eventData.bounce.bouncedRecipients[0].diagnosticCode
            // do stuff here
    } else {
        // Not supported
        // do stuff here
    }

    // anything else can come in here

    return res.end("ok")

})

References:

https://docs.aws.amazon.com/ses/latest/APIReference/API_Operations.html