GSuite Error: Can't create new access token for user - OAuth2 Nodemailer

GSuite Error: Can't create new access token for user - OAuth2 Nodemailer

我正在尝试从 nodejs 通过 gmail 发送电子邮件,但我一直 运行 进入此错误。

Error: Can't create new access token for user
  at XOAuth2.generateToken(c: \apps\node\myapp\node_modules\nodemailer\lib\xoauth2\index.js: 184: 33)
  at XOAuth2.getToken(c: \apps\node\myapp\node_modules\nodemailer\lib\xoauth2\index.js: 123: 18)
  at SMTPConnection._handleXOauth2Token(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 1697: 27)
  at SMTPConnection.login(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 540: 22)
  at c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - transport\index.js: 374: 32
  at SMTPConnection.<anonymous>(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 215: 17)
  at Object.onceWrapper(events.js: 420: 28)
  at SMTPConnection.emit(events.js: 314: 20)
  at SMTPConnection._actionEHLO(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 1313: 14)
  at SMTPConnection._processResponse(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 942: 20)
  at SMTPConnection._onData(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 749: 14)
  at TLSSocket.SMTPConnection._onSocketData(c: \apps\node\myapp\node_modules\nodemailer\lib\smtp - connection\index.js: 195: 44)
  at TLSSocket.emit(events.js: 314: 20)
  at addChunk(_stream_readable.js: 304: 12)
  at readableAddChunk(_stream_readable.js: 280: 9)
  at TLSSocket.Readable.push(_stream_readable.js: 219: 10) {
  code: 'EAUTH',
    command: 'AUTH XOAUTH2'
}

我已经设置了我的 G Suite 帐户,创建了一个服务帐户并为该项目启用了 Gmail API。我还为服务帐户启用了 G-Suite 域范围委托,并将客户端 ID 和适当的范围添加到我的 G Suite 帐户。

我下载了我的凭据文件并将其重命名为使用 .js 这样我就可以将其作为 ES 模块导入。

import nodemailer from "nodemailer";
import * as key from "../credentials.js";

const SENDER_EMAIL = "support@domain.com";
const RECEIVER_EMAIL = "customer@gmail.com";

async function start() {
  const transporter = nodemailer.createTransport({
    host: "smtp.gmail.com",
    port: 465,
    secure: true,
    auth: {
      type: "OAuth2",
      user: SENDER_EMAIL,
      serviceClient: key.client_id,
      privateKey: key.private_key,
    },
  });

  try {
    await transporter.verify();
    await transporter.sendMail({
      from: SENDER_EMAIL,
      to: RECEIVER_EMAIL,
      subject: "Hello Humans",
      text: "The quick brown fox jumps over the lazy dog.",
    });
  } catch (err) {
    console.error(err);
  }
}

export default start;

现在,调用 start() 时出现上述消息的错误。我想不通。帮助。

我希望你在 11 个月前解决了你的问题,但是,对于那些发现这个问题的人,我遇到了同样的问题并找到了答案 here。我相信这可能是你的情况,因为你提到硬编码值确实有效。

显然,私钥中的 \n 以这种方式使用会带来一些问题。在我的例子中,我从 Firebase runtime config 中获取私钥值,并遵循 link 中的建议,我最终在密钥上得到了 replace(/\n/g, '\n')

const nodemailerTransporter = nodemailer.createTransport({
  host: env.nodemailer.host,
  port: 465,
  secure: true, // true for TLS 465, false for other ports
  auth: {
    type: "OAuth2",
    user: env.nodemailer.user,
    serviceClient: env.nodemailer.clientid,
    privateKey: env.nodemailer.privatekey.replace(/\n/g, '\n'),  // <=== HERE
    accessUrl: env.nodemailer.tokenuri, // <== HERE
  },
});

这确实有效。我使用的是 "host": "smtp-relay.gmail.com",但你的 smtp.gmail.com 情况也是如此。

还要考虑 accessUrl(取自 credentials.json 的 token_uri):

"token_uri": "https://oauth2.googleapis.com/token"

这与 nodemailer 使用的默认值不同 (https://accounts.google.com/o/oauth2/token)。 IDK 如果这很重要。