Vercel 中的 Nodemailer 不在生产环境中发送电子邮件

Nodemailer in vercel not sending email in production

我在我的无服务器 Next.js 项目中使用 Nodemailer 发送电子邮件,该项目部署在 Vercel 中,在开发模式下运行良好。但是我在生产中遇到了问题。没有返回错误,一切都与开发模式相同,除了我没有收到任何电子邮件。

我有另一个用 React 构建并部署在 Heroku 中的项目,在那里我以相同的方式发送电子邮件并且在开发和生产中都运行良好,所以我知道问题出在 Vercel 上。

是的,我在 Google 帐户中启用了“允许安全性较低的应用程序”,是的,我启用了验证码。

我也读过这个 https://vercel.com/docs/solutions/email 但它并没有真正让我明白我应该做什么。我可以看到这是 SMTP 的问题,但我不知道具体是什么。

有人遇到过这种问题吗?我该如何解决这个问题?

const transporter = nodemailer.createTransport({
    host: "smtp.gmail.com",
    port: 465,
    auth: {
        user: myEmail@gmail.com,
        pass: myEmailPass
    }
});
            
const mailOptions = {
    from: `${req.body.name} ${req.body.email}`,
    to: myEmail@gmail.com,
    subject: `${req.body.subject}`,
    text: `Text: ${req.body.text}`
}
            
transporter.sendMail(mailOptions, (err, res) => {
    if(err) {
          console.log(err);
    } else {
          console.log("success");
    }
});

更新

我更改为 SendGrid:创建了一个帐户,创建了一个 API 密钥,并像这样更改了代码(而不是上面的代码):

sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
    to: `myEmail@gmail.com`,
    from: `myEmail@gmail.com`,
    subject: `${req.body.subject}`,
    text: `${req.body.text}`
};
sgMail
.send(msg)
.then(() => {
     console.log('email sent')
})
.catch((error) => {
     console.error("error", error)
});

它注销了“电子邮件已发送”,但我没有收到任何电子邮件。 这与 Nodemailer 的问题相同。 我现在很困惑...

我已经遇到过同样的问题,nodemailer 不能在 vercel 上运行,但在 heroku 上一切正常。文档中指定 vercel 不会阻止 stmp 连接,但根据我的经验,实际上 stmp 连接被阻止。你可以做的是使用 nodemailer 的替代品。使用 sendgrid,它工作正常

An article on how integrating Sendgrid with Next.js

这个问题确实很费解。我设法通过简单地添加 async/await 来解决这个问题。这是因为 Vercel 不支持流式响应(即发即弃函数)。

来源:https://vercel.com/docs/platform/limits#streaming-responses

我 运行 解决了这个问题并设法修复它并通过添加 async/await 的承诺继续使用 nodemailer。

const nodemailer = require("nodemailer");

export default async (req, res) => {

const { firstName, lastName, email, message } = JSON.parse(req.body);

const transporter = nodemailer.createTransport({
    port: 465,
    host: "smtp.gmail.com",
    auth: {
        user: "myEmail@gmail.com",
        pass: "password",
    },
    secure: true,
});

await new Promise((resolve, reject) => {
    // verify connection configuration
    transporter.verify(function (error, success) {
        if (error) {
            console.log(error);
            reject(error);
        } else {
            console.log("Server is ready to take our messages");
            resolve(success);
        }
    });
});

const mailData = {
    from: {
        name: `${firstName} ${lastName}`,
        address: "myEmail@gmail.com",
    },
    replyTo: email,
    to: "recipient@gmail.com",
    subject: `form message`,
    text: message,
    html: `${message}`,
};

await new Promise((resolve, reject) => {
    // send mail
    transporter.sendMail(mailData, (err, info) => {
        if (err) {
            console.error(err);
            reject(err);
        } else {
            console.log(info);
            resolve(info);
        }
    });
});

res.status(200).json({ status: "OK" });
};

我在 Nodemailer 上遇到了类似的问题,但我通过首先在 Vercel 中添加环境变量然后提交到 github(它将自动上传到 Vercel)来修复它。所以先给vercel添加变量让它生效