Microsoft.Exchange.WebServices 2.2.1.0生成令牌后调用接口报403错误
问题描述
开发环境
- Visual Studio 2022,.NET版本4.8
- Microsoft.Exchange.WebServices版本2.2.1.0
- Microsoft.Exchange.WebServices.Auth版本15.0.0.0
- Microsoft.Identity.Client版本4.63.0.0
Azure权限配置

问题详情
代码已成功生成令牌,但执行以下代码行时抛出403禁止错误:
var folders = _service.FindFolders(WellKnownFolderName.Inbox, new FolderView(10));
错误信息:
Microsoft.Exchange.WebServices.Data.ServiceRequestException: 'The request failed. The remote server returned an error: (403) Forbidden.'
完整代码
private static void ReadMailsFromExchangeServer() { // _service.Credentials = new WebCredentials("test@test.com", "qwerty", "tng"); try { string token = GetAccessToken(); ExchangeService _service = new ExchangeService(ExchangeVersion.Exchange2016) { Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"), Credentials = new OAuthCredentials(token), }; // Use your EWS endpoint // Impersonate the user you want to act on behalf of _service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test@test.com"); // Set X-AnchorMailbox header to the SMTP address of the mailbox being accessed _service.HttpHeaders.Add("X-AnchorMailbox", "test@test.com");//test@test.com _service.HttpHeaders.Add("X-PreferServerAffinity", "true"); var folders = _service.FindFolders(WellKnownFolderName.Inbox, new FolderView(10)); foreach (var folder in folders) { Console.WriteLine(folder.DisplayName); } } catch (Exception ex) { } } private static async void GetTokens() { // Using Microsoft.Identity.Client 4.22.0 var cca = ConfidentialClientApplicationBuilder .Create(ConfigurationManager.AppSettings["appId"]) .WithClientSecret(ConfigurationManager.AppSettings["clientSecret"]) .WithTenantId(ConfigurationManager.AppSettings["tenantId"]) .Build(); var ewsScopes = new string[] { "https://outlook.office365.com/.default" }; try { var authResult = await cca.AcquireTokenForClient(ewsScopes) .ExecuteAsync(); var ewsClient = new ExchangeService(); ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"); ewsClient.Credentials = new OAuthCredentials(authResult.AccessToken); ewsClient.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "test@test.com"); //Include x-anchormailbox header ewsClient.HttpHeaders.Add("X-AnchorMailbox", "test@test.com"); } catch (Exception ex) { } }
排查与解决建议
权限配置检查
- 确认Azure应用已添加
Exchange.ManageAsApp应用权限,并完成管理员同意。从权限配置图核对该权限是否存在,若缺失需补充后重新获取令牌。 - 验证目标邮箱
test@test.com的EWS访问是否启用:通过Exchange管理中心或PowerShell命令Get-CASMailbox test@test.com | Select-Object EwsEnabled查看,若结果为False,执行Set-CASMailbox test@test.com -EwsEnabled $true启用。
- 确认Azure应用已添加
代码异步逻辑修正
- 当前
GetTokens为async void,调用时无法等待令牌生成完成,导致ReadMailsFromExchangeServer可能拿到无效令牌。重构令牌获取方法为异步返回:
同时修改邮件读取方法为异步:private static async Task<string> GetAccessToken() { var cca = ConfidentialClientApplicationBuilder .Create(ConfigurationManager.AppSettings["appId"]) .WithClientSecret(ConfigurationManager.AppSettings["clientSecret"]) .WithTenantId(ConfigurationManager.AppSettings["tenantId"]) .Build(); var ewsScopes = new string[] { "https://outlook.office365.com/.default" }; var authResult = await cca.AcquireTokenForClient(ewsScopes).ExecuteAsync(); return authResult.AccessToken; }private static async Task ReadMailsFromExchangeServer() { try { string token = await GetAccessToken(); // 后续服务初始化、文件夹查询逻辑保持不变 } catch (Exception ex) { Console.WriteLine(ex.ToString()); // 不要吞异常,输出便于排查 } }
- 当前
令牌有效性验证
- 解码生成的JWT令牌,检查
roles声明中是否包含Exchange.ManageAsApp。若不存在,说明权限配置未生效,需重新配置权限并再次获取令牌。
- 解码生成的JWT令牌,检查
EWS版本适配
- Office 365环境建议使用
ExchangeVersion.ExchangeOnline(若当前EWS版本支持),替换代码中的ExchangeVersion.Exchange2016,避免版本不匹配引发的权限问题。
- Office 365环境建议使用
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

