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

使用ImapFlow读取Gmail收件箱时提示‘Invalid credentials (Failure)’错误

问题描述

我尝试用NodeJS读取Gmail收件箱,已创建Gmail账号并在Google Cloud配置OAuth应用,拿到了ClientID、ClientSecret和refresh token,但运行脚本时出现认证失败错误。

我的脚本

import xoauth2 from 'xoauth2';
import { ImapFlow } from 'imapflow';

const xoauth2Gen = xoauth2.createXOAuth2Generator({
    user: 'MY_EMAIL@gmail.com',
    clientId: 'XXXXXXX.apps.googleusercontent.com',
    clientSecret: 'XXXX',
    refreshToken: 'XXXXXXX',
});

const PreTestsAuthentication = async () => {
    const xoauth2Token = await new Promise<string>((resolve, reject) => {
        xoauth2Gen.getToken((error: unknown, token: string) => {
            if (error) {
                return reject(error);
            }

            return resolve(token);
        });
    });

    const client = new ImapFlow({
        host: 'imap.gmail.com',
        port: 993,
        secure: true,
        auth: {
            user: 'MY_EMAIL@gmail.com',
            pass: 'XXXXX',
            accessToken: xoauth2Token,
        },
    });

    await client.connect();

    await client.logout();
};

export default PreTestsAuthentication;

错误信息

{
  "response": "3 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)",
  "responseStatus": "NO",
  "responseText": "Invalid credentials (Failure)",
  "serverResponseCode": "AUTHENTICATIONFAILED",
  "authenticationFailed": true,
  "oauthError": {
    "status": "invalid_request",
    "scope": "https://mail.google.com/"
  }
}

refresh token获取方式

  • 遵循Drive API快速开始指南获取refresh token
  • 使用的代码:
const client = await authenticate({
    scopes: ['https://www.googleapis.com/auth/drive.metadata.readonly'],
    keyfilePath: CREDENTIALS_PATH,
});

从client对象提取refresh_token用于上述脚本。


解决方案

1. 核心问题:Scope不匹配

你获取refresh token时用的是Drive只读权限的scope,但访问Gmail IMAP必须使用Gmail相关权限,需包含https://mail.google.com/(IMAP访问所需的完整权限),或更窄的https://www.googleapis.com/auth/gmail.readonly(仅读取需求时可用)。

需重新获取带有Gmail scope的refresh token:

  • 修改认证代码的scopes:
const client = await authenticate({
    scopes: ['https://mail.google.com/'],
    keyfilePath: CREDENTIALS_PATH,
});
  • 重新运行认证流程,替换原refresh token(旧token因权限范围不匹配,无法用于Gmail认证)。

2. 修正ImapFlow的Auth配置

代码中同时传入pass和accessToken会导致冲突,OAuth认证无需密码,仅保留user和accessToken即可。

3. 改用官方Google Auth库(推荐)

xoauth2库维护活跃度低,建议使用官方google-auth-library生成access token,兼容性更有保障。


修正后的代码
import { ImapFlow } from 'imapflow';
import { OAuth2Client } from 'google-auth-library';

const oauth2Client = new OAuth2Client({
  clientId: 'XXXXXXX.apps.googleusercontent.com',
  clientSecret: 'XXXX',
  refreshToken: '新获取的带Gmail scope的refreshToken',
});

const PreTestsAuthentication = async () => {
  // 获取access token
  const { token } = await oauth2Client.getAccessToken();
  if (!token) {
    throw new Error('Failed to get access token');
  }

  const client = new ImapFlow({
    host: 'imap.gmail.com',
    port: 993,
    secure: true,
    auth: {
      user: 'MY_EMAIL@gmail.com',
      accessToken: token,
    },
  });

  try {
    await client.connect();
    console.log('Authentication successful!');
  } catch (err) {
    console.error('Authentication failed:', err);
  } finally {
    await client.logout();
  }
};

export default PreTestsAuthentication;

额外注意事项

  • 确保Google Cloud OAuth应用的授权域名、重定向URI配置正确(本地测试常用http://localhost:3000)。
  • Gmail账号需开启IMAP访问:设置→转发和POP/IMAP→IMAP访问→启用IMAP。
  • Google Workspace账号需管理员允许该OAuth应用的权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:13:36