使用 Lambda、NodeJs 和 Nodemailer 发送电子邮件不起作用
Sending an eMail with Lambda, NodeJs and Nodemailer doesn't work
我正在尝试使用之前经过 SES 身份验证的帐户从 Lambda 发送电子邮件; node.js 使用 Nodemailer。没有错误,但它也不发送。
这是我正在使用的流程:
module.exports.eviarCorreoPrueba = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
console.log('inicia envio de correos');
var transporter = nodemailer.createTransport({
//pool: true,
host: 'email-smtp.us-east-1.amazonaws.com',
port: 465,
secure: true,
auth: {
user: 'user',
pass: 'pass'
}
});
console.log('se crea transporte ');
var mailOptions = {
from: 'test@email.com',
to: 'test@email.com',
subject: 'Prueba Lambda',
html: 'hello World'
};
console.log('se asignan las opciones de correo');
console.log('inicia envio de correo');
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
callback(null, {
statusCode: 200,
body: JSON.stringify({
input: 'not send'
})
})
} else {
console.log('Email sent');
}
});
console.log('funcion finalizada');
};
这些是日志回答结果:
您的 Lambda 超时。查看 Cloudwatch 日志中的最后一条消息。您将 lambda 超时设置为 6 秒,我想这不足以让 lambda 发送请求(通过 transporter.sendMail
)并获得响应。尝试增加 lambda 时间。大约 30 秒?
我为我设计的新 lambda 设置超时的方法是 运行 它们多次,直到我得到一个平均完成时间。然后我在那个时间上加 20 秒。
另外,transporter.sendMail
是异步函数。这意味着 console.log('funcion finalizada')
可能会 运行 在您的函数完成之前(但您的函数实际上尚未完成)。
阅读有关异步 javascript 和回调的更多信息:https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee
此外,如果您想以同步方式编写异步代码,请使用 async/await
以防有人遇到 'nodemailer not working in Lambda' 问题:
您 post 中的代码在本地服务器中有效,因为:
在您的本地环境中,有一个 运行 服务器来调度所有调用堆栈,包括同步和异步任务。一旦你在本地环境中调用 transporter.sendMail()
,它将被放置到当前调用堆栈的末尾,并将一直执行到你的调用堆栈中的最后一次执行完成。在您的情况下,异步函数 transporter.sendMail()
将安排在 console.log('funcion finalizada');
之后调用
为什么它在 Lambda 中不起作用:
每次调用lambda函数时,它都会执行代码,执行完后kill进程,也就是说不能调用异步transporter.sendMail()
,因为console.log('funcion finalizada');
lambda 函数进程将终止,并在执行之前清除计划的异步任务。
要使其在 Lambda 中运行:
1) 将函数更改为 async
函数
module.exports.eviarCorreoPrueba = async (event, context) => { ... }
2) 在继续
之前等待您的transporter.sendMail()
被调用
const response = await new Promise((rsv, rjt) => {
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return rjt(error)
}
rsv('Email sent');
});
});
return {
statusCode: 200,
body: JSON.stringify({
input: response
})
}
3) 让你的 nodemailer emailbot 工作的最后一件事:
您需要转 Less secure app access on and Allow access to your Google Account 因为您只是使用用户名和密码来连接您的 Gmail 帐户。
*注意:如果您想使用更安全的方式连接您的Gmail(例如OAuth 2.0),您可以参考我的文章:Create a Free Serverless Contact Form Using Gmail, Nodemailer, and AWS Lambda
希望这对遇到此问题的任何人有所帮助。
干杯,
我正在尝试使用之前经过 SES 身份验证的帐户从 Lambda 发送电子邮件; node.js 使用 Nodemailer。没有错误,但它也不发送。
这是我正在使用的流程:
module.exports.eviarCorreoPrueba = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
console.log('inicia envio de correos');
var transporter = nodemailer.createTransport({
//pool: true,
host: 'email-smtp.us-east-1.amazonaws.com',
port: 465,
secure: true,
auth: {
user: 'user',
pass: 'pass'
}
});
console.log('se crea transporte ');
var mailOptions = {
from: 'test@email.com',
to: 'test@email.com',
subject: 'Prueba Lambda',
html: 'hello World'
};
console.log('se asignan las opciones de correo');
console.log('inicia envio de correo');
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
callback(null, {
statusCode: 200,
body: JSON.stringify({
input: 'not send'
})
})
} else {
console.log('Email sent');
}
});
console.log('funcion finalizada');
};
这些是日志回答结果:
您的 Lambda 超时。查看 Cloudwatch 日志中的最后一条消息。您将 lambda 超时设置为 6 秒,我想这不足以让 lambda 发送请求(通过 transporter.sendMail
)并获得响应。尝试增加 lambda 时间。大约 30 秒?
我为我设计的新 lambda 设置超时的方法是 运行 它们多次,直到我得到一个平均完成时间。然后我在那个时间上加 20 秒。
另外,transporter.sendMail
是异步函数。这意味着 console.log('funcion finalizada')
可能会 运行 在您的函数完成之前(但您的函数实际上尚未完成)。
阅读有关异步 javascript 和回调的更多信息:https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee
此外,如果您想以同步方式编写异步代码,请使用 async/await
以防有人遇到 'nodemailer not working in Lambda' 问题:
您 post 中的代码在本地服务器中有效,因为:
在您的本地环境中,有一个 运行 服务器来调度所有调用堆栈,包括同步和异步任务。一旦你在本地环境中调用 transporter.sendMail()
,它将被放置到当前调用堆栈的末尾,并将一直执行到你的调用堆栈中的最后一次执行完成。在您的情况下,异步函数 transporter.sendMail()
将安排在 console.log('funcion finalizada');
为什么它在 Lambda 中不起作用:
每次调用lambda函数时,它都会执行代码,执行完后kill进程,也就是说不能调用异步transporter.sendMail()
,因为console.log('funcion finalizada');
lambda 函数进程将终止,并在执行之前清除计划的异步任务。
要使其在 Lambda 中运行:
1) 将函数更改为 async
函数
module.exports.eviarCorreoPrueba = async (event, context) => { ... }
2) 在继续
之前等待您的transporter.sendMail()
被调用
const response = await new Promise((rsv, rjt) => {
transporter.sendMail(mailOptions, function (error, info) {
if (error) {
return rjt(error)
}
rsv('Email sent');
});
});
return {
statusCode: 200,
body: JSON.stringify({
input: response
})
}
3) 让你的 nodemailer emailbot 工作的最后一件事: 您需要转 Less secure app access on and Allow access to your Google Account 因为您只是使用用户名和密码来连接您的 Gmail 帐户。
*注意:如果您想使用更安全的方式连接您的Gmail(例如OAuth 2.0),您可以参考我的文章:Create a Free Serverless Contact Form Using Gmail, Nodemailer, and AWS Lambda
希望这对遇到此问题的任何人有所帮助。
干杯,