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

.NET Core读取Office 365邮件遇认证失败,请求排查

排查.NET Core Azure部署下Office 365 IMAP认证失败问题

问题背景

在.NET Core环境中开发读取关联Azure账户的Office 365邮件功能,部署到Azure后执行代码时出现Authentication Failed错误。当前API权限配置及核心代码如下:

API权限配置

  • Microsoft Graph:User.Read(Delegated), IMAP.AccessAsUser.All(Delegated)
  • Office 365 Exchange Online:IMAP.AccessAsApp(Application)

核心代码

public async Task<List<ReceivedEMails>> ReadEmailsAsync()
{
    var emailMessages = new List<ReceivedEMails>();

    try
    {
        // OAuth2 configuration
        var clientId = _configuration["EmailSettings:ClientId"];
        var tenantId = _configuration["EmailSettings:TenantId"];
        var clientSecret = _configuration["EmailSettings:ClientSecret"];
        var userEmail = _configuration["EmailSettings:EmailAddress"];
        var scope = new string[] { "https://outlook.office.com/.default" };

        // Get Access Token
        var cca = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithClientSecret(clientSecret)
            .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}/v2.0"))
            .Build();

        var result = await cca.AcquireTokenForClient(scope).ExecuteAsync();

        // Connect to IMAP server
        using (var client = new MailKit.Net.Imap.ImapClient())
        {
            await client.ConnectAsync("outlook.office365.com", 993, true);
            await client.AuthenticateAsync(new SaslMechanismOAuth2(userEmail, result.AccessToken)); //error:authentication failed.

            // Select inbox
            await client.Inbox.OpenAsync(FolderAccess.ReadOnly);

            var items = await client.Inbox.FetchAsync(0, -1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId);

            foreach (var item in items)
            {
                var email = client.Inbox.GetMessage(item.UniqueId);

                emailMessages.Add(new ReceivedEMails
                {
                    EmailCode = email.MessageId,
                    EmailSubject = email.Subject,
                    EmailSender = email.From.Mailboxes.FirstOrDefault()?.Address,
                    EmailContent = email.TextBody,
                    CreatedDate = email.Date.DateTime
                });
            }

            await client.DisconnectAsync(true);
        }
    }
    catch (Exception ex)
    {
        throw new InvalidOperationException("Failed to read emails.", ex);
    }

    return emailMessages;
}

问题排查与修复方案

1. 权限配置冲突与缺失

你使用的是客户端凭证流(Client Credentials Flow),属于应用权限模式,但当前权限配置存在问题:

  • IMAP.AccessAsUser.All是委托权限,仅适用于用户交互的认证流(如Authorization Code Flow),无法在客户端凭证流中生效,可移除该权限。
  • IMAP.AccessAsApp(应用权限)必须完成两个关键步骤:
    • 由全局管理员对该权限授予管理员同意(应用权限无法通过用户同意生效)。
    • 在Exchange Online PowerShell中为目标邮箱配置应用访问策略,允许你的应用访问该邮箱:
      New-ApplicationAccessPolicy -AppId <你的客户端ID> -PolicyScopeGroupId <目标邮箱地址> -AccessRight RestrictAccess -Description "允许应用访问指定邮箱"
      

2. 令牌请求Scope错误

客户端凭证流中,请求IMAP应用权限时,应明确指定Scope为https://outlook.office365.com/IMAP.AccessAsApp,而非https://outlook.office.com/.default(虽然.default包含权限,但明确指定可避免受众不匹配问题)。修改代码中的Scope定义:

var scope = new string[] { "https://outlook.office365.com/IMAP.AccessAsApp" };

3. 认证参数与令牌有效性检查

  • 确认传入SaslMechanismOAuth2的userEmail是目标邮箱的完整地址,且已被上述应用访问策略授权。
  • 解码获取到的令牌(可使用本地工具或在线解析器),检查**受众(aud)**是否为https://outlook.office365.com,若受众错误,说明Scope配置仍有问题。

4. Azure部署环境验证

  • 确认Azure应用注册的客户端密钥未过期,且代码中配置的clientSecret与实际密钥一致。
  • 检查Azure App Service(或其他部署服务)的环境变量EmailSettings各项值是否正确,避免配置缺失或拼写错误。

5. 简化方案:改用Microsoft Graph API

若IMAP的OAuth2配置过于繁琐,可直接使用Microsoft Graph API读取邮件:

  1. 在应用注册中添加Microsoft Graph的Mail.Read(Application)权限并授予管理员同意。
  2. 修改代码为Graph API调用:
public async Task<List<ReceivedEMails>> ReadEmailsAsync()
{
    var emailMessages = new List<ReceivedEMails>();
    try
    {
        var clientId = _configuration["EmailSettings:ClientId"];
        var tenantId = _configuration["EmailSettings:TenantId"];
        var clientSecret = _configuration["EmailSettings:ClientSecret"];
        var userEmail = _configuration["EmailSettings:EmailAddress"];

        var cca = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithClientSecret(clientSecret)
            .WithAuthority(new Uri($"https://login.microsoftonline.com/{tenantId}/v2.0"))
            .Build();

        var result = await cca.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }).ExecuteAsync();

        var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
        {
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
        }));

        var messages = await graphClient.Users[userEmail].MailFolders.Inbox.Messages
            .Request()
            .Select(m => new { m.Id, m.Subject, m.From, m.Body, m.ReceivedDateTime })
            .GetAsync();

        foreach (var msg in messages)
        {
            emailMessages.Add(new ReceivedEMails
            {
                EmailCode = msg.Id,
                EmailSubject = msg.Subject,
                EmailSender = msg.From?.EmailAddress?.Address,
                EmailContent = msg.Body?.Content,
                CreatedDate = msg.ReceivedDateTime?.DateTime ?? DateTime.MinValue
            });
        }
    }
    catch (Exception ex)
    {
        throw new InvalidOperationException("Failed to read emails.", ex);
    }
    return emailMessages;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 16:00:56