Last active
August 11, 2020 13:36
-
-
Save jakubboucek/d99c596c50d5fb217d3944417b5e0020 to your computer and use it in GitHub Desktop.
AWS Lambda - custom SES Bounce message
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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