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

Nodemailer+OAuth认证失败:535-5.7.8登录无效错误求助

Nodemailer 发送邮件触发 535-5.7.8 认证失败错误

配置Nodemailer发送邮件时,出现Error: Invalid login: 535-5.7.8 Username and Password not accepted错误。此前功能正常,更换公司账号测试后,原个人账号也无法使用。已重新创建OAuth客户端ID、通过OAuth Playground获取凭证,但问题依旧。能成功获取access token,但发送邮件时认证失败。

报错信息

Successfully retrieved access token <an up to date access token>
Error sending email: Error: Invalid login: 535-5.7.8 Username and Password not accepted. For more information, go to
535 5.7.8  https://support.google.com/mail/?p=BadCredentials 8926c6da1cb9f-4ec7458ef79sm1016661173.14 - gsmtp
    at SMTPConnection._formatError (C:\Users\Build\code\projxon\business-data-association\backend\node_modules\nodemailer\lib\smtp-connection\index.js:807:19)
    at SMTPConnection._actionAUTHComplete (C:\Users\Build\code\projxon\business-data-association\backend\node_modules\nodemailer\lib\smtp-connection\index.js:1586:34)
    at SMTPConnection.<anonymous> (C:\Users\Build\code\projxon\business-data-association\backend\node_modules\nodemailer\lib\smtp-connection\index.js:1565:26)
    at SMTPConnection._processResponse (C:\Users\Build\code\projxon\business-data-association\backend\node_modules\nodemailer\lib\smtp-connection\index.js:991:20)
    at SMTPConnection._onData (C:\Users\Build\code\projxon\business-data-association\backend\node_modules\nodemailer\lib\smtp-connection\index.js:772:14)
    at SMTPConnection._onSocketData (C:\Users\Build\code\projxon\business-data-association\backend\node_modules\nodemailer\lib\smtp-connection\index.js:195:44)
    at TLSSocket.emit (node:events:524:28)
    at addChunk (node:internal/streams/readable:561:12)
    at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
    at Readable.push (node:internal/streams/readable:392:5) {
  code: 'EAUTH',
  response: '535-5.7.8 Username and Password not accepted. For more information, go to\n' +
    '535 5.7.8  https://support.google.com/mail/?p=BadCredentials 8926c6da1cb9f-4ec7458ef79sm1016661173.14 - gsmtp',
  responseCode: 535,
  command: 'AUTH XOAUTH2'
}

相关代码

import express from "express";
import cors from "cors";
import nodemailer from "nodemailer";
import dotenv from "dotenv";
import { google } from "googleapis";

dotenv.config();

const app = express();
app.use(cors());
app.use(express.json());

const OAuth2Client = new google.auth.OAuth2(
  process.env.EMAIL_CLIENT_ID,
  process.env.EMAIL_CLIENT_SECRET,
  process.env.EMAIL_REDIRECT_URI 
);

OAuth2Client.setCredentials({
  refresh_token: process.env.EMAIL_REFRESH_TOKEN,
});

const getAccessToken = async () => {
  try {
    const { token } = await OAuth2Client.getAccessToken();
    if (!token) {
      throw new Error('No access token retrieved');
    }
    console.log("Successfully retrieved access token", token);
    return token;
  } catch (error) {
    console.error("Failed to create access token:", error);
    throw new Error("Failed to create access token.");
  }
};

const createTransporter = async () => {
  const accessToken = await getAccessToken();
  if (!accessToken) throw new Error("Failed to get access token");

  return nodemailer.createTransport({
    service: "gmail",
    auth: {
      type: "OAuth2",
      user: process.env.EMAIL_USER,
      clientId: process.env.EMAIL_CLIENT_ID,
      clientSecret: process.env.EMAIL_CLIENT_SECRET,
      refreshToken: process.env.EMAIL_REFRESH_TOKEN,
      accessToken, 
    },
  });
};

app.post("/send-email", async (req, res) => {
  const { name, email, message } = req.body;

  const mailOptions = {
    from:{process.env.EMAIL_USER}, 
    to: email, 
    subject: "Thank Youn!",
    text: `Hi ${name}`,
    replyTo: process.env.EMAIL_USER, 
  };

  try {
    const transporter = await createTransporter();
    await transporter.sendMail(mailOptions);
    res.status(200).json({ message: "Email sent successfully!" });
  } catch (error) {
    console.error("Error sending email:", error);

    if (error.responseCode === 535) {
      res.status(401).json({ error: "Authentication error. Please check your credentials." });
    } else {
      res.status(500).json({ error: "Error sending email. Please try again later." });
    }
  }
});


const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

已尝试方案

  • 重新创建OAuth客户端凭证
  • 本地测试个人及公司账号

解决办法

1. 确认OAuth权限范围

在Google Cloud控制台或OAuth Playground中,为客户端ID添加https://mail.google.com/权限范围——这是Gmail发送邮件所需的完整权限,仅用https://www.googleapis.com/auth/gmail.send可能导致认证失败。

2. 刷新令牌有效性校验

更换账号后旧刷新令牌会失效,需:

  • 重新在OAuth Playground中授权目标账号,获取最新刷新令牌
  • 核对.env文件中EMAIL_REFRESH_TOKEN与新令牌完全一致

3. 检查账号安全设置

  • 个人账号:确认是否开启了第三方应用访问权限(OAuth2虽不强制,但部分场景可能受影响)
  • 公司账号:联系管理员确认是否有安全策略限制第三方应用发送邮件

4. 修正代码语法错误

mailOptions中from字段写法错误,且存在笔误,修正如下:

const mailOptions = {
  from: process.env.EMAIL_USER, // 或完整对象格式:{ name: "自定义名称", address: process.env.EMAIL_USER }
  to: email, 
  subject: "Thank You!", // 修正笔误:Youn → You
  text: `Hi ${name}`,
  replyTo: process.env.EMAIL_USER, 
};

5. 移除旧授权记录

访问Google账号的第三方应用管理页面,删除旧的客户端授权记录,重新授权获取刷新令牌。

6. 交由Nodemailer自动管理令牌

无需手动获取access token,Nodemailer可自动处理令牌刷新,修改createTransporter函数:

const createTransporter = () => {
  return nodemailer.createTransport({
    service: "gmail",
    auth: {
      type: "OAuth2",
      user: process.env.EMAIL_USER,
      clientId: process.env.EMAIL_CLIENT_ID,
      clientSecret: process.env.EMAIL_CLIENT_SECRET,
      refreshToken: process.env.EMAIL_REFRESH_TOKEN,
    },
  });
};

内容的提问来源于stack exchange,提问作者EvanPrograms

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 17:27:04