The Nodemailer package in a Node.js Server

Emails are an essential way of communicating. Most servers today use emails to send information to clients. In this tutorial, we are going to create a server that does the same. We will be sending two types of emails; plain text and HTML emails.

You can get the starter code from Github. It has the following packages.

  1. Express – we will be creating a node server with the help of express.js
  2. Nodemailer – this npm package sends emails using SMTP as it’s primary transport. It is also used to create plugins like nodemailer-postmark-transportgmail-nodemailer-transport, etc.
  3. Pug – it is a templating engine used to create HTML strings to be rendered.

Before we start, it’s important to note that we won’t be sending emails to real addresses. This can result in a lot of unnecessary emails in the inbox and/or spam messages. To avoid this, we can use a fake SMTP server that can receive our test emails.

A good service to do this with is Ethereal. It will provide us with the required SMTP configurations and the nodemailer configuration. Go ahead and create an account. Copy the Nodemailer configuration and add it to the app.js file. It should look something like the code below:

const transporter = nodemailer.createTransport({
    host: 'smtp.ethereal.email',
    port: 587,
    auth: {
        user: '<some-username>',
        pass: '<some-password>'
    }
});

Then import the nodemailer and express package and initialize the app.

const express = require('express')
const app = express()
const nodemailer = require('nodemailer')
const transporter = nodemailer.createTransport({
    host: 'smtp.ethereal.email',
    port: 587,
    auth: {
        user: '<some-username>',
        pass: '<some-password>'
    }
});

app.use(express.json());
app.listen('2400', () => {console.log('server started on port 2400')})
module.exports = app;

The first email we will send will be a plain text email. We use the sendEmail function of Nodemailer transport to send the emails. It takes in the email data as one of the parameters. The data includes:

  • from – the senders email address
  • to – the recipient email address
  • subject – the subject of the email
  • text/html – the content of the email. It can be plain text or html.

Go ahead and create an endpoint that sends a plain text email.

app.get('/email/text', (req, res) => {
    transporter.sendMail({
        from: '"moose" <me@moose.dev>',
        to: '"You there" <you@there.com>',
        subject: 'First email',
        text: 'Hello, nice to meet you'
    })
        .then(info => res.send(info))
        .catch(error => res.send(error))
})

As you can see, it returns a promise and we return the response or error from the sendEmail function. If it was successful, you will get the email in the Ethereal inbox. It is as simple as that.

For HTML, we add the tags inside a string and it will detect the content and style and display it .

app.get('/email/html', (req, res) => {
    transporter.sendMail({
        from: '"moose" <me@moose.dev>',
        to: '"You there" <you@there.com>',
        subject: 'Second email',
        html: '<h1>Hi again</h1> <p>This time we have used html!</p>'
    })
        .then(info => res.send(info))
        .catch(error => res.send(error))
})

In this endpoint we get an email with a header and a paragraph below it. A very small difference with the plain text. The only problem with this is that we may need to load a whole webpage in the string. This results in dirty and unreadable code.

To solve that, we can make use of a templating engine. We can use it to generate the entire HTML code then we can pass it in the HTML value. For that, we will use Pug.

First, create a package in the root-level of the project and name it views. Inside the package, create a file, and name it email.pug and add the following code.

html
    head
        title Pug Email template
    body
        h1 Hey there
        p We have now used a pug file. Yaay!

You will notice that we do not use the angle-brackets with pug and indentation is also very important. It shows relationship between elements. Read more about it in the official documentation. Go ahead and import the package then add the following endpoint.

app.get('/email/file', (req, res) => {
    let body = pug.renderFile('views/email.pug')
    transporter.sendMail({
        from: '"moose" <me@moose.dev>',
        to: '"You there" <you@there.com>',
        subject: 'Third email',
        html: body
    })
        .then(info => res.send(info))
        .catch(error => res.send(error))
})

As you can see, we use the renderFile function to compile our Pug code to HTML and get the resulting string. Then we pass the string to the HTML field. The good thing about this is that you can have a wide variety of elements and still have clean and organized code.

With that, you are now able to send emails from your Node.js server. You can use the Gmail SMTP settings to send emails to real addresses. A good challenge can be adding images to your email so go ahead and try it out! The full code of this tutorial can be found on Github. Feel free to open a PR or submit an issue.

Related posts:

Using Prisma with Postgres and Node.js
Debugging a Node.Js app using Chrome Dev Tools
Understanding Cookies and Implementing them in Node.js
How to Get SSL HTTPS for Localhost
Getting Started with EJS Templating Engine
How to use TypeScript with Node.js
How To Develop An Interactive Command Line Application Using Node.js
Node.js - Frontend or Backend?
Getting Started with Push Notifications in Node.js using Service Workers
Develop Your First Data-Driven Node.js Web App
Getting Started With Node.js Timers
Documenting a Node.js REST API using Swagger
How to Generate QR Code Using Node.js
How to Implement Caching using Adonis.js 5
Implementing Secret Key Cryptography in JavaScript
Keeping Node.js Fast: Tools, Techniques, And Tips For Making High-Performance Node.js Servers
Agora Cloud Recording with Node.js
Consuming the TinEye Reverse Image Search API in Node.js
Exploring Node.js Internals
Node.js Callback Concept
Create and Deploy NPM Packages
Data Encryption and Decryption in Node.js using Crypto
Building your First Telegram Bot using Node.js and Telegraf
Debugging a Node.js Application running in a Docker Container
Node.js Network Requests using Axios
Getting Started with Fastify Node.js Framework and Faunadb
Understanding HTTP Requests in Node.js
How to build a real time chat application in Node.js
Getting Started with Node.js Worker Thread
The Guide To Ethical Scraping Of Dynamic Websites With Node.js And Puppeteer
Node.js versus Next.js - A React Approach
Rendering HTML Pages as an HTTP Server Response Using Node.js