node.jsreactjsnext.jsnodemailer

Why Nodemailer is working locally but not in Production?


When I try to send an email locally it works but in production, in the network tab I get everything right just email doesn't want to send and I don't get any error.

  try {
    const { name, email, message } = req.body;

    const transporter = nodemailer.createTransport({
      port: 465,
      host: "smtp.gmail.com",
      auth: {
        user: process.env.NEXT_PUBLIC_GMAIL_EMAIL,
        pass: process.env.NEXT_PUBLIC_GMAIL_PASSWORD,
      },
      secure: true,
    });

    const mailData = {
      from: process.env.NEXT_PUBLIC_GMAIL_EMAIL,
      to: process.env.NEXT_PUBLIC_EMAIL_WHICH_RECIEVES_CONTACT_INFO,
      subject: `Message From ${email}`,
      text: message,
    };

    transporter.sendMail(mailData, function (err, info) {
      if (err) console.log(err);
      else console.log(info);
    });

    res.status(200).json({ message: "Email sent" });
  } catch (error: any) {
    res.status(500).json({ message: error.message });
  }


Solution

  • I kind of had a similar issue with nodemailer and Next.js, try to wrap the transporter in a Promise, hopefully it works for you too:

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

    explanation: due to the nature of serveless functions, we have to await for the email to be sent before moving on. if we don't the serverless function will end before sending the email(because it's short-lived)

    however, you should note that this solution is good for sending a few emails, if you're planning to bulk send emails you better use a dedicated email service like sendgrid