使用Microsoft Graph SDK在类库中获取已发送邮件遇权限异常求助
解决Microsoft Graph SDK获取已发送邮件的两种方案
方案一:修复Integrated Windows Auth的MsalUiRequiredException异常
你遇到的MsalUiRequiredException主要由权限不足、IWA运行条件不满足或同步调用死锁导致,按以下步骤修复:
补充必要权限
当前代码仅请求User.Read范围,获取已发送邮件需要Mail.Read或Mail.ReadWrite委托权限。- 登录Azure AD应用注册,在「API权限」中添加
Microsoft Graph的Mail.Read(委托权限),并点击「授予管理员同意」(租户级应用需此操作)。 - 修改scopes为:
var scopes = new[] { "Mail.Read" };
- 登录Azure AD应用注册,在「API权限」中添加
满足IWA运行条件
Integrated Windows Auth仅适用于:- 加入域的Windows机器
- 运行代码的用户是Azure AD或AD同步的域用户
- 应用注册中已启用「Integrated Windows Authentication」(在「身份验证」→「高级设置」中开启)
避免同步调用死锁
不要用.Result同步等待异步方法,改用异步调用:var sentEmails = await graphClient.Users[authMail].MailFolders.SentItems.Request().GetAsync();若必须同步,可添加
.ConfigureAwait(false)规避死锁:var sentEmails = graphClient.Users[authMail].MailFolders.SentItems.Request().GetAsync().ConfigureAwait(false).GetAwaiter().GetResult();
方案二:客户端凭据模式正确调用Graph SDK
你已能获取客户端凭据令牌,但需注意应用权限配置和SDK使用方式:
配置应用权限
客户端凭据模式使用应用权限,而非委托权限:- 在Azure AD应用注册中添加
Microsoft Graph的Mail.Read.Application(应用权限),并点击「授予管理员同意」。 - 若需访问特定用户邮箱,需在Exchange Online中运行PowerShell命令分配权限:
New-ApplicationAccessPolicy -AppId <你的客户端ID> -PolicyScopeGroupId <目标用户邮箱> -AccessRight AllowAccess -Description "允许应用访问指定邮箱"
- 在Azure AD应用注册中添加
用MSAL构建Graph客户端
推荐使用ClientCredentialProvider(需安装Microsoft.Graph.AuthNuGet包),替代DelegateAuthenticationProvider:private static GraphServiceClient CreateClientWithAppCredentials() { var tenantId = "xxx"; var clientId = "xxxx"; var clientSecret = "xxxxx"; var credentialProvider = new ClientCredentialProvider( new ClientCredential(clientId, clientSecret), new[] { "https://graph.microsoft.com/.default" }, tenantId, "https://login.microsoftonline.com/" ); return new GraphServiceClient(credentialProvider); }正确调用API
使用构建好的客户端调用已发送邮件接口:var graphClient = CreateClientWithAppCredentials(); var sentEmails = await graphClient.Users[authMail].MailFolders.SentItems.Messages.Request().GetAsync();
额外注意
- 客户端凭据模式的令牌代表应用身份,而非用户身份,必须使用
https://graph.microsoft.com/.default作为权限范围。 - 避免混用ADAL(旧版认证库)和MSAL(新版),推荐用MSAL获取令牌:
private static async Task<string> GetGraphTokenWithMsal() { var tenantId = "xxx"; var clientId = "xxxx"; var clientSecret = "xxxxx"; var cca = ConfidentialClientApplicationBuilder .Create(clientId) .WithTenantId(tenantId) .WithClientSecret(clientSecret) .Build(); var result = await cca.AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" }).ExecuteAsync(); return result.AccessToken; }
内容的提问来源于stack exchange,提问作者Diego Perez
相关产品推荐
相关产品推荐

