简体   繁体   中英

Google refresh token 7-day expiration period in Nodemailer

Google shuts down "Less secure app" feature on their mail services last month. Because of this, I cannot just use Nodemailer by using email and password only. I am forced to setup Nodemailer with Google OAuth. But, the refresh token expires every week. What should I do?

Here's my transporter code.

const transporter = nodemailer.createTransport({
            service: 'gmail',
            auth: {
                type: 'OAuth2',
                user: process.env.GA_MAIL,
                accessToken,
                clientId: process.env.GA_CLIENT_ID,
                clientSecret: process.env.GA_CLIENT_SECRET,
                refreshToken: process.env.GA_REFRESH_TOKEN,
            },
});

This is the problem better worded :

This is the file token.js :

const { google } = require('googleapis');
const path = require('path');
const fs = require('fs');
const credentials = require('./email.json');

// Replace with the code you received from Google
const code = "";
const { client_secret, client_id, redirect_uris } = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

oAuth2Client.getToken(code).then(({ tokens }) => {
  const tokenPath = path.join(__dirname, 'token.json');
  fs.writeFileSync(tokenPath, JSON.stringify(tokens));
  console.log('Access token and refresh token stored to token.json');
});

when running the token.js file a file called token.json gets created with some access tokens :

{"access_token":"","refresh_token":"","scope":"https://www.googleapis.com/auth/gmail.send","token_type":"Bearer","expiry_date":1656595108942}

but after 7 days the access_token expires.

A solution I came up with , though it's untested , is to have inside a .catch() block a call for a token refresh like so :

main.js :

//...
const refreshToken = require("./refresh_token.js");
//...
}).catch((err) => {
    reply(interaction,"Error, Refreshing token.. Please try again");
    console.error(err);
    refreshToken();
    return;
});
//...

refresh_token.js :

const { google } = require('googleapis');
const path = require('path');
const fs = require('fs');
const credentials = require('./email.json');
const token = require("./token.json");

module.exports = () => {
  const code = token.refresh_token;
  const { client_secret, client_id, redirect_uris } = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

  oAuth2Client.getToken(code).then(({ tokens }) => {
    const tokenPath = path.join(__dirname, 'token.json');
    fs.writeFileSync(tokenPath, JSON.stringify(tokens));
    console.log('Access token and refresh token stored to token.json');
  });
}

The reason I put it in a catch statement is because when the token is not expired we get a invalid_grant error when trying to run oAuth2Client.getToken(token.refresh_token)

^^ THIS HAS NOT BEEN TESTED ^^

if the refresh_token expires as well then I have no idea how to do this , please help

Setting the testing mode into a production mode in Google Developer Console will prevent refresh token from exipiring.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM