使用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;
方案二:确保应用密码的环境变量正确加载
- 在项目根目录创建
.env.local文件,写入正确凭据:
GOOGLE_EMAIL=你的谷歌邮箱账号@gmail.com GOOGLE_APP_PASSWORD=你的16位应用密码
注意:应用密码需要谷歌账号开启两步验证后才能生成,生成后直接复制16位字符串即可,无需保留空格。
- 修改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
相关产品推荐
相关产品推荐

