Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AWS Lambda Node 20.x Support #147

Merged
merged 5 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ the email forwarding mapping from original destinations to new destination.
2. In AWS Lambda, add a new function and skip selecting a blueprint.

- Name the function "SesForwarder" and optionally give it a description. Ensure
Runtime is set to Node.js 16.x. (Node.js 18.x can be used if the AWS SDK v2
module is also installed.)
Runtime is set to Node.js 20.x.

- For the Lambda function code, either copy and paste the contents of
`index.js` into the inline code editor or zip the contents of the repository
Expand Down
36 changes: 17 additions & 19 deletions index.js
mylesboone marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use strict";

var AWS = require('aws-sdk');
const { S3Client, CopyObjectCommand, GetObjectCommand } = require("@aws-sdk/client-s3");
const { SESv2Client, SendEmailCommand } = require("@aws-sdk/client-sesv2");

console.log("AWS Lambda SES Forwarder // @arithmetric // Version 5.1.0");

Expand Down Expand Up @@ -160,19 +161,19 @@ exports.fetchMessage = function(data) {
data.config.emailKeyPrefix + data.email.messageId
});
return new Promise(function(resolve, reject) {
data.s3.copyObject({
data.s3.send(new CopyObjectCommand({
Bucket: data.config.emailBucket,
CopySource: data.config.emailBucket + '/' + data.config.emailKeyPrefix +
data.email.messageId,
Key: data.config.emailKeyPrefix + data.email.messageId,
ACL: 'private',
ContentType: 'text/plain',
StorageClass: 'STANDARD'
}, function(err) {
}), function(err) {
if (err) {
data.log({
level: "error",
message: "copyObject() returned error:",
message: "CopyObjectCommand() returned error:",
error: err,
stack: err.stack
});
Expand All @@ -181,21 +182,21 @@ exports.fetchMessage = function(data) {
}

// Load the raw email from S3
data.s3.getObject({
data.s3.send(new GetObjectCommand({
Bucket: data.config.emailBucket,
Key: data.config.emailKeyPrefix + data.email.messageId
}, function(err, result) {
}), async function(err, result) {
if (err) {
data.log({
level: "error",
message: "getObject() returned error:",
message: "GetObjectCommand() returned error:",
error: err,
stack: err.stack
});
return reject(
new Error("Error: Failed to load message body from S3."));
}
data.emailData = result.Body.toString();
data.emailData = await result.Body.transformToString();
return resolve(data);
});
});
Expand Down Expand Up @@ -285,19 +286,16 @@ exports.processMessage = function(data) {
};

/**
* Send email using the SES sendRawEmail command.
* Send email using the SESv2 SendEmailCommand command.
*
* @param {object} data - Data bundle with context, email, etc.
*
* @return {object} - Promise resolved with data.
*/
exports.sendMessage = function(data) {
var params = {
Destinations: data.recipients,
Source: data.originalRecipient,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid any functional changes, I'll restore this Source parameter.

RawMessage: {
Data: data.emailData
}
Destination: { ToAddresses: data.recipients },
Content: { Raw: { Data: Buffer.from(data.emailData) } },
};
data.log({
level: "info",
Expand All @@ -306,19 +304,19 @@ exports.sendMessage = function(data) {
data.recipients.join(", ") + "."
});
return new Promise(function(resolve, reject) {
data.ses.sendRawEmail(params, function(err, result) {
data.ses.send(new SendEmailCommand(params), function(err, result) {
if (err) {
data.log({
level: "error",
message: "sendRawEmail() returned error.",
message: "SendEmailCommand() returned error.",
error: err,
stack: err.stack
});
return reject(new Error('Error: Email sending failed.'));
}
data.log({
level: "info",
message: "sendRawEmail() successful.",
message: "SendEmailCommand() successful.",
result: result
});
resolve(data);
Expand Down Expand Up @@ -351,9 +349,9 @@ exports.handler = function(event, context, callback, overrides) {
context: context,
config: overrides && overrides.config ? overrides.config : defaultConfig,
log: overrides && overrides.log ? overrides.log : console.log,
ses: overrides && overrides.ses ? overrides.ses : new AWS.SES(),
ses: overrides && overrides.ses ? overrides.ses : new SESv2Client(),
s3: overrides && overrides.s3 ?
overrides.s3 : new AWS.S3({signatureVersion: 'v4'})
overrides.s3 : new S3Client({signatureVersion: 'v4'})
};
Promise.series(steps, data)
.then(function(data) {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"test": "nyc --statements 100 -- mocha -- --check-leaks --timeout 3000"
},
"dependencies": {
"aws-sdk": "~2.1083.0"
"@aws-sdk/client-s3": "^3.188.0",
"@aws-sdk/client-ses": "^3.188.0"
},
"devDependencies": {
"coveralls": "^3.0.7",
Expand Down
33 changes: 19 additions & 14 deletions test/fetchMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

var assert = require("assert");

const {GetObjectCommand, CopyObjectCommand} = require('@aws-sdk/client-s3');

var index = require("../index");

describe('index.js', function() {
Expand All @@ -25,11 +27,17 @@ describe('index.js', function() {
},
log: console.log,
s3: {
copyObject: function(options, callback) {
callback(null);
},
getObject: function(options, callback) {
callback(null, {Body: "email data"});
send: function(options, callback) {
if (options instanceof CopyObjectCommand)
callback(null);
else if (options instanceof GetObjectCommand)
callback(null, {
Body: {
transformToString: function() {
return "email data";
}
}
});
}
}
};
Expand All @@ -55,10 +63,7 @@ describe('index.js', function() {
},
log: console.log,
s3: {
copyObject: function(options, callback) {
callback(true);
},
getObject: function(options, callback) {
send: function(options, callback) {
callback(true);
}
}
Expand All @@ -83,11 +88,11 @@ describe('index.js', function() {
},
log: console.log,
s3: {
copyObject: function(options, callback) {
callback(null);
},
getObject: function(options, callback) {
callback(true);
send: function(options, callback) {
if (options instanceof CopyObjectCommand)
callback(null);
else if (options instanceof GetObjectCommand)
callback(true);
}
}
};
Expand Down
20 changes: 14 additions & 6 deletions test/handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
var assert = require("assert");
var fs = require("fs");

const {GetObjectCommand, CopyObjectCommand} = require('@aws-sdk/client-s3');

var index = require("../index");

describe('index.js', function() {
Expand All @@ -16,15 +18,21 @@ describe('index.js', function() {
};
var overrides = {
s3: {
copyObject: function(options, callback) {
callback(null);
},
getObject: function(options, callback) {
callback(null, {Body: "email data"});
send: function(options, callback) {
if (options instanceof CopyObjectCommand)
callback(null);
else if (options instanceof GetObjectCommand)
callback(null, {
Body: {
transformToString: function() {
return "email data";
}
}
});
}
},
ses: {
sendRawEmail: function(options, callback) {
send: function(options, callback) {
callback(null, {status: "ok"});
}
},
Expand Down
4 changes: 2 additions & 2 deletions test/sendMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('index.js', function() {
context: {},
log: console.log,
ses: {
sendRawEmail: function(options, callback) {
send: function(options, callback) {
callback(null, {status: "ok"});
}
}
Expand All @@ -45,7 +45,7 @@ describe('index.js', function() {
context: {},
log: console.log,
ses: {
sendRawEmail: function(options, callback) {
send: function(options, callback) {
callback(true);
}
}
Expand Down