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
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:

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:

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:

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:

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:

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,
pass: PASSWORD
},});
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,};
transporter .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:

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:

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 plainenglish.io and subscribe to Decoded, our YouTube channel!