Now that we have the endpoint ready to be called, we can go in the details of sending the email newsletter.

app.post('/send', (req, res) => {
  const content = req.body.content

	//we'll send the emails here

  res.end()
})

When you have up to a reasonable amount of emails in the database, let’s say 1000, just using your email server’s SMTP works fine.

But above some number of emails, you need to implement a queue system to avoid overloading your memory and the SMTP server.

This is how you send 1 single email using nodemailer, a popular package that simplifies handling sending emails, using any SMTP account:

const nodemailer = require('nodemailer')

//...
const to = ''
const subject = ''
const body = ''

//SMTP_USERNAME, SMTP_PASSWORD, SMTP_HOST, SMTP_PORT are environment variables to authenticate with your SMTP server

const transporter = nodemailer.createTransport({
	host: process.env.SMTP_HOST,
	port: process.env.SMTP_PORT,
	secure: true,
	auth: {
  	user: process.env.SMTP_USERNAME,
  	pass: process.env.SMTP_PASSWORD
	}
})

const mailOptions = {
  from: process.env.FROM_EMAIL,
  to: to,
  subject: subject,
  html: body
}

transporter.sendMail(mailOptions, (err, info) => {
  if (err) {
    console.log(err)
  } else {
    // email sent
    console.log(info)
  }
})

It’s highly recommended that you use a dedicated, paid SMTP server to send transactional emails, like Mailgun, Sendgrid or Mandrill. Use your own email SMTP server only for a small amount of emails. For our simple example, your email SMTP will work fine, but keep it in mind.

If you don’t want to send real emails here, sign up for Mailtrap.io, which is a fake SMTP server well suited for this use case.

First, add nodemailer to your package.json file.

Then add this to the /send endpoint:

app.post('/send', (req, res) => {
  const body = req.body.content

  const subject = 'Newsletter from me!'

  getEmails().then(emails => {

    const transporter = nodemailer.createTransport({
      host: process.env.SMTP_HOST,
      port: process.env.SMTP_PORT,
      secure: true,
      auth: {
        user: process.env.SMTP_USERNAME,
        pass: process.env.SMTP_PASSWORD
      }
    })

    const sleep = (milliseconds) => {
      return new Promise(resolve => setTimeout(resolve, milliseconds))
    }

    const sendEmail = (mailOptions, i, emails, res) => {
      if (i === emails.length) {
        res.end()
        return
      }
      mailOptions.to = emails[i].email

      transporter.sendMail(mailOptions, (err, info) => {
        if (err) {
          console.log(err)
        } else {
          // email sent
          sleep(500).then(() => {
            sendEmail(mailOptions, ++i, emails, res)
          })

        }
      })
    }

    const mailOptions = {
      from: process.env.FROM_EMAIL,
      subject: subject,
      html: body
    }

    sendEmail(mailOptions, 0, emails, res)
  })
})

This code does the following: first we fetch the body of the email from the request body (warning: we still need to filter and validate it!), then we get the emails from Airtable using the getEmails() function we added in the previous lessons.

Next, we initialize nodemailer and we use a recursive structure, with a little sleep between each call, to send emails without overloading the SMTP server.

In the challenges proposed in the next lesson you’ll improve this code yourself.

See the app at the current point on Glitch :・゚✧


Go to the next lesson