Mace
Mace

Reputation: 141

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

Upvotes: 1

Views: 4020

Answers (3)

Gour Chandra Saha
Gour Chandra Saha

Reputation: 11

I modified the transporter and it solved the issue. This is the whole function to send a mail. the 'html' should

import nodemailer from 'nodemailer';
import config from '../config';
export const sendEmail = async (to: string, subject: string, html: string) => {
  const transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      user: config.support_email,
      pass: config.support_email_password,
    },
    tls: {
      rejectUnauthorized: false,
    },
  });

  const mailData = {
    from: config.support_email,
    to,
    subject,
    html,
  };
  await new Promise((resolve, reject) => {
    transporter.sendMail(mailData, (err, info) => {
      if (err) {
        reject(err);
      } else {
        resolve(info);
      }
    });
  });
};

Upvotes: 1

It's Ritik Dude
It's Ritik Dude

Reputation: 31

for me, adding tls makes it working

const transporter = nodemailer.createTransport({
    service: 'gmail',
    host: 'smtp.gmail.com',
    tls: {
        ciphers: "SSLv3",
    },
    port: 587,
    secure: false,
    auth: {
        user: process.env.MAIL_SENDER,
        pass: process.env.MAIL_PASS
    }
});

Upvotes: 0

mocherfaoui
mocherfaoui

Reputation: 1217

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

Upvotes: 11

Related Questions