How to Send Emails with Google OAuth Refresh Tokens in a MERN App

karan khatikkaran khatik
4 min read

Hey there! In this guide, we’re going to explore how you can generate a Google OAuth refresh token directly from your application to send emails, instead of using the Google Developer Playground. This method not only helps you manage tokens more efficiently but also makes your email sending process smoother. If you haven't seen my previous blog on sending emails using Google OAuth, you can check it out here: How to Send Emails Using Google OAuth in Node.js.

In the earlier blog, I used Google Developer Playground to get the refresh token, but that's not the ideal method for production. So, let’s explore a better way to handle it within our app.

📋 Prerequisites

Before we jump in, make sure you have:

  1. Client ID and Client Secret: If you haven’t created them yet, follow the steps in my previous blog to get them.

🔍 High-Level Overview

Here’s how we’ll generate the refresh token and use it to send emails:

  1. Generate the OAuth URL: We’ll create a URL with the required scopes (like sending emails).

  2. Authenticate and Get Tokens:: This URL will redirect you to Google’s login page where you log in with your Gmail account. After logging in, Google will redirect you to a callback URL. Here, we will capture the refresh token and save it in our database for future use.

  3. Send Emails with Nodemailer: Use the refresh token to authenticate Nodemailer and send emails.

high-level-diagram-for-sending-email

🛠️ Step-by-Step Guide

1. Generate the OAuth URL

We start by creating an OAuth URL that users will visit to authenticate and authorize our application. Here’s a basic example of how to generate this URL in Node.js:

cosnt { google } = require('googleapis');
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URI
);

// Generate the URL
const scopes = ['https://www.googleapis.com/auth/gmail.send'];
const authUrl = oauth2Client.generateAuthUrl({
  access_type: 'offline',
  scope: scopes,
});

console.log('Authorize this app by visiting this url:', authUrl);

Replace YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, and YOUR_REDIRECT_URI with your actual values.

2. Authenticate and Get the Refresh Token

Once you go to the generated URL and log in, Google will send you to your callback URL. You need to handle this redirect to get the authorization code, which you can then exchange for tokens:

javascriptCopy codeconst code = 'authorization_code_from_google';

oauth2Client.getToken(code, (err, tokens) => {
  if (err) {
    console.error('Error retrieving access token', err);
    return;
  }

  // Save the refresh token and other tokens
  oauth2Client.setCredentials(tokens);
  console.log('Refresh Token:', tokens.refresh_token);
  // Save tokens.refresh_token to your database
});

3. Send Emails Using Nodemailer and the Refresh Token

With the refresh token saved, you can use it with Nodemailer to send emails. Here’s how you can set it up:

const nodemailer = require('nodemailer');
const { google } = require('googleapis');

// Create OAuth2 client
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URI
);

// Set refresh token
oauth2Client.setCredentials({
  refresh_token: 'your_saved_refresh_token',
});

async function sendMail() {
  try {
    // Get access token
    const accessToken = await oauth2Client.getAccessToken();

    // Create transporter with OAuth2
    const transporter = nodemailer.createTransport({
      service: 'gmail',
      auth: {
        type: 'OAuth2',
        user: 'your_email@gmail.com',
        clientId: YOUR_CLIENT_ID,
        clientSecret: YOUR_CLIENT_SECRET,
        refreshToken: 'your_saved_refresh_token',
        accessToken: accessToken.token,
      },
    });

    // Define email options
    const mailOptions = {
      from: 'your_email@gmail.com',
      to: 'recipient@example.com',
      subject: 'Test Email',
      text: 'Hello world!',
    };

    // Send email
    const result = await transporter.sendMail(mailOptions);
    console.log('Email sent:', result);
  } catch (error) {
    console.error('Error sending email:', error);
  }
}

// Execute sendMail function
sendMail();

🚀 Final Notes

  • Client Origin: Make sure your app's client origin and callback route are correctly set in your Google Cloud Console to match those used in your code.

  • Server Route: This is the URL where Google will send the authorization code. Ensure it's correctly set up to handle this in your app.

Above is a high-level overview of the approach. If you get stuck or want to see a proper example, check out the complete example and more details in the GitHub repository.

Thanks for reading! I hope this guide helps you simplify your email sending process with Google OAuth. If you have any questions or need more details, feel free to reach out.

0
Subscribe to my newsletter

Read articles from karan khatik directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

karan khatik
karan khatik

I'm a Full Stack Developer specializing in the MERN stack, passionate about learning and writing to share knowledge and insights.