Nodemailer in vercel not sending email in production

Viewed 5894

I'm using Nodemailer to send emails in my serverless Next.js project, deployed in Vercel, which works perfectly in development mode. But I'm having problems in production. No error returned, everything works the same way as is development mode, except I don't receive any email.

I have another project built with React and deployed in Heroku where I send emails the same way and it works fine, development and production, so I understand the problem is with Vercel.

Yes, I enabled "Allow Less Secured Apps" in Google account and yes, I enabled Captcha.

I also read this https://vercel.com/docs/solutions/email but it doesn't really make me understand what I should do in my case. I can see it's a matter of SMTP but I don't know what exactly.

Anybody experienced this kind of problem? How can I fix this?

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");
    }
});

UPDATE

I changed to SendGrid: made an account, created an API Key, and changed the code like so(instead the one above):

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)
});

It logs out "email sent" but I don't receive any email. It's the same problem like with Nodemailer. I'm confused now...

4 Answers

I ran into this issue and managed to fix it and keep using nodemailer by adding in promises with async/await.

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" });
};

I have already encountered the same problem, nodemailer was not working on vercel but on heroku everything worked perfectly. it is specified in the doc that vercel does not block stmp connections but according to what I have experienced, in practice stmp connections are blocked. what you can do is use an alternative to nodemailer. use sendgrid and it works fine

An article on how integrating Sendgrid with Next.js

I had a similar issue with Nodemailer but I fixed it by first adding the environment variables in Vercel then commit to the github(It will automatically be uploaded on vercel). So add the variables to vercel first for it to take effect

Related