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

Node.js程序使用Outlook发件失败,求助切换至OAuth2认证方案

解决Node.js通过OAuth2认证发送Outlook邮件的步骤

一、在Azure AD注册应用

  • 登录Azure门户,进入Azure Active Directory → 应用注册 → 新注册
  • 填写应用名称,选择支持的账户类型:
    • 若使用个人Outlook邮箱,选「任何组织目录中的账户和个人Microsoft账户」
    • 若仅企业内部邮箱,选「此组织目录中的账户」
  • 设置重定向URI:无用户交互的后台服务选「公共客户端/本机(移动和桌面)」,填入https://login.microsoftonline.com/common/oauth2/nativeclient;Web应用填对应回调地址
  • 注册完成后,记录客户端ID(Client ID)和租户ID(Tenant ID)(个人邮箱场景用common作为租户ID)

二、配置应用权限

  • 在已注册的应用中,进入API权限 → 添加权限
  • 选择Microsoft Graph,根据场景选权限类型:
    • 后台服务(无用户交互):选「应用权限」,勾选Mail.Send,点击「添加权限」后,点击「授予管理员同意」(需企业管理员操作)
    • 有用户交互场景:选「委托权限」,勾选Mail.Send,用户首次使用时手动授权即可
  • 确认权限已成功添加并生效

三、生成客户端凭证(仅应用权限场景需要)

  • 进入应用的证书和密码 → 客户端密码 → 新客户端密码
  • 填写描述和过期时间,点击「添加」,立即记录生成的客户端密码值(离开页面后无法再查看)

四、修改Node.js代码实现OAuth2认证发送邮件

推荐使用nodemailer结合@azure/msal-node获取令牌,以下是两种场景的示例:

场景1:后台服务(客户端凭证流,无用户)

const nodemailer = require('nodemailer');
const { ConfidentialClientApplication } = require('@azure/msal-node');

// Azure AD配置参数
const config = {
  auth: {
    clientId: '你的客户端ID',
    clientSecret: '你的客户端密码',
    authority: 'https://login.microsoftonline.com/你的租户ID(或common)'
  }
};

const cca = new ConfidentialClientApplication(config);

// 获取访问令牌
async function getAccessToken() {
  const tokenRequest = {
    scopes: ['https://graph.microsoft.com/.default']
  };
  const response = await cca.acquireTokenByClientCredential(tokenRequest);
  return response.accessToken;
}

// 发送邮件
async function sendEmail() {
  const accessToken = await getAccessToken();
  const transporter = nodemailer.createTransport({
    host: 'smtp.office365.com',
    port: 587,
    secure: false,
    auth: {
      type: 'OAuth2',
      user: '你的Outlook邮箱地址',
      clientId: config.auth.clientId,
      clientSecret: config.auth.clientSecret,
      tenantId: config.auth.authority.split('/').pop(),
      accessToken: accessToken
    }
  });

  const mailOptions = {
    from: '你的Outlook邮箱地址',
    to: '收件人邮箱地址',
    subject: '测试邮件(OAuth2)',
    text: '这是通过OAuth2认证发送的测试邮件'
  };

  try {
    await transporter.sendMail(mailOptions);
    console.log('邮件发送成功');
  } catch (error) {
    console.error('邮件发送失败:', error);
  }
}

sendEmail();

场景2:有用户交互(授权码流)

需先获取用户授权码,再交换令牌,适合桌面或Web应用:

const nodemailer = require('nodemailer');
const { PublicClientApplication } = require('@azure/msal-node');

const config = {
  auth: {
    clientId: '你的客户端ID',
    authority: 'https://login.microsoftonline.com/common'
  }
};

const pca = new PublicClientApplication(config);

// 生成授权URL(引导用户登录授权)
async function getAuthUrl() {
  const authCodeUrlParameters = {
    scopes: ['https://graph.microsoft.com/Mail.Send'],
    redirectUri: 'https://login.microsoftonline.com/common/oauth2/nativeclient'
  };
  const response = await pca.getAuthCodeUrl(authCodeUrlParameters);
  console.log('请访问此URL授权:', response);
  // 用户授权后会返回授权码,手动填入下方code变量
}

// 用授权码交换令牌并发送邮件
async function sendEmailWithAuthCode(code) {
  const tokenRequest = {
    code: code,
    scopes: ['https://graph.microsoft.com/Mail.Send'],
    redirectUri: 'https://login.microsoftonline.com/common/oauth2/nativeclient'
  };
  const response = await pca.acquireTokenByCode(tokenRequest);

  const transporter = nodemailer.createTransport({
    host: 'smtp.office365.com',
    port: 587,
    secure: false,
    auth: {
      type: 'OAuth2',
      user: '你的Outlook邮箱地址',
      clientId: config.auth.clientId,
      refreshToken: response.refreshToken,
      accessToken: response.accessToken
    }
  });

  const mailOptions = {
    from: '你的Outlook邮箱地址',
    to: '收件人邮箱地址',
    subject: '测试邮件(OAuth2授权码流)',
    text: '这是通过授权码流OAuth2认证发送的测试邮件'
  };

  try {
    await transporter.sendMail(mailOptions);
    console.log('邮件发送成功');
  } catch (error) {
    console.error('邮件发送失败:', error);
  }
}

// 先调用getAuthUrl获取授权URL,拿到code后调用sendEmailWithAuthCode
// getAuthUrl();
// sendEmailWithAuthCode('用户授权后得到的code');

五、常见注意事项

  • 确保应用权限已正确配置并授予同意,否则会出现令牌权限不足的错误
  • 客户端密码和令牌属于敏感信息,不要硬编码在代码中,建议用环境变量管理
  • 客户端凭证流适用于后台服务,无需用户干预;授权码流需要用户手动授权,适合有交互的场景
  • 令牌有过期时间,应用权限场景下可定期刷新,授权码流可用refreshToken自动刷新

内容的提问来源于stack exchange,提问作者Jerry HTGCN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 19:27:43