Skip to content

Instantly share code, notes, and snippets.

@OssiPesonen
Last active November 14, 2020 15:24
Show Gist options
  • Save OssiPesonen/d4a20114106fedca1a6171df5d5f75a3 to your computer and use it in GitHub Desktop.
Save OssiPesonen/d4a20114106fedca1a6171df5d5f75a3 to your computer and use it in GitHub Desktop.
Lambda SES bounce event handler
const AWS = require('aws-sdk');
const _ = require('lodash');
const successResponse = message => {
return {
statusCode: 200,
body: JSON.stringify({
message: message
})
}
};
/**
* Deliver given message to DLQ
*
* @param sqs
* @param message
* @returns {Promise<void>}
*/
async function sendMessageToDLQ (sqs, message) {
await sqs.sendMessage({ MessageBody: message, QueueUrl: process.env.DLQ_URL }).promise();
}
/**
* Process bounced messages
*
* @param event SNS notification event
* @return {object} Success response object
*/
exports.handler = async (event) => {
const sns = new AWS.SNS({ region: process.env.REGION });
const sqs = new AWS.SQS({ region: process.env.REGION });
if (_.get(event, 'Records', null)) {
for (const property in event.Records) {
const record = event.Records[ property ];
const notification = JSON.parse(record.Sns.Message);
// Make sure notification type is Bounce
if (notification.notificationType === 'Bounce') {
const headers = _.get(notification, 'mail.headers', null);
if (!headers) {
// SES has a configuration error, handle failure
await sendMessageToDLQ(sqs, record.Sns.Message);
return successResponse('Original message headers missing');
}
const snsTargetArn = notification.mail.headers.find((header) => header.name === 'X-BOUNCE-SNS-TARGET-ARN');
if (!snsTargetArn) {
// Client did not provide the TargetArn, handle failure
await sendMessageToDLQ(sqs, record.Sns.Message);
return successResponse('Missing TargetArn header');
}
let bouncedRecipients = [];
// Add all bounced recipients to message
if (_.get(notification, 'bounce.bouncedRecipients', false)) {
notification.bounce.bouncedRecipients.forEach(function (value) {
bouncedRecipients.push({ emailAddress: value.emailAddress });
});
}
// Build the message
const message = JSON.stringify({
messageId: notification.mail.messageId,
bounceType: notification.bounce.bounceType,
bounceSubType: notification.bounce.bounceSubType,
timestamp: notification.bounce.timestamp,
bouncedRecipients: bouncedRecipients
});
// Processed, publish
await sns.publish({
MessageAttributes: {
'OriginalMessageId': {
DataType: 'String',
StringValue: bounce.messageId
}
},
Subject: 'Here is a bounced email notification',
Message: message,
TargetArn: snsTargetArn.value
}).promise();
}
else {
// Not a bounce message. Deliver to DLQ.
await sendMessageToDLQ(sqs, record.Sns.Message);
return successResponse('Not a bounce message');
}
}
}
return successResponse('ok');
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment