You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:20:37