如何在Node.js中自动获取Google刷新令牌?Strapi邮件发送故障求助
问题描述
我正在Strapi CMS中开发一款邮件发送插件,使用Nodemailer和Google OAuth2实现功能,但令牌会在1小时后自动过期。我尝试了多种方法,但代码仍无法正常运行,以下是我的代码:
const nodemailer = require("nodemailer"); const { google } = require("googleapis"); const OAuth2 = google.auth.OAuth2; const oauth2Client = new OAuth2( `"${process.env.CLIENT_ID }"`, `"${process.env.CLIENT_SECRET}"`, "https://developers.google.com/oauthplayground", ); // oauth2Client.setCredentials({ // refresh_token: `"${process.env.REFRESH_TOKEN }"`, // }); // const accessToken = oauth2Client.getAccessToken() module.exports = ({ env }) => ({ // ... email: { provider: env(`${process.env.REACT_APP_EMAIL_PROVIDER}`), providerOptions: { host: env("EMAIL_SMTP_HOST", "smtp.gmail.com"), port: env("EMAIL_SMTP_PORT", 587), auth: { type: "OAuth2", user: "hotrodhv58@gmail.com", clientId: `"${process.env.CLIENT_ID }"`, clientSecret: `"${process.env.CLIENT_SECRET}"`, refreshToken: `"${process.env.REFRESH_TOKEN}"`, accessToken: `"${process.env.ACCESS_TOKEN}"`, }, }, settings: { defaultFrom: env(`${process.env.REACT_APP_EMAIL_ADDRESS_FROM}`), defaultReplyTo: env(`${process.env.REACT_APP_EMAIL_ADDRESS_REPLY}`), }, }, // ... });
遇到的错误
- 基础认证错误:
Error sending email to xxxxssss@gmail.com {"code":"EAUTH","command":"AUTH XOAUTH2"}
- 使用Async Await后的连接错误:
{"Errno":-4078, "code": "Esocket", "Syncall": "Connect", "Address":"127.0.0.1", "Port": 587, "Command": "Conn"}}
解决方案
1. 移除环境变量的多余引号
代码中给环境变量套了额外双引号("${process.env.CLIENT_ID}"),会导致认证参数带上无效引号,直接使用原始环境变量即可:
const oauth2Client = new OAuth2( process.env.CLIENT_ID, process.env.CLIENT_SECRET, "https://developers.google.com/oauthplayground" ); // auth配置部分 auth: { type: "OAuth2", user: "hotrodhv58@gmail.com", clientId: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, refreshToken: process.env.REFRESH_TOKEN, },
2. 启用AccessToken自动刷新
Google OAuth2的AccessToken默认1小时过期,无需手动维护,Nodemailer可通过RefreshToken自动获取新令牌。修改代码如下:
const nodemailer = require("nodemailer"); const { google } = require("googleapis"); const OAuth2 = google.auth.OAuth2; const oauth2Client = new OAuth2( process.env.CLIENT_ID, process.env.CLIENT_SECRET, "https://developers.google.com/oauthplayground" ); oauth2Client.setCredentials({ refresh_token: process.env.REFRESH_TOKEN, }); module.exports = ({ env }) => ({ // ... email: { provider: env("REACT_APP_EMAIL_PROVIDER"), providerOptions: { host: env("EMAIL_SMTP_HOST", "smtp.gmail.com"), port: env("EMAIL_SMTP_PORT", 587), secure: false, // 587端口使用TLS,需设为false auth: { type: "OAuth2", user: "hotrodhv58@gmail.com", clientId: process.env.CLIENT_ID, clientSecret: process.env.CLIENT_SECRET, refreshToken: process.env.REFRESH_TOKEN, // 自动获取并刷新AccessToken accessToken: async () => { const { token } = await oauth2Client.getAccessToken(); return token; }, }, }, settings: { defaultFrom: env("REACT_APP_EMAIL_ADDRESS_FROM"), defaultReplyTo: env("REACT_APP_EMAIL_ADDRESS_REPLY"), }, }, // ... });
3. 修复Esocket连接错误
错误原因是provider配置错误嵌套了process.env,导致Strapi无法识别邮件提供商,尝试连接本地端口。直接使用env("REACT_APP_EMAIL_PROVIDER")即可,无需额外嵌套。
4. 验证Google OAuth配置
- 确保Google Cloud项目已启用Gmail API
- 确认RefreshToken、Client ID、Client Secret均有效
- 未验证的应用需将目标邮箱添加为OAuth同意屏幕的测试用户
内容的提问来源于stack exchange,提问作者BinChanhKun
相关产品推荐
相关产品推荐

