Skip to content

Sending emails with nodemailer on Vercel

I couldn’t figure out why nodemailer didn’t work on Vercel, then (tldr) I found out I needed await and not a callback.

Here’s the code I had:

nodemailer
  .createTransport({
    host: 'smtpserver.com',
    port: 465,
    secure: true,
    auth: {
      user: import.meta.env.USER,
      pass: import.meta.env.PASS,
    },
  })
  .sendMail(
    {
      from: 'me@me.com',
      to: email,
      subject,
      html,
    },
    function (err, info) {
      console.log(info)
      if (err) {
        console.log(err)
      } else {
        console.log('sent email')
      }
    }
  )

This worked locally.

But when pushed to Vercel and it ran in a serverless function environment, the email was never sent.

Also, I never got the “sent email” message in the logs.

Nor any error.

Turns out the callback-based version of sendMail() failed to work (due to the nature of serverless functions, I believe, they are terminated earlier and the email is never sent) and I needed to use the promise-based version, by omitting the second parameter (the callback function) to sendMail()

try {	   
	await nodemailer
	  .createTransport({
	    host: 'smtpserver.com',
	    port: 465,
	    secure: true,
	    auth: {
	      user: import.meta.env.FASTMAIL_EMAIL,
	      pass: import.meta.env
	        .FASTMAIL_APP_SPECIFIC_PASSWORD,
	    },
	  })
	  .sendMail({
	    from: 'me@me.com',
	    to: email,
	    subject,
	    html,
	  })
	console.log('Email sent to ' + email)
} catch (e) {
  console.error(e)
}

→ Here's my latest YouTube video

→ I wrote 17 books to help you become a better developer, download them all at $0 cost by joining my newsletter

JOIN MY CODING BOOTCAMP, an amazing cohort course that will be a huge step up in your coding career - covering React, Next.js - next edition February 2025

Bootcamp 2025

Join the waiting list