Configure Gmail Authentication with Nodemailer

Setting up authentication with Gmail in node via Nodemailer causes issues when simply using your plain password. If you Google this issue many people will point you to use something called "Less Secure App Access, however, can't use Less Secure Apps (shown below) anymore, and this change is fairly recent.

To circumvent this issue one must use an "App Password" generated from their Gmail account. Now although this may appear to be Two Factor Authentication, it is not the case and it is misleading. An App Password is used for devices that are not set up for two-factor authentication. However, to get an app password from your account, you need to enable two-factor authentication, which seems counterintuitive. 

Step 1-) Enable Two Factor Authentication In Your Gmail Account

To do this go into the settings for the corresponding Gmail account you will be using with Nodemailer at:

https://myaccount.google.com/security

Find the steps for two-factor authentication and set it up accordingly. Once it is done it should look like the image below.

2-) Generate An App Password

Simply click the App Passwords link in the Security section of your profile settings:

https://myaccount.google.com/security

Eventually, this will lead you to a screen to generate an app password as shown below. I was using a Mac so I just selected Mac, but it does not necessarily matter.

3-) Setup your transporter in Node with the corresponding credentials

Create a javascript file with the following content

var dotenv = require("dotenv")
dotenv.config()

const nodemailer = require("nodemailer");
let transporter = nodemailer.createTransport({
    service: 'Gmail',
    host: 'smtp.gmail.com',
    secure: false,
    auth: {
        user: process.env.EMAIL_TEST,
        pass: process.env.EMAIL_TEST_APP_PSWD
    },
})

I set up this file as a service in my services directory, but you can place it as you like. I also used a .env file to save my variables in, however, if you like you can just hardcode the values for your email account into the file. 

4-) Utilize your transporter object to send an email (optional)

At this point, if you followed the steps correctly you should no longer have any authentication issues regarding your Gmail account. So you are good to go, now you can use the transporter as you like.

In my use case, I used the transporter object to send an email when users sign up for my application to verify their email exists.

module.exports = {
    verifyUserEmail: async function verifyUserEmail(name, userEmail, username, token) {
        try {
            let info = await transporter.sendMail({
                from: process.env.EMAIL_TEST,
                to: userEmail,
                subject: "Hello " + name + " please verify your email by clicking the link",
                html: process.env.homepageDev + "/verifyUserEmail/" + username + "/" + token,
            })
        } catch (err) {
            console.log(err)
        }
    }
}

In the exported function (verifyUserEmail)  it takes in:

    name: Name of the user

    userEmail: The email we are sending to

    username: The username of the user in my application

    token: A JWT token that is linked to the user

I import this function to my routes handler as follows:

const emails = require('../services/Email');

I then utilize the imported function as follows:

router.post('/signup', async (req, res) => {
    const signedUpUser = new Schemas.SignUp({
        fullName: req.body.fullName,
        username: req.body.username,
        email: req.body.email,
        password: req.body.password,
        role: req.body.role
    })
    const emailToken = jwt.sign({
        username: req.body.username
    }, 'secret1234', { expiresIn: '1h' })
    emails.verifyUserEmail(req.body.fullName, req.body.email, req.body.username, emailToken)
    signedUpUser.save()
        .then(data => {
            res.json(data)
        })
        .catch(error => {
            res.json(error)
        })
}) 

Conclusion

We are done, this is a good example of how to use the transporter you created from end to end. I hope this tutorial was clear regarding how to get your Gmail configured properly with Nodemailer. The main takeaway is that one-factor authentication with just a password is no longer useable, nor can we use the previously popular "Less Secure Apps" method as detailed across the internet. Thankfully we have App Passwords, and this is a nice and simple way to get your transporter object setup easily. Thanks for reading everyone, now get out of here and spam some emails to your users!

Create a free account to access full content.

All access to code and resources on ShillehTek.

Signup Now

Already a member? Sign In

Explore More on Our Blog

Controlling an LED with a Snap Using the KY-037 Sound Sensor and Raspberry Pi

Controlling an LED with a Snap Using the KY-037 Sound Sensor and Raspberry Pi

Discover how to set up, code, and activate the LED based on detected sound with the Raspberry Pi...

Getting Started with the KY-037 Sound Sensor and Raspberry Pi: Detecting Sound Using Python

Getting Started with the KY-037 Sound Sensor and Raspberry Pi: Detecting Sound Using Python

In this tutorial, I’ll guide you through setting up the KY-037 sound sensor with a Raspberry Pi using...

How to Post to Reddit Using Python

How to Post to Reddit Using Python

Post to reddit automatically using a Python script.

How to Create a Time-Lapse Video with a Raspberry Pi Camera

How to Create a Time-Lapse Video with a Raspberry Pi Camera

Learn how to make a timelapse with your Raspberry Pi in Python.

How to Integrate the MPU6050 with the STM32 Blue Pill

How to Integrate the MPU6050 with the STM32 Blue Pill

Learn how to measure acceleration with the STM32 and the MPU6050 in the Arduino IDE.

Getting Started with STM32 Blue Pill in Arduino IDE Using a USB to TTL Converter — Write Your First Program

Getting Started with STM32 Blue Pill in Arduino IDE Using a USB to TTL Converter — Write Your First Program

This comprehensive tutorial will guide you through the process of setting up and programming the STM32 Blue Pill...

Automate Task Scheduling in AWS with Lambda, Step Functions, and CloudWatch

Automate Task Scheduling in AWS with Lambda, Step Functions, and CloudWatch

In this tutorial, I'll show you how to automatically schedule tasks in AWS at regular intervals using AWS...

Implementing Google reCAPTCHA in a Simple React and Node.js App

Implementing Google reCAPTCHA in a Simple React and Node.js App

Learn how to protect your React applications from bots and spam with Google reCAPTCHA integration! This step-by-step tutorial...

AWS Lambda Tutorial: Using Selenium with Chromedriver in Python

AWS Lambda Tutorial: Using Selenium with Chromedriver in Python

In this tutorial, I will guide you through the process of running Selenium with ChromeDriver inside an AWS...

How to Connect MLX90614 Infrared Thermometer to Raspberry Pi Pico W: MicroPython Tutorial!

How to Connect MLX90614 Infrared Thermometer to Raspberry Pi Pico W: MicroPython Tutorial!

Learn how to use the MLX90614 with the Raspberry Pi Pico W and get infrared values in MicroPython.

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.