Effective Email Bounce Handling with AWS SNS and SES

Pramod Tolani
Simform Engineering
8 min readSep 26, 2023

A step-by-step guide to set up email bounce handling with AWS SNS, SES, and Express JS Server.

Managing email bounces is crucial for maintaining strong email deliverability rates, particularly in bulk mailings. A bounced email signifies that the message couldn’t reach the recipient’s inbox.

In this guide, we will learn how to set up Bounce handling, connect it to AWS SES and SNS, and update the DB for spam filtering.

Understanding Email Bounces

Email bounces occur when the delivery of a message fails, and the server kicks it back to the sender. A hard bounce means the email address is invalid and will never work, while a soft bounce is temporary due to a full inbox or unavailable server.

If you don’t handle bounce emails correctly, these problematic addresses will persist on your mailing list, resulting in recurring bounces with each campaign. This alerts email providers to poor list hygiene, harming email deliverability.

What is AWS SES?

Amazon Simple Email Service (SES) is AWS’ scalable and extensively accessible email transmission and reception service. SES simplifies the process of sending emails by providing a secure SMTP interface or integration with AWS SDKs. This eliminates the need to manage your own email servers.

Keep reading here.

What is AWS SNS?

Amazon Simple Notification Service (SNS) operates as a managed pub/sub messaging system, overseeing the scaling and coordination of message distribution to various subscribers and endpoints such as email, SQS, Lambda, and HTTP.

Learn more.

Steps to Setup AWS SNS, SES, and Server

Step 1: Create an AWS Free Tier Account

  • Open your web browser and navigate to the AWS Free Tier Page AWS Free Tier Page
  • Click on the “Create a Free Account button.
AWS Home Page
  • Enter your account information and choose “Verify email address” to receive a verification code.
  • Enter the verification code and choose “Verify”.
  • Set a strong password for your root user and continue through the remaining signup steps.
  • There are a few more steps to complete the signup.
  • After verifying your account, you will be redirected to the AWS Console page.
AWS Console Dashboard

Step 2: Setup an AWS SES account (if not already done)

Verify Identities:

Start by establishing an identity and validating the intended email address for sending messages.

  • Access your AWS Management Console account and locate “Simple Email Service” in the search results.
AWS Console Search Result
  • Initiate the verification process for an email address by selecting “Create identity” and adhering to the on-screen guidance.
AWS SES: Create Identities
  • After successful verification, your email address will be shown within the list of confirmed identities in your SES account.
AWS SES: List of Verified Identities

Create SMTP Credentials:

  • To set up SMTP credentials, click Create SMTP credentials to create login details for your SMTP account.
AWS SES: Account Dashboard
  • When you create an SMTP account, it generates an IAM user. Your SMTP details, including IAM username and password, are accessible and can be downloaded as a CSV file.
AWS SES: IAM Console

Step 3: Setup the server route

npm install -g express-generator
express --no-view email-bounce
cd email-bounce
npm install nodemailer body-parser mongoose dotenv

Define routes for SNS HTTP subscriptions.

// app.js

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const bodyParser = require('body-parser');

var indexRouter = require('./routes/index');
var emailRouter = require('./routes/email');

const transporter = require('./utils/email');

require("./db");

var app = express();

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

/**
* Please add the following two lines,
* For parse the AWS SES notification events payload
**/
app.use(bodyParser.raw());
app.use(bodyParser.text());

app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

/**
* Route for handling the AWS SES notification events
**/
app.use('/api/email-bounce', indexRouter);

/**
* Test route for sending the email
**/
app.get('/api/send-mail', emailRouter);

module.exports = app;
// router/index.js

const express = require("express");
const router = express.Router();

const UserModel = require("../models/users.model");

/**
* Route to handle AWS SES notification events payload.
* You can use this route to update the database or track all notification types.
*/
router.post("/", function (req, res, next) {
console.log("Webhook body", req.body);

const { notificationType, bounce } = req.body;

/**
* Check if the notification type is bounce.
* We will only update the counter if the type is bounce.
*/
if (notificationType === "Bounce") {
/**
* Fetch the email address from the notification payload
*/
const emailAddress = bounce["bounced Recipients"][0]["emailAddress"];

/**
* Find the user in the users collection.
*/
const userObj = await UserModel.findOne({
email: emailAddress,
});

/**
* If the user exists in the DB then increase the counter.
*/
if (userObj) {
userObj.emailBounceCounter = userObj.emailBounceCounter + 1;
await userObj.save();
}
}

res.json(req.body);
});

module.exports = router;
// routes/email.js

var express = require("express");
var router = express.Router();

const UserModel = require("../models/users.model");
const transporter = require("../utils/email");

router.post("/", async function (req, res, next) {

const email = req.body;

const response = {
status: false,
info: null,
};

/**
* Find the email address in the users collection.
*/
const userObj = await UserModel.findOne(
{
email,
},
"emailBounceCounter"
);

/**
* If the email address exits,
* and email bounce counter is less than 3,
* then we will send the email to the user.
*/
if (userObj && userObj.emailBounceCounter < 3) {
const info = await transporter.sendMail({
from: process.env.AWS_SES_FROM_ADDRESS, // Sender address
to: email, // Receivers email address
subject: "Test Subject", // Subject line
text: "Hello world?", // Plain text body
html: "<b>Hello world?</b>", // HTML body
});

response.status = true;
response.info = info;
}

res.json(response);
});

module.exports = router;
  • Deploy the server, and you can monitor and update the database for bounce, complaint, and delivery events. This, in turn, helps filter out spam emails and maintain your app’s health.

Step 4: Setup AWS SNS account

Create Topic:

  • Search for SNS, click on it, choose “Topics” in the left navigation pane, and click “Create topic”.
AWS SNS: Topics List
  • Select the topic type (Standard/FIFO) and provide a name.
AWS SNS: Create Topic Form

Create Subscription for Email:

  • Now, click on Create Subscription under the Subscription tab.
AWS SNS: Topic Details Page
  • Here, we can set up various subscriptions for AWS services like SQS and Lambda. In this example, we’ll focus on two: Email and HTTP/HTTPS.
  • Start by selecting the email protocol and entering the endpoint address.
AWS SNS: Create a Subscription Form
  • The confirmation email will be sent to the subscriber for subscription validation. They should open the email and click “Confirm Subscription” to complete the process.
AWS SNS: Verification Email
AWS SNS: Email Confirmation Message

Create Subscription for HTTP/HTTPS:

  • Repeat the previous step for HTTP/HTTPS subscriptions and enter the webhook URL for notifications.
  • In the “Subscription” tab, select “Create Subscription,” and choose the protocol as “HTTP/HTTPS”.
AWS SNS: Create a Subscription Form
  • Following that, you will receive a JSON payload at your webhook. Extract and copy the subscription URL from it.
AWS SNS: HTTP Subscription Webhook Payload for Verification
  • Use the copied URL to confirm the subscription.
AWS SNS: Subscription Verification
AWS SNS: Verified Subscription List For a Topic

Test Subscriptions:

To test the subscriptions,

  • Click the Publish Message button in the top right corner of the screen.
AWS SNS: Topic Details Page
  • Next, enter the subject and the message body and click the Publish Message button.
AWS SNS: Publish Message For a Topic Form
  • You will receive a test notification in your email inbox and observe a log entry in your webhook.
AWS SNS: Published Subscription Email
AWS SNS: Published HTTP Subscription Wehbook Payload

Step 5: Configure SNS to send notifications to the server

  • First, go to SES and click on Verified Identities.
  • Find your added identities in the list.
  • To enable notifications for a specific identity, click it, access its details, and go to the Notifications tab.
AWS SES: Identity Details Page
  • You’ll find Feedback notifications. Click “edit” on the right.
AWS SES: Identity Notifications List Tab
  • On this page, you will find three notification types: Bounce, Compliant, and Delivery.
AWS SNS: Identity Notifications Details Page
  • Based on your preferences, choose the SNS Topics from the list to enable notification events.
  • If you select “Include original email headers,” you’ll receive additional headers from AWS.
  • With these settings, your server gets notified when emails are bounced, delivered, or marked as spam by recipients.
AWS SES: Delivery Type Event Notification Payload
AWS SES: Bounce Type Event Notification Payload

Your application is now ready to handle bounce emails.

For the complete code and implementation details, visit our GitHub repository: GitHub Repo Link

Conclusion

Using AWS SES and SNS for email bounce handling can greatly boost your email marketing success. It automates bounce detection, sends real-time notifications, reduces manual work, and helps you maintain a good sender reputation. This can also save you money on email delivery costs.

To excel in email marketing, keep monitoring and adapting your strategies, as a strong sender reputation ensures your emails land in the inbox, not spam.

Stay alert, take action, and keep your emails on the right track.

Follow the Simform Engineering blog for more such insights and updates.

Connect With Us: Twitter | LinkedIn

--

--