我想从我的个人邮箱中检索一些电子邮件附件。
如果我使用可以从 Graph Explorer 复制的令牌,一切都会正常工作,即使它似乎已过期并且需要多次检索“刷新”的令牌。
var tokenProvider = new TokenProvider(access_token); // access_token from Microsoft Graph Explorer.
var authenticationProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider);
var graphServiceClient = new GraphServiceClient(authenticationProvider);
var user = graphServiceClient.Users[userId];
var messages = await user.Messages.GetAsync(); // Works fine.
尽管如此,当我从 C# 代码生成令牌时,我收到了 Service Unavailable 异常。
执行了太多次重试。发送请求时重试次数超过 3 次。 (HTTP 请求失败,状态代码:ServiceUnavailable)。
var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
using var httpClient = new HttpClient();
var requestBody = $"client_id={clientId}&client_secret={clientSecret}&redirect_uri=http://localhost&grant_type=client_credentials&scope=https://graph.microsoft.com/.default";
var request = new HttpRequestMessage(HttpMethod.Post, tokenEndpoint)
{
Content = new StringContent(requestBody, Encoding.UTF8, "application/x-www-form-urlencoded")
};
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<JObject>(responseContent);
var access_token = $"{data["access_token"]}";
var tokenProvider = new TokenProvider(access_token);
var authenticationProvider = new BaseBearerTokenAuthenticationProvider(tokenProvider);
var graphServiceClient = new GraphServiceClient(authenticationProvider);
var user = graphServiceClient.Users[userId];
var messages = await user.Messages.GetAsync(); // Service Unavailable.
我还通过 Postman 获得了一个明显有效的令牌,其中包含 200 状态代码。我也尝试更改 tenatId、clientId 等,但这会导致其他问题。
有人知道导致问题的原因吗?
如本MS Doc中所述,您需要使用委托权限,该权限适用于交互流或授权代码流等委托流。从个人帐户检索消息。
最初,我通过在“移动和桌面应用程序”平台中添加重定向URI注册了一个多租户Entra ID应用程序,如下所示:
现在,我在上面的应用程序注册中添加了
Mail.Read
权限,即委托类型:
要使用交互流进行身份验证,请确保启用公共客户端选项:
在我的例子中,我使用了下面的示例代码,该代码使用交互式流程进行身份验证,并通过使用个人帐户登录成功获得了响应:
using Azure.Identity;
using Microsoft.Graph;
using Microsoft.Graph.Models.ODataErrors;
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "common";
var clientId = "appId";
var options = new InteractiveBrowserCredentialOptions
{
TenantId = tenantId,
ClientId = clientId,
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud,
RedirectUri = new Uri("http://localhost"),
};
var interactiveCredential = new InteractiveBrowserCredential(options);
var graphClient = new GraphServiceClient(interactiveCredential, scopes);
try
{
var messages = await graphClient.Me.Messages.GetAsync(requestConfiguration =>
{
requestConfiguration.QueryParameters.Expand = new string[] { "attachments" };
});
foreach (var message in messages.Value)
{
Console.WriteLine($"Subject: {message.Subject}");
Console.WriteLine($"Message ID: {message.Id}");
if (message.Attachments.Any())
{
Console.WriteLine("Attachments:");
foreach (var attachment in message.Attachments)
{
Console.WriteLine($" Attachment Id: {attachment.Id}");
Console.WriteLine($" Attachment Name: {attachment.Name}");
}
}
else
{
Console.WriteLine("No attachments found.");
}
Console.WriteLine("-------------------------------------------");
}
}
catch (ODataError odataError)
{
Console.WriteLine(odataError.Error.Code);
Console.WriteLine(odataError.Error.Message);
}
回复:
参考: