Sending Emails with Node.js Using SMTP, Gmail, and OAuth2

Nick Roach
8 min readMar 12, 2018

--

Edit: I’ve updated some of the code in this article to reflect changes to libraries, so please be sure you have the most up to date versions of your packages! If you find any issues/mistakes/room for improvement please leave a response, thanks for reading!

Edit 2: I made a small change to reflect the fact that the code in this article must be wrapped in an async function to work properly. Make sure to read up on async/await functions before reading this if you’re not familiar with them!

Edit 3: I made a change to remove the async function, as there is now a function that does all of the token stuff in one step. No need to worry about async/await anymore, but you should still check it out!

Edit 4: I removed my email address from the examples…make sure to replace the email addresses in the code with your gmail address and the email address you’d like to send an email to as necessary.

Edit 5: Sheesh, this thing took off in my absence. As always, more updates to code. I went through the responses and took those suggestions with a high number of claps (around 50 or more) and added those as potential code that may have to be added to make this work. Glad you’re all getting something out of this, keep responding with any changes that helped you get this working!

I spent a while searching Stack Overflow and Nodemailer’s documentation for a way to send emails using Node.js in a relatively concise way through my Gmail account. I found a lot of useful information, but many of the solutions required me to go into my account settings and Enable Less Secure Apps. That sounded way too scary for me, especially considering I had been saved by Google’s security measures on more than a few occasions.

So after quite a bit of digging, I found the current method of setting up OAuth2 for a Google Developer application and connecting it to the Nodemailer module using SMTP. Let’s go through the steps!

Step 1: Creating a New Project

The first thing we have to do is make a new project in the Google Developer Console. Once in the console, press Select a project in the top left corner.

Press “Select a project” in the top left corner

Once the window opens, press the + icon in the top right corner to create a new project.

Press “+” to add a new project

You’ll be brought to a new page to name your project. Once you give your project a name, press Create. It’ll take about 15 seconds for your project to be created, then go to Select a project again and select your project.

Step 2: Create API Credentials

Now that you have a new project, we have to give your project credentials! You should be on the project dashboard. It looks kind of intimidating right? Most of it isn’t necessary for what we need to do, all we have to do right now is open the project settings. Click Go to project settings at the bottom of the Project Info section of the dashboard.

Go to your project’s settings

In your project settings, there is a sidebar on the left with a bunch of different options. Click the last one that says API Credentials.

(I noticed that in another account I didn’t see the API Credentials tab on the sidebar in project settings. If this happens, go back to the dashboard and select Go to APIs overview under the APIs tab and select Credentials in the sidebar.)

Select “API Credentials”

Now you’re in a pretty bare page with just one section called “API Credentials”. Click the dropdown that says Create Credentials and choose OAuth client ID from the list.

Select “Oauth client ID” from the dropdown

You should see a little warning banner near the top of the page:

To create an OAuth client ID, you must first set a product name on the consent screen

Just press the Configure consent screen button on the banner and it’ll let you name your “product”. It doesn’t matter what you call it, just give it a name and press Save, then you should be redirected back to the Create client ID page.

Now under Application Type, choose Web Application and a small form will open up with sections for Name and Restrictions. You can give your client ID any name you like, but under Restrictions in the Authorized redirect URIs section add https://developers.google.com/oauthplayground. Now press Create!

Give your client ID a name and the redirect URI

Step 3: Save your Client ID and Client Secret

You should’ve been redirected to a page with a small “card” in the center with your client ID and client secret. Make sure to save these somewhere, you’ll need them soon! If you accidentally clicked out of that card before you could save your ID and secret, just click the name of your client ID and it’ll take you to its settings with the ID and secret at the top of the page!

Save your client ID and secret

Step 4: Configure OAuth

We need just a few more things before we get to the code. First, go to https://developers.google.com/oauthplayground and click the tools icon in the top right. Check the box that says Use your own OAuth credentials and enter your client ID and secret. Without closing out of the settings, enter https://mail.google.com/ into the box in the Select and authorize APIs section and press Authorize APIs. You should get a very scary-looking screen that looks like this:

Nothing to worry about, this just means Google hasn’t confirmed our app is okay to use (duh, we just made it). Click the Advanced button on the left and then press Go to Your App’s Name (unsafe). We get another, less intimidating screen that looks like this:

Click Allow and you should get redirected back to the OAuth page. Now go to Step 2 of the sidebar on the left and press Exchange authorization code for tokens.

This should populate the two boxes below called Refresh token and Access token with a couple of strings. Copy down the Refresh token as we’ll need it for later!

Step 5: Write Some Code!

That was extremely tedious and boring. Now we get to the fun part, writing the code and sending some emails! Start by making a project folder to put your email program in:

mkdir EmailerApp
cd EmailerApp

Now we need to initialize it as a node project:

npm init

Next, we need to install the library that we’ll use to send emails called Nodemailer, and also the Google OAuth client for Node.js:

npm install nodemailer googleapis

First, we’ll bring in the relevant packages:

// youremailprogram.jsconst nodemailer = require("nodemailer");
const { google } = require("googleapis");
const OAuth2 = google.auth.OAuth2;

Now we need to set up our OAuth client with all of our information that we’ve saved, you’ll need your client ID, your client secret, and the URL for the OAuth Playground that we used earlier:

const oauth2Client = new OAuth2(
"Your ClientID "Here", // ClientID
"Your Client Secret Here", // Client Secret
"https://developers.google.com/oauthplayground" // Redirect URL
);

Now we’re going to use the Refresh token that we held onto to get an Access token from OAuth.

“But wait, wasn’t there an access token in the OAuth Playground…why didn’t we just copy that one down?”

You might have noticed that when we received the refresh token and access token that OAuth told us right below that the access token would expire after about 3600 seconds. So to get a new access token, we have to provide our refresh token like so:

oauth2Client.setCredentials({
refresh_token: "Your Refresh Token Here"
});
const accessToken = oauth2Client.getAccessToken()

We now have to describe how we want to send the email using SMTP and Nodemailer:

const smtpTransport = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: "your.gmail.here@gmail.com",
clientId: "Your ClientID Here",
clientSecret: "Your Client Secret Here",
refreshToken: "Your Refresh Token Here",
accessToken: accessToken
}
});

According to chaim weiss, you may need to add the following attribute to the above javascript object:

tls: {
rejectUnauthorized: false
}

We have everything we need, let’s give our email some content!

const mailOptions = {
from: "your.gmail.here@gmail.com",
to: "some.other.email@gmail.com",
subject: "Node.js Email with Secure OAuth",
generateTextFromHTML: true,
html: "<b>test</b>"
};

Last but not least, let’s send our email!

smtpTransport.sendMail(mailOptions, (error, response) => {
error ? console.log(error) : console.log(response);
smtpTransport.close();
});

Now you should be able to run your emailer program:

node youremailprogram.js

and you should get something that looks like this!

{ accepted: [ 'some.other.email@gmail.com' ],
rejected: [],
envelopeTime: 183,
messageTime: 767,
messageSize: 300,
response: '250 2.0.0 OK 1535834445 w6-v6sm5381340ywg.3 - gsmtp',
envelope: {
from: 'your.gmail.here@gmail.com',
to: [ 'some.other.email@gmail.com' ]
},
messageId: '<62a8f8b7-021d-e332-e82b-454ea30c4d83@gmail.com>' }

By the way, if you’d like to send the email to multiple accounts, simply put all the accounts in the same string separated by a comma:

to: 'email1@gmail.com, email2@gmail.com, email3@gmail.com'

Small Disclaimer: This may be obvious to most, but this isn’t the proper way to store your OAuth information. You’ll want to store that information outside of your program in a secure way and then bring it in with your code.

I’m sure there are better ways of doing this, this was just what I came up with after a good bit of research and no other options that seemed as safe. If you have any suggestions for improvement or thoughts on better ways of sending a secure email please let me know in the comments! Thanks for reading!

--

--