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

使用Nodemailer+Google APIs做3LO认证时遇PLAIN凭证缺失错误

解决Next.js API路由中Nodemailer+Google服务发邮件的"Missing credentials for 'PLAIN'"错误

核心问题分析

这个错误本质是Nodemailer无法获取PLAIN认证所需的有效凭据,你的两种尝试分别踩了不同的坑:

1. OAuth2方式的拼写错误

初始代码里的auth.type写成了'0Auth2'(数字0,不是字母O),导致Nodemailer无法识别OAuth2认证类型,自动降级为PLAIN认证,但PLAIN需要的pass字段未提供,因此触发报错。

2. 应用密码方式的环境变量加载问题

改用应用密码后仍报错,大概率是环境变量未正确读取,比如process.env.GOOGLE_EMAIL或process.env.GOOGLE_APP_PASSWORD返回undefined,导致PLAIN认证缺少必要的用户名/密码。


修正方案

方案一:修复OAuth2配置

修正auth.type的拼写错误,同时添加环境变量非空校验:

import type { NextApiRequest, NextApiResponse } from 'next';
import { google } from 'googleapis';
import nodemailer from 'nodemailer';

const handleSendVerificationEmail = async (req: NextApiRequest, res: NextApiResponse) => {
  const { email } = req.body;

  // 读取并校验环境变量
  const user = process.env.GOOGLE_EMAIL_ADDRESS;
  const clientId = process.env.GOOGLE_CLIENT_ID_MAIL;
  const clientSecret = process.env.GOOGLE_CLIENT_SECRET_MAIL;
  const refreshToken = process.env.GOOGLE_REFRESH_TOKEN;
  const redirectURI = process.env.GOOGLE_REDIRECT_URI;

  if (!user || !clientId || !clientSecret || !refreshToken || !redirectURI) {
    return res.status(500).json({ error: '缺少OAuth2认证凭据' });
  }

  const oAuth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectURI);
  oAuth2Client.setCredentials({ refresh_token: refreshToken });

  try {
    const accessToken = await oAuth2Client.getAccessToken();

    const transporter = nodemailer.createTransport({
      host: 'smtp.gmail.com',
      port: 465,
      secure: true,
      auth: {
        type: 'OAuth2', // 修正拼写:字母O,不是数字0
        user,
        clientId,
        clientSecret,
        refreshToken,
        accessToken: accessToken.token as string,
      },
    });

    const mailOptions = {
      from: `YourTable <${user}>`,
      to: email,
      subject: 'Hello from gmail using API',
      text: 'Hello from gmail email using API',
      html: '<h1>Hello from gmail email using API</h1>',
    };

    await transporter.sendMail(mailOptions);
    res.status(200).json({ email });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: '无法发送验证邮件' });
  }
};

export default handleSendVerificationEmail;

方案二:确保应用密码的环境变量正确加载

  1. 在项目根目录创建.env.local文件,写入正确凭据:
GOOGLE_EMAIL=你的谷歌邮箱账号@gmail.com
GOOGLE_APP_PASSWORD=你的16位应用密码

注意:应用密码需要谷歌账号开启两步验证后才能生成,生成后直接复制16位字符串即可,无需保留空格。

  1. 修改API路由代码,添加凭据校验:
import type { NextApiRequest, NextApiResponse } from 'next';
import nodemailer from 'nodemailer';

const handleSendVerificationEmail = async (req: NextApiRequest, res: NextApiResponse) => {
  const { email } = req.body;

  const user = process.env.GOOGLE_EMAIL;
  const pass = process.env.GOOGLE_APP_PASSWORD;

  // 先校验凭据是否存在
  if (!user || !pass) {
    return res.status(500).json({ error: '缺少邮箱认证凭据' });
  }

  try {
    const transporter = nodemailer.createTransport({
      host: 'smtp.gmail.com',
      port: 465,
      secure: true,
      auth: {
        user,
        pass,
      },
    });

    const mailOptions = {
      from: `YourTable <${user}>`,
      to: email,
      subject: 'Hello from gmail using API',
      text: 'Hello from gmail email using API',
      html: '<h1>Hello from gmail email using API</h1>',
    };

    await transporter.sendMail(mailOptions);
    res.status(200).json({ email });
  } catch (error) {
    console.error(error);
    res.status(500).json({ error: '无法发送验证邮件' });
  }
};

export default handleSendVerificationEmail;

关键注意事项

  • 修改.env.local后必须重启Next.js开发服务器,否则新的环境变量不会生效。
  • OAuth2方式需要在谷歌云控制台正确配置OAuth consent screen,并将你的邮箱添加为测试用户(未发布的OAuth应用仅支持测试用户)。
  • 应用密码生成后妥善保存,不要泄露到代码仓库或公开环境中。

内容的提问来源于stack exchange,提问作者Jakob Basshunter Widmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:31:04