Reputation: 468
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,
},
});
Upvotes: 1
Views: 1114
Reputation: 468
Setting the testing mode into a production mode in Google Developer Console will prevent refresh token from exipiring.
Upvotes: 0
Reputation: 11
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
Upvotes: 1