使用Nodemailer+Office 365 OAuth2发邮件遇令牌创建错误求助
问题分析与解决步骤
出现Can't create new access token for user错误,大概率是OAuth2配置不完整、权限未正确配置或TLS参数错误导致的,以下是具体排查和修复方案:
1. 先修复TLS配置错误
你的代码中设置了tls: { ciphers: 'SSLv3' },但Office 365 SMTP服务已废弃SSLv3协议,这会直接导致TLS握手失败,间接影响令牌请求。必须删除这个配置项,使用Nodemailer默认的TLS cipher即可。
2. 完善OAuth2配置(分两种场景)
Office 365的SMTP OAuth2支持两种授权流,你需要根据自己的使用场景补充对应参数:
场景1:授权码流(针对单个用户邮箱)
适合需要用特定用户身份发送邮件的场景,需要用户完成授权流程获取刷新令牌:
const config: Options = { service: 'office365', // 配置service后可省略host/port/secure参数 requireTLS: true, auth: { type: 'OAuth2', user: this.configService.get<string>('mail.senderMail'), clientId: clientId, clientSecret: clientSecret, refreshToken: '你的刷新令牌', // 必须补充,Nodemailer会自动用它刷新access token scope: 'https://outlook.office365.com/SMTP.Send', // 对应SMTP发送权限 accessUrl: 'https://login.microsoftonline.com/2XXXXXXXXXXXXXX/oauth2/v2.0/token', }, };
前置要求:
- 在Azure AD注册应用时,添加Delegated权限:
SMTP.Send或Mail.Send - 完成授权码流程,获取有效的
refreshToken
场景2:客户端凭证流(应用级权限,无需用户授权)
适合服务端后台发送邮件的场景,需要管理员授予应用权限:
const config: Options = { service: 'office365', requireTLS: true, auth: { type: 'OAuth2', user: this.configService.get<string>('mail.senderMail'), // 发送邮件的邮箱地址 clientId: clientId, clientSecret: clientSecret, grant_type: 'client_credentials', // 必须指定客户端凭证流类型 scope: 'https://outlook.office365.com/.default', // 应用权限需使用.default scope accessUrl: 'https://login.microsoftonline.com/2XXXXXXXXXXXXXX/oauth2/v2.0/token', }, };
前置要求:
- 在Azure AD注册应用时,添加Application权限:
SMTP.Send或Mail.Send - 由租户管理员完成权限同意操作
3. 额外检查项
- 确认
accessUrl中的租户ID(2XXXXXXXXXXXXXX)正确,商业版Office 365必须使用租户ID,个人账号可替换为common - 检查Azure AD应用的重定向URI、权限范围是否与授权流程一致
- 确保
clientId和clientSecret没有拼写错误或过期
内容的提问来源于stack exchange,提问作者Yousi
相关产品推荐
相关产品推荐

