Search code examples
node.jsoauth-2.0nodemailer

What is the definitive way to use Gmail with OAuth and Nodemailer?


Desired Behaviour

Use Gmail, OAuth2 and Nodemailer to send an email from a server side node.js file.

What I've Tried

Relevant Documentation

https://nodemailer.com/smtp/oauth2
https://nodemailer.com/usage/using-gmail
https://developers.google.com/gmail/api/auth/web-server

Relevant Questions

send emails from MY gmail account with OAuth2 and nodemailer
How do I authorise an app (web or installed) without user intervention?
https://stackoverflow.com/a/47936349
https://stackoverflow.com/a/22572776

There were gaps in the instructions of the above sources and some information was outdated, so the answer below was my final implementation which appears to be working.

I'm posting this solution for confirmation it is best practice and, if it is, to save others time.


Solution

  • The following worked for me, there are two parts:

    01) app.js

    02) Google and OAuth2 setup


    app.js

    var nodemailer = require("nodemailer");
    
    var transporter = nodemailer.createTransport({
        host: 'smtp.gmail.com',
        port: 465,
        secure: true,
        auth: {
            type: 'OAuth2',
            user: local_settings.my_gmail_username,
            clientId: local_settings.my_oauth_client_id,
            clientSecret: local_settings.my_oauth_client_secret,
            refreshToken: local_settings.my_oauth_refresh_token,
            accessToken: local_settings.my_oauth_access_token
        }
    });
    
    
    var mail = {
        from: "John Smith <me@mydomain.com>",
        to: "user@userdomain.com",
        subject: "Registration successful",
        text: "You successfully registered an account at www.mydomain.com",
        html: "<p>You successfully registered an account at www.mydomain.com</p>"
    }
    
    transporter.sendMail(mail, function(err, info) {
        if (err) {
            console.log(err);
        } else {
            // see https://nodemailer.com/usage
            console.log("info.messageId: " + info.messageId);
            console.log("info.envelope: " + info.envelope);
            console.log("info.accepted: " + info.accepted);
            console.log("info.rejected: " + info.rejected);
            console.log("info.pending: " + info.pending);
            console.log("info.response: " + info.response);
        }
        transporter.close();
    });
    

    Google and OAuth Setup

    The code above requires the following setup:

    01) Go to https://console.developers.google.com

    02) If you don't have a project, you will be prompted to create one

    enter image description here

    03) Click on Create Project

    04) Click on Create

    enter image description here
    05) Enter a Project Name and click Create

    enter image description here

    06) Select the Gmail API

    enter image description here

    07) Click on Enable

    enter image description here

    08) Click on Create Credentials

    enter image description here

    09) Enter the required settings

    enter image description here

    10) Give the OAuth client a name and ensure you add https://developers.google.com/oauthplayground as a redirect URI in order to generate the refresh and access tokens later

    enter image description here
    11) Define the consent screen settings

    enter image description here

    12) Click I'll do this later and Done

    enter image description here

    13) Click on the Edit icon, to view your Client ID and Client Secret

    enter image description here

    14) To generate access and refresh tokens, go to https://developers.google.com/oauthplayground

    15) Click on the cog icon in the top right, check Use your own OAuth credentials and enter Client ID and Client Secret

    enter image description here

    16) In the left column, select Gmail API v1 and click Authorise APIs

    enter image description here

    17) If you are signed into multiple accounts, when prompted select the relevant account

    enter image description here

    18) Click Allow

    enter image description here

    19) Click Exchange authorisation code for tokens

    enter image description here
    I'm not sure why there is a count down on the access token, but hopefully the message at the bottom of the screen means that the token won't expire.