使用Nodemailer通过Gmail发件失败,求无需应用令牌的解决方案
问题描述
开发邮件客户端时,希望用户输入Google凭据后即可发送邮件,使用nodemailer实现时遇到认证失败,错误提示535-5.7.8 Username and Password not accepted,开启Gmail非安全应用访问权限也无效。
尝试的代码:
const nodemailer = require('nodemailer'); async function main() { let transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 587, secure: false, auth: { user: 'divine@gmail.com', pass: '******', }, }); let info = await transporter.sendMail({ from: '"Divine" <divine@gmail.com>', to: 'info@example.com', subject: 'Hello', text: 'Hello world?', html: '<b>Hello world?</b>', }); console.log('Message sent: %s', info.messageId); } main().catch(console.error);
收到的错误信息:
Node.js v18.12.1 PS C:\Users\divine\Programming\Node.js\EmailClient> node index Error: Invalid login: 535-5.7.8 Username and Password not accepted. Learn more at 535 5.7.8 https://support.google.com/mail/?p=BadCredentials l19-20020a170902f69300b00177efb56475sm24894649plg.85 - gsmtp at SMTPConnection._formatError (C:\Users\divine\Programming\Node.js\EmailClient\node_modules\nodemailer\lib\smtp-connection\index.js:790:19) at SMTPConnection._actionAUTHComplete (C:\Users\divine\Programming\Node.js\EmailClient\node_modules\nodemailer\lib\smtp-connection\index.js:1542:34) at SMTPConnection.<anonymous> (C:\Users\divine\Programming\Node.js\EmailClient\node_modules\nodemailer\lib\smtp-connection\index.js:546:26) at SMTPConnection._processResponse (C:\Users\divine\Programming\Node.js\EmailClient\node_modules\nodemailer\lib\smtp-connection\index.js:953:20) at SMTPConnection._onData (C:\Users\divine\Programming\Node.js\EmailClient\node_modules\nodemailer\lib\smtp-connection\index.js:755:14) at SMTPConnection._onSocketData (C:\Users\divine\Programming\Node.js\EmailClient\node_modules\nodemailer\lib\smtp-connection\index.js:193:44) at TLSSocket.emit (node:events:513:28) at addChunk (node:internal/streams/readable:324:12) at readableAddChunk (node:internal/streams/readable:297:9) at Readable.push (node:internal/streams/readable:234:10) { code: 'EAUTH', response: '535-5.7.8 Username and Password not accepted. Learn more at\n' + '535 5.7.8 https://support.google.com/mail/?p=BadCredentials l19-20020a170902f69300b00177efb56475sm24894649plg.85 - gsmtp', responseCode: 535, command: 'AUTH PLAIN' }
解决方案
方法1:使用应用专用密码(App Password)
Google已停用「非安全应用访问」功能,若你的Gmail账号开启了两步验证(2FA),可生成应用专用密码替代原账号密码:
- 登录Google账号安全设置页面
- 找到「应用专用密码」选项,选择「邮件」作为应用类型,自定义设备名称
- 生成16位密码,替换代码中
auth.pass字段的值即可
方法2:使用OAuth2认证(Google官方推荐)
这是当前Gmail SMTP认证的标准方案,步骤如下:
- 登录Google Cloud控制台,创建新项目并启用Gmail API
- 创建OAuth2客户端ID,设置授权回调地址(本地开发可设为
http://localhost:3000) - 引导用户完成OAuth授权流程,获取refresh_token
- 配置nodemailer使用OAuth2认证,示例代码:
const nodemailer = require('nodemailer'); const { google } = require('googleapis'); const OAuth2 = google.auth.OAuth2; const oauth2Client = new OAuth2( '你的客户端ID', '你的客户端密钥', 'http://localhost:3000' // 授权回调地址 ); oauth2Client.setCredentials({ refresh_token: '获取到的refresh_token' }); async function main() { const accessToken = await oauth2Client.getAccessToken(); let transporter = nodemailer.createTransport({ service: 'gmail', auth: { type: 'OAuth2', user: 'divine@gmail.com', clientId: '你的客户端ID', clientSecret: '你的客户端密钥', refreshToken: '获取到的refresh_token', accessToken: accessToken } }); let info = await transporter.sendMail({ from: '"Divine" <divine@gmail.com>', to: 'info@example.com', subject: 'Hello', text: 'Hello world?', html: '<b>Hello world?</b>', }); console.log('Message sent: %s', info.messageId); } main().catch(console.error);
refresh_token可长期使用,每次发送邮件时会自动刷新access_token。
方法3:Google Workspace账号专属配置(仅企业账号)
若使用的是Google Workspace(原G Suite)企业账号,管理员可在后台配置允许SMTP直接登录,无需额外令牌,但普通个人Gmail账号不支持此方式。
内容的提问来源于stack exchange,提问作者divinelemon
相关产品推荐
相关产品推荐

