Image for post
Image for post
Photo by Lucas George Wendt on Unsplash

How to send emails with Node.js

How to send an email using node.js, and dynamically generate HTML to send email to our user

Aayush Acharya
Jul 4, 2020 · 9 min read

In this article, we will learn how to send email using Node.js. To follow along with this article, you need to have some basic understanding of Express and Node.

Here, we will be using a package called nodemailer to send emails. We will also use a dynamic HTML generator which will help us to send beautiful looking emails.

In order to learn how to send email, we will write some code to send email to a newly signed up user. We will also write code to send bills to our user using nodemailer. This should get you started with nodemailer.

Now let’s start coding!

Open up your terminal in your working directory and write the following command:

npm init -y

The -y flag here helps us to set the values as default.

Now, let’s install the packages we need. For that, write the following lines of code:

npm i nodemailer mailgen express

Nodemailer is a node package that will help us to send email, while mailgen helps us to generate nice looking email.

Now that we have installed packages, let’s create a file named index.js in our main project directory. Now, our folder structure should look like this:

Image for post
Image for post

Now, let’s write some lines of code in our index.js file.

The code is pretty simple. We have imported express, initialized our app, used express.json()middleware, created a route of/api , and started the server.

Now let’s create a folder called routes in our main project directory. Then create a file named appRoute.js. Our folder structure should look like this:

Image for post
Image for post

Now let’s open the file appRoute.js and write following lines of code:

In the above file, we have imported express and appController(we will create the file shortly). Then we added two endpoints namely /api/user/signup and /api/product/get-the-bill. Notice that I have not added any validation at all because this project is just for learning purpose. But you should add validation while creating a real world application.

Now let’s create a folder named controller. In that directory, create a file named appController.js . Now, our folder structure should look like this:

Image for post
Image for post

Before doing anything with our appController.js file, we need to create a folder called config in our main project directory. In that folder, create three different files called index.js , prod.js and dev.js . This should make our folder structure should look like this:

Image for post
Image for post

Now, let’s open index.js file, which is inside of the config directory, and write the following lines of code:

if (process.env.NODE_ENV === "production") {  module.exports = require("./prod");} else {  module.exports = require("./dev");}

These lines of code will either export the modules from prod.js file or dev.js file depending upon value of NODE_ENV. If NODE_ENV is "production" it will export module from prod.js else it will export file from dev.js .

Now, open the file prod.js, and write the following lines of code:

module.exports = {  PASSWORD: process.env.PASSWORD,  EMAIL: process.env.EMAIL,  MAIN_URL: process.env.MAIN_URL,};

In this file we are exporting PASSWORD , EMAIL, MAIN_URL. All these values are received from environment variable. I hope you know about environment variable. These modules will only be exported when NODE_ENV is "production". This should make our production process easier.

Now, let’s talk about PASSWORD, EMAIL, MAIN_URL. These are the variables we need while sending email. To send email, we need to have a mail service provider. In our case we will be using yahoo mail. If you want to use other service provider, you will be capable do it by the end of this article.

Let’s talk about the values that those variables should store. The EMAIL should be your yahoo’s email address and the MAIN_URL is just the URL of your app. The password is the password for the email address. But the password might not work here. So, you will have to ask yahoo to generate a random set of string as a password for your app. For that you will need to open your yahoo mail. Then click on your profile image. After that, a popup appears then, click on Account Info.

Now, click on account security. If you were not able to follow along with this set of instructions, just click this link (This link is working at the time of writing this article). Now, scroll to the bottom of the page. Did you see an option called ‘manage app password’? Click on that!

Now click on the dropdown option and choose ‘Other Desktop.’ After that, you will have to write the name of the app. It should look like this:

Image for post
Image for post

In my case, I have named the app as Nodemailer. The name doesn’t really matter here. After writing the name click on generate. After that, you will receive a randomly generated password for your app. Store it safe somewhere.

Now, let’s open the file dev.js and write the following lines of code:

module.exports = {  EMAIL: "",  // your yahoo email address goes here  PASSWORD: "",  // recently generated password goes here  MAIN_URL: "http://localhost:3000/", };

I think the above lines of code are pretty clear. You just need to enter the values as mentioned in the comment of the above code.

Now let’s go to our file appController.js , and write the following lines of code:

It’s a lot of code! What exactly is happening here? Let’s go slowly. Okay?

As you can see, first few lines are just imports. Then we have transporter. That part looks like this:

let transporter = nodemailer.createTransport({  service: "Yahoo",
secure: true,
auth: {
user: EMAIL,

The function of transporter is to send email. Every time we need to send an email, we have to send it through a transporter.

Here, nodemailer.createTransport helps us to create a transporter, and we stored that transporter in transporter variable. createTransport takes in service. This service takes in the email service provider. In our case it is “Yahoo”. You can also see that there is an option for secure inside of the createTransport. This secure option helps us to implement TLS, if set to true.

After that we have auth , which takes in user and pass . The user key takes in email address while pass key takes in password.

Now, let’s take a look at MailGenerator . In the above code it looks like this:

let MailGenerator = new Mailgen({  theme: "default",  product: {    name: "Nodemailer",    link: MAIN_URL,  },});

You can see here that we have created a new instance of Mailgen . It takes in theme. There are multiple themes offered by mailgen that you can choose from. In our case we are using the default theme. You can try out other themes that mailgen has to offer. For that you need to visit this documentation.

Then we can see the product, which takes in the name and the link. The name is just the name of our app. The name will appear in the emails that will be sent. The same way link is the link to our app’s URL. This link will also be included in the email that we will be sending to our user. Pretty simple, right?

Now let’s take a look at signup function.

const signup = (req, res) => {
const { userEmail, name } = req.body; // sign up the user ..... let response = { body: { name, intro: "Welcome to Nodemailer! We're very excited to have you on board.", }, }; let mail = MailGenerator.generate(response); let message = { from: EMAIL, to: userEmail, subject: "signup successful", html: mail, }; transporter .sendMail(message) .then(() => { return res.status(200)
.json({ msg: "you should receive an email from us" });
}) .catch((error) => console.error(error));};

We have a function called signup here. This function runs when a user makes a POST request to the URL /api/user/signup. You obviously know about that.

Then you can see there is pseudocode for the user signup. It is because this article focuses on sending email. Let’s not spend time on creating authentication system here. Okay?

Now let’s take a look at the response . It is an object, which takes in body. The body has the key name and intro . The name should be the name of our user. Note that we have received the name from the user through POST request.

Now let’s take a look at intro . The intro is the first section of the email that will be generated. The body has an option for the outro too; we will learn about it shortly.

Then you can see that we have a variable called mail . The MailGenerator.generate takes in response and returns us with html format of the email. We then have stored the HTML in the variable called mail.

Now let’s take a look at the variable called the message. In this variable, we created an object containing from, to, html, and subject. I hope you understood about it, as it is clear from the name itself. One more thing I want to mention here is that, you could’ve used a simple textual format over html format by using text instead of html in the message object.

You can see transporter.sendMail which takes in message object.

After that we have written code to check whether the message is sent to our user. If the message is sent to the user, we will send the user a status of 200 and response of a success message, else we will log the error.

Now let’s take a look at the getBill function. It looks like this:

const getBill = (req, res) => {  const { name, userEmail } = req.body;  let response = {    body: {      name,      intro: "Your bill has arrived!",      table: {        data: [{          item: "MERN stack book",          description: "A mern stack book",          price: "$10.99",        }],    },    outro: "Looking forward to do more business with you",   }};let mail = MailGenerator.generate(response);
let message = { from: EMAIL, to: userEmail, subject: "transaction", html: mail,};
.sendMail(message) .then(() => { return res.status(200) .json({ msg: "you should receive an email from us" }); }) .catch((error) => console.error(error));};

Most of the things are similar here, as implemented in the signup function. I’ll just explain about the things that are new. Okay?

One thing that is new here, is table object inside of the response object. The table object contains data , which is an array of objects. That object has three property item , description , price . It is pretty clear from the name itself, right? Notice that our bill data is hard coded here. We generally don’t hard code a bill, but for now we will be hardcoding it. Okay?

The other thing that’s new here is outro inside of the response object. The outro is the ending section of our email. There’s nothing new other than that.

Now let’s try this out. For that let’s open up Postman. Now let’s make a POST request to the URL http://localhost:3000/api/user/signup with postman.

Note that you must add two fields name and userEmail , where name must be user’s name and userEmail must be user’s email address. Don’t forget to add the header of Conent-Type as application/json in postman. Now make the POST request to the URL. You should receive an email saying something like this:

Image for post
Image for post

It looks good compared to normal text email, doesn’t it?

Now let’s do the same for our http://localhost:3000/api/product/get-the-bill . This should also be a POST request with the same header as before and the same fields i.e. name and userEmail. The email that the user will receive will look something like this:

Image for post
Image for post

This means we have learnt how to send email in node.js.

If you want to implement other email service provider, here’s a link, which shows some of the supported email service provider. If you want to dig deeper with nodemailer, you can follow this link, which will take you to its documentation. If you want to learn more about mailgen, you can check out mailgen’s documentation through this link.

JavaScript In Plain English

Did you know that we have four publications and a YouTube channel? Find them all at and subscribe to Decoded, our YouTube channel!

JavaScript In Plain English

New JavaScript + Web Development articles every day.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store