Skip to content

Instantly share code, notes, and snippets.

@jakubboucek
Last active August 11, 2020 13:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakubboucek/d99c596c50d5fb217d3944417b5e0020 to your computer and use it in GitHub Desktop.
Save jakubboucek/d99c596c50d5fb217d3944417b5e0020 to your computer and use it in GitHub Desktop.
AWS Lambda - custom SES Bounce message
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const ses = new AWS.SES();
// Configuration - you MUST fill all these {PLACEHOLDERS}
const bucketName = {BUCKET_NAME};
const bucketPrefix = {BUCKET_PATH_PREFIX}; // you can leave empty string
// e-mail address to send bounces from
const reportSender = {REPORT_SENDER_EMAIL};
// ARN identity to send bounces from
const reportSenderArn = {REPORT_SENDER_ARN};
exports.handler = async function(event, context, callback) {
console.log('Bounce sender');
const sesNotification = event.Records[0].ses;
console.log("Processed SES Notification:\n", JSON.stringify(sesNotification, null, 2));
try {
const mail = await s3.getObject({
Bucket: bucketName,
Key: bucketPrefix + sesNotification.mail.messageId
}).promise().then(mail => mail.Body.toString());
let headers = mail.split("\r\n\r\n", 2)[0];
// AWS bug - remove `Content-Type` line from body because
// InvalidParameterValue: Missing start boundary
headers = headers.replace(/^content-type:.+(?:\r?\n|$)/im, '');
const messageId = sesNotification.mail.commonHeaders.messageId;
const returnPath = sesNotification.mail.commonHeaders.returnPath;
const recipientEmail = sesNotification.receipt.recipients[0];
const arrivalDate = sesNotification.mail.commonHeaders.date;
const boundary = "--boundary=" + Math.random().toString(36).substring(2, 15);
// Here you can customise user-readable message
const humanReadableReport = `We are so sorry, but you sent your email message to inbox "${recipientEmail}",
which is works as sending gateway only.
You message will not be delivered.
Sent automatically by ACME Corp.
www.acme.com`;
let message = `Subject: Delivery Status Notification (Failure)
References: ${messageId}
From: "Vyfakturuj.cz mailer daemon" <${reportSender}>
To: ${returnPath}
Content-Type: multipart/report; boundary="${boundary}"; report-type=delivery-status
--${boundary}
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Content-Description: Notification
${humanReadableReport}
--${boundary}
Content-Type: message/delivery-status
Content-Transfer-Encoding: 7bit
Content-Description: Delivery Status Notification
Reporting-MTA: dns; inbound-smtp.eu-west-1.amazonaws.com
Arrival-Date: ${arrivalDate}
Action: failed
Final-Recipient: rfc822; ${recipientEmail}
Original-Recipient: rfc822; ${recipientEmail}
Diagnostic-Code: smtp; 550 5.1.1 Recipient address rejected: User is sending gateway only
Status: 5.1.1
--${boundary}
Content-Type: text/rfc822-headers
Content-Transfer-Encoding: 7bit
Content-Description: Undelivered Message
${headers}
--${boundary}--
`;
message = message.replace(/\r?\n/g, "\r\n");
console.log(message);
const sesRawParams = {
RawMessage: {
Data: message
},
Destinations: [returnPath],
Source: reportSender,
SourceArn: reportSenderArn,
};
const bounceMessageId = await ses.sendRawEmail(sesRawParams).promise().then(data => data.MessageId);
console.log("Sent bounce message ID:\n", bounceMessageId);
}catch(err) {
console.log(err, err.stack);
}
};
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"s3:GetObject",
"logs:CreateLogStream",
"ses:SendRawEmail",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:eu-west-1:{AWSACCOUNTID}:log-group:/aws/lambda/*",
"{REPORT_SENDER_ARN}",
"arn:aws:s3:::{BUCKET_NAME}/{BUCKET_PATH_PREFIX}*"
]
},
{
"Effect": "Allow",
"Action": "ses:SendRawEmail",
"Resource": "{REPORT_SENDER_ARN}"
},
{
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:eu-west-1:{AWSACCOUNTID}:*"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment