希望你一切都好。我正在开发一个使用 express 和 nodemailer 的应用程序。我的应用程序成功发送了电子邮件,但问题是我无法以我想要的方式一次发送一封电子邮件。我不想将一系列地址放入“收件人”字段中,我希望单独发送每封电子邮件。
我已经成功了,但是有一个问题。Microsoft 似乎已经编写了某种限制,以防止应用程序一次具有超过一定数量的连接。(链接与帖子文件末尾的解释。)
我试图通过一些权宜之计解决这个问题。不是所有这些我都会给你带来麻烦。其中大多数涉及setInterval()
和 或map
或forEach
。我不打算发送那么多电子邮件——当然不是为了挑逗任何类型的标准。我什至不想在我的电子邮件中包含任何 HTML。只是纯文本。但是,当我的应用程序发送 2/3 电子邮件时,我遇到了它们的错误消息(响应代码 432)。
下面你会看到我的代码。
这是我的代码的第一个相关部分。
db.query(sqlEmailGetQuery, param)
.then(result => {
handleEmail(result, response);
}).catch(error => {
console.error(error);
response.status(500).json({ error: 'an unexpected error occured.' });
});
});
这是它的第二部分。
function handleEmail(result, response) {
const email = result.rows[0];
let i = 0;
email.json_agg.map(contact => {
const msg = {
from: process.env.EMAIL_USER,
to: email.json_agg[i].email,
subject: email.subject,
text: email.emailBody + ' ' + i
};
i++;
return new Promise((resolve, reject) => {
setInterval(() => {
transporter.sendMail(msg, function (error, info) {
if (error) {
return console.log(error);
} else {
response.status(200).json(msg);
transporter.close();
}
});
}, 5000 + i);
});
});
}
email.json_agg[i].email
,但显然一旦我达到连接限制,它就停止工作。setInterval
与forEach
和await
因为它与每个连接的承诺,但是这不是问题的根源,这也不能工作。随着我对这个问题的理解不断加深,我可以看到我要么必须想办法等待足够长的时间,以便我可以发送另一封电子邮件 - 没有连接超时或每次发送电子邮件时断开连接-mail,这样当我发送下一封电子邮件时,我就有了新的连接。在我看来,如果后者是可能的,那么每个人都会这样做并违反微软的政策。
有没有办法让我解决这个问题,每说 3 秒发送 3 封电子邮件,然后等待,再发送三封?电子邮件的数量如此之多,如果需要,我可以等十秒钟。是否有其他限制较少的 smtp 主机?
请让我知道你的想法。如果有帮助,我的传输配置如下。
const transporter = nodemailer.createTransport({
pool: true,
host: 'smtp-mail.outlook.com',
secureConnection: false,
maxConnections: 1,
port: 587,
secure: false,
tls: { ciphers: 'SSLv3' },
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS
}
});
首先,将同一封电子邮件发送给大量用户的最有效方法是将其发送给您自己并密件抄送所有收件人。这将让您向 SMTP 服务器发送一封电子邮件,然后它将该电子邮件分发给所有收件人,而没有收件人能够看到任何单个收件人的电子邮件地址。
其次,您不能使用计时器来可靠地控制一次运行的请求数量,因为计时器与完成给定请求所需的时间无关,因此计时器只是对请求平均时间的猜测,它们可能在某些条件下工作并且在事情响应较慢时不起作用。相反,您必须实际使用一个请求的完成来知道是否可以发送下一个请求。
如果您仍然想发送单独的电子邮件并连续发送您的电子邮件,一个接一个地发送,以避免一次处理太多,您可以执行以下操作:
async function handleEmail(result) {
const email = result.rows[0];
for (let [i, contact] of email.json_agg.entries()) {
const msg = {
from: process.env.EMAIL_USER,
to: contact.email,
subject: email.subject,
text: email.emailBody + ' ' + i
};
await transporter.sendMail(msg);
}
}
如果您不传递transporter.sendMail()
回调,那么它将返回一个您可以直接使用的承诺 - 无需将其包装在您自己的承诺中。
请注意,此代码不会向您的 http 请求发送响应,因为这应该是调用代码的责任,而您之前的代码试图为每封电子邮件发送响应,而您只能发送一个响应,而之前的代码是如果出现错误,则不发送任何响应。
此代码依赖于返回给调用者的承诺来传达它是成功还是遇到错误,然后调用者可以决定如何处理这种情况。
您也可能不应该传递result
给这个函数,而应该只是传递,email
因为这段代码没有理由知道它必须访问某些数据库查询结果才能获得它需要的值。这应该是调用者的责任。那么,这个函数就更通用了。
如果您不想一次发送一封电子邮件,而是想一次发送 N 封电子邮件,则可以使用类似的方法mapConcurrent()
来执行此操作。它迭代一个数组并同时保持最多 N 个请求。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句