diff --git a/get-refresh-token.js b/get-refresh-token.js new file mode 100644 index 0000000..352e401 --- /dev/null +++ b/get-refresh-token.js @@ -0,0 +1,84 @@ +/** + * One-time script to generate a Gmail OAuth2 refresh token. + * Run once, copy the refresh token into .env, then delete this file. + * + * Usage: + * node get-refresh-token.js + * + * Prerequisites: + * - GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET set in .env (or exported in shell) + * - In Google Cloud Console → OAuth 2.0 Client → Authorized redirect URIs: + * add http://localhost:3000/oauth2callback + */ + +require('dotenv').config(); +const { google } = require('googleapis'); +const http = require('http'); +const url = require('url'); + +const CLIENT_ID = process.env.GOOGLE_CLIENT_ID; +const CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET; +const REDIRECT_URI = 'http://localhost:3000/oauth2callback'; + +if (!CLIENT_ID || !CLIENT_SECRET) { + console.error('GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must be set in .env'); + process.exit(1); +} + +const oauth2Client = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI); + +const authUrl = oauth2Client.generateAuthUrl({ + access_type: 'offline', + prompt: 'consent', // forces refresh_token to be returned even if previously authorized + scope: [ + 'https://www.googleapis.com/auth/gmail.readonly', + 'https://www.googleapis.com/auth/gmail.send', + 'https://www.googleapis.com/auth/gmail.modify', + ], +}); + +console.log('\n=== Gmail OAuth2 Token Generator ===\n'); +console.log('1. Open this URL in your browser:\n'); +console.log(authUrl); +console.log('\n2. Authorize the app with your support Gmail account.'); +console.log('3. You will be redirected to localhost — this script will capture the token.\n'); + +// Temporary local server to capture the callback +const server = http.createServer(async (req, res) => { + const parsed = url.parse(req.url, true); + if (parsed.pathname !== '/oauth2callback') { + res.end('Not found'); + return; + } + + const code = parsed.query.code; + if (!code) { + res.end('No code received.'); + server.close(); + return; + } + + try { + const { tokens } = await oauth2Client.getToken(code); + res.end('
You can close this tab.
'); + server.close(); + + console.log('\n=== SUCCESS ===\n'); + console.log('Add this to your .env:\n'); + console.log(`REFRESH_TOKEN=${tokens.refresh_token}`); + if (!tokens.refresh_token) { + console.log('\nWARNING: No refresh_token returned.'); + console.log('Go to https://myaccount.google.com/permissions and revoke access for your app, then run this script again.'); + } + console.log('\nAll tokens (for reference):'); + console.log(JSON.stringify(tokens, null, 2)); + } catch (err) { + res.end('Error exchanging code: ' + err.message); + server.close(); + console.error('Error:', err); + } +}); + +server.listen(3000, () => { + console.log('Waiting for OAuth callback on http://localhost:3000 ...\n'); +});