Skip to content

Instantly share code, notes, and snippets.

@mihaiserban
Created November 2, 2018 14:28
Show Gist options
  • Save mihaiserban/8a03fd28e54cac8856dbdfebd95bd7b3 to your computer and use it in GitHub Desktop.
Save mihaiserban/8a03fd28e54cac8856dbdfebd95bd7b3 to your computer and use it in GitHub Desktop.
AWS SNS handle SES bounce/complaints
const express = require("express");
const router = express.Router();
const User = require("../models/user");
const AWS = require("aws-sdk");
AWS.config.update({
accessKeyId: process.env.accessKeyId,
secretAccessKey: process.env.secretAccessKey,
region: "us-east-1"
});
const sns = new AWS.SNS();
const topicArnBounce =
"arn:aws:sns:us-east-1:32314142141:ses-bounces-topic-prod";
var paramsTopicBounces = {
Protocol: "https",
TopicArn: topicArnBounce,
Endpoint: "https://YOUR_ENDPOINT/aws/sns/handle-bounces"
};
const topicArnComplaint =
"arn:aws:sns:us-east-1:41412231312:ses-complaints-topic-prod";
var paramsTopicComplaints = {
Protocol: "https",
TopicArn: topicArnComplaint,
Endpoint: "https://YOUR_ENDPOINT/aws/sns/handle-complaints"
};
sns.subscribe(paramsTopicBounces, function(error, data) {
if (error) throw new Error(`Unable to set up SNS subscription: ${error}`);
console.log(`SNS subscription set up successfully: ${JSON.stringify(data)}`);
});
sns.subscribe(paramsTopicComplaints, function(error, data) {
if (error) throw new Error(`Unable to set up SNS subscription: ${error}`);
console.log(`SNS subscription set up successfully: ${JSON.stringify(data)}`);
});
const handleSnsNotification = async (req, res) => {
const message = JSON.parse(req.body.Message);
if (
(message && message.notificationType == "Bounce") ||
message.notificationType == "Complaint"
) {
const mail = message.mail;
if (mail && mail.destination) {
for (let i = 0; i < mail.destination.length; i++) {
const address = mail.destination[i];
try {
const user = await User.findOne({ email: address }).exec();
if (!user) continue;
user.emailError = true;
user.emailErrorDescription = message.notificationType;
await user.save();
} catch (error) {
console.error(error.message);
}
}
}
}
};
const handleResponse = async (topicArn, req, res) => {
if (
req.headers["x-amz-sns-message-type"] === "Notification" &&
req.body.Message
) {
await handleSnsNotification(req, res);
} else if (
req.headers["x-amz-sns-message-type"] === "SubscriptionConfirmation"
) {
var params = {
Token: req.body.Token,
TopicArn: topicArn
};
sns.confirmSubscription(params, function(err, data) {
if (err) throw err; // an error occurred
console.error(data);
});
}
};
router.post("/sns/handle-bounces", async function(req, res) {
try {
await handleResponse(topicArnBounce, req, res);
res.status(200).json({
success: true,
message: "Successfully received message"
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message
});
}
});
router.post("/sns/handle-complaints", async function(req, res) {
try {
handleResponse(topicArnComplaint, req, res);
res.status(200).json({
success: true,
message: "Successfully received message."
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message
});
}
});
module.exports = router;
express.use(function(req, res, next) {
if (req.get("x-amz-sns-message-type")) {
req.headers["content-type"] = "application/json"; //IMPORTANT, otherwise content-type is text for topic confirmation reponse, and body is empty
}
next();
});
// Load body parser to handle POST requests
express.use(bodyParser.json());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment