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

使用ConfidentialClientApplicationBuilder获取SMTP令牌及认证问题求助

问题:使用ConfidentialClientApplication获取令牌后SMTP认证失败

问题背景

  • 初始使用https://outlook.office365.com/SMTP.Send作为scope时,触发错误:Microsoft.Identity.Client.MsalServiceException: 'AADSTS1002012: The provided value for scope https://outlook.office365.com/SMTP.Send is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI)'
  • 将scope改为https://outlook.office365.com/.default后成功获取令牌,但出现两个新问题:
    1. result.Account为null,直接调用会抛出空引用异常
    2. 手动填写用户名后,触发MailKit.Security.AuthenticationException: '535: 5.7.3 Authentication unsuccessful'

相关代码片段

令牌获取代码

var pca = ConfidentialClientApplicationBuilder
                     .Create(ClientId)
                     .WithClientSecret(clientSecret)
                     .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
                     .WithRedirectUri(RedirectUrl)
                     .Build();

var outlookScope = new string[] { "https://outlook.office365.com/SMTP.Send" };

AuthenticationResult result = null;

try
{
    result = await pca.AcquireTokenForClient(outlookScope)
        .ExecuteAsync();
}
catch (MsalException ex)
{
    Console.WriteLine($"Error acquiring access token: {ex}");
}

SMTP认证代码

if (result != null)
{
    Console.WriteLine($"Access token: {result.AccessToken}");

    var message = new MimeMessage();
    message.From.Add(new MailboxAddress("Sender Name", "sender@example.com"));
    message.To.Add(new MailboxAddress("Recipient Name", "recipient@example.com"));
    message.Subject = "Test Email";
    message.Body = new TextPart("plain")
    {
        Text = "This is a test email sent using MailKit and Microsoft.Identity.Client."
    };

    using (var emailClient = new SmtpClient())
    {
        var oauth2 = new SaslMechanismOAuth2(result.Account.Username, result.AccessToken);
        await emailClient.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
        await emailClient.AuthenticateAsync(oauth2);
        await emailClient.SendAsync(message);
        await emailClient.DisconnectAsync(true);
    }
}

解决方案

1. 理解客户端凭证流的特性

AcquireTokenForClient属于应用级认证流,并非用户级认证,因此result.Account必然为null——该流不关联具体用户账号,必须手动指定发件人邮箱作为SMTP认证的用户名。

2. 修复SMTP认证失败的核心配置

出现535错误的根源是Azure AD权限配置缺失,需完成以下步骤:

步骤1:配置Azure AD应用权限

  • 进入Azure Portal → 目标应用注册 → API权限
  • 添加权限 → 选择Office 365 Exchange Online → 应用权限
  • 勾选SMTP.Send权限,点击添加后,必须点击授予管理员同意(权限需管理员审批后才生效)

步骤2:修正令牌请求配置

  • 保留https://outlook.office365.com/.default作为scope(客户端凭证流仅支持此格式,会自动包含所有已授予的应用权限)
  • 移除WithRedirectUri配置(客户端凭证流不需要重定向URI)

步骤3:修正MailKit认证代码

  • 手动指定租户内的有效发件人邮箱作为OAuth2的用户名
  • 确保SMTP服务器地址、端口和加密方式正确

修正后的完整代码:

// 获取令牌
var pca = ConfidentialClientApplicationBuilder
    .Create(ClientId)
    .WithClientSecret(clientSecret)
    .WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
    .Build();

var outlookScope = new string[] { "https://outlook.office365.com/.default" };
AuthenticationResult result = null;

try
{
    result = await pca.AcquireTokenForClient(outlookScope)
        .ExecuteAsync();
}
catch (MsalException ex)
{
    Console.WriteLine($"获取令牌失败: {ex}");
}

// 发送邮件
if (result != null)
{
    var senderEmail = "sender@example.com"; // 必须是当前租户内的有效邮箱
    var message = new MimeMessage();
    message.From.Add(new MailboxAddress("发送者", senderEmail));
    message.To.Add(new MailboxAddress("接收者", "recipient@example.com"));
    message.Subject = "测试邮件";
    message.Body = new TextPart("plain")
    {
        Text = "这是使用MailKit和MSAL发送的测试邮件。"
    };

    using (var emailClient = new SmtpClient())
    {
        var oauth2 = new SaslMechanismOAuth2(senderEmail, result.AccessToken);
        await emailClient.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.StartTls);
        await emailClient.AuthenticateAsync(oauth2);
        await emailClient.SendAsync(message);
        await emailClient.DisconnectAsync(true);
    }
}

3. 额外排查点

  • 确认发件人邮箱未被禁用,且属于当前Azure AD租户
  • 检查ClientSecret是否有效、未过期
  • 确保Azure AD应用的企业应用设置中,已启用对Exchange Online的访问

内容的提问来源于stack exchange,提问作者It's Siddiqi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:29:52