Skip to content

Sending emails with nodemailer on Vercel

The Valley of Code

Your Web Development Manual

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: '[email protected]',
      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: '[email protected]',
	    to: email,
	    subject,
	    html,
	  })
	console.log('Email sent to ' + email)
} catch (e) {
  console.error(e)
}
  • THE VALLEY OF CODE (+ PRO), your web development manual
  • I wrote 15+ free coding BOOKS, download them here
  • SOLOPRENEUR LAND the missing MBA for wannabe solopreneurs craving a life with more freedom, control, fulfillment and purpose (summer 2024)