【问题标题】:Using Microsoft Graph to fetch emails without any user interaction使用 Microsoft Graph 获取电子邮件,无需任何用户交互
【发布时间】:2018-11-03 05:25:19
【问题描述】:

我要做的就是获取用户 ID 的电子邮件,其他用户无需登录其 Microsoft 帐户即可访问该用户 ID。我查看了许多 SO 帖子 (this)、代码示例 (thisthis) 并查看了 OpenID 的 specs 和其他文档 (this),但仍然无法弄清楚.

我已在 azure 门户中注册应用并授予所需权限。使用sample app 我可以获取用户列表,但不能获取电子邮件列表。我比较了用户查询和电子邮件查询的请求标头。两者看起来都一样。有人可以告诉我我做错了什么吗?

代码如下:

Startup.Auth.cs

public static string clientId = "<CLIENT ID>";
public static string clientSecret = <CLIENT SECRET>;
private static string authority = "https://login.microsoftonline.com/common/v2.0";
public static string redirectUri = "https://localhost:44316/";

private void ConfigureAuth(IAppBuilder app)
{
   app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

   app.UseCookieAuthentication(new CookieAuthenticationOptions());

   app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
   {
       ClientId = clientId,
       Authority = authority,
       RedirectUri = redirectUri,
       PostLogoutRedirectUri = redirectUri,
       //Scope = "openid profile offline_access Mail.Read",
       Scope = "email profile openid offline_access User.Read Mail.Read",
       //ResponseType = "id_token",
       ResponseType = "code id_token",
       TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, NameClaimType = "name" },
       Notifications = new OpenIdConnectAuthenticationNotifications
       {
          AuthenticationFailed = this.OnAuthenticationFailedAsync,
          SecurityTokenValidated = this.OnSecurityTokenValidatedAsync
        }
    });
}

SyncController.cs

private const string AuthorityFormat = "https://login.microsoftonline.com/{0}/v2.0";
private const string MSGraphScope = "https://graph.microsoft.com/.default";
//private const string MSGraphQuery = "https://graph.microsoft.com/v1.0/users";
//private const string MSGraphQuery = "https://graph.microsoft.com/v1.0/me";
private const string MSGraphQuery = "https://graph.microsoft.com/v1.0/me/messages";

public async Task GetAsync(string tenantId)
{
    MSALCache appTokenCache = new MSALCache(Startup.clientId);

    // Get a token for the Microsoft Graph. If this line throws an exception for
    // any reason, we'll just let the exception be returned as a 500 response
    // to the caller, and show a generic error message to the user.
    ConfidentialClientApplication daemonClient = new ConfidentialClientApplication(Startup.clientId, string.Format(AuthorityFormat, tenantId), Startup.redirectUri,
                                                                                   new ClientCredential(Startup.clientSecret), null, appTokenCache.GetMsalCacheInstance());
    AuthenticationResult authResult = await daemonClient.AcquireTokenForClientAsync(new[] { MSGraphScope });

    HttpClient client = new HttpClient();

    // Uses SendAsync
    /*HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, MSGraphQuery);
    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
    //request.Headers.Add("client-request-id", System.Guid.NewGuid().ToString());
    //request.Headers.Add("return-client-request-id", "true");
    HttpResponseMessage response = await client.SendAsync(request);*/

    // Uses GetAsync
    client.BaseAddress = new System.Uri(MSGraphQuery);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + authResult.AccessToken);
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    HttpResponseMessage response = await client.GetAsync(MSGraphQuery);
}

编辑 1: 以下是用户列表(有效)和电子邮件列表(无效)的请求和响应值:

Request body to fetch user list (working):

{Method: GET, RequestUri: 'https://graph.microsoft.com/v1.0/users', Version: 1.1, Content: <null>, Headers:
{
  Accept: application/json
  Authorization: Bearer eyJ0eXAiOiJKV...
}}


Response when fetching user list (working):

{StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Transfer-Encoding: chunked
  request-id: 02034f96-f519-4f5f-b47d-efb98dff0072
  client-request-id: 02034f96-f519-4f5f-b47d-efb98dff0072
  x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"South India","Slice":"SliceC","Ring":"5","ScaleUnit":"002","Host":"AGSFE_IN_8","ADSiteName":"INS"}}
  OData-Version: 4.0
  Duration: 76.0712
  Strict-Transport-Security: max-age=31536000
  Cache-Control: private
  Date: Fri, 02 Nov 2018 12:36:51 GMT
  Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; IEEE754Compatible=false; charset=utf-8
}}


Request body to fetch emails (not working):

{Method: GET, RequestUri: 'https://graph.microsoft.com/v1.0/me/mailFolders('Inbox')/messages', Version: 1.1, Content: <null>, Headers:
{
  Accept: application/json
  Authorization: Bearer eyJ0eXAiOiJKV...
}}    

Response when fetching list of emails (not working):

{StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Transfer-Encoding: chunked
  request-id: 5b728866-b132-404f-9986-70fc56e57c3c
  client-request-id: 5b728866-b132-404f-9986-70fc56e57c3c
  x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"South India","Slice":"SliceC","Ring":"5","ScaleUnit":"002","Host":"AGSFE_IN_6","ADSiteName":"INS"}}
  Duration: 4205.8126
  Strict-Transport-Security: max-age=31536000
  Cache-Control: private
  Date: Fri, 02 Nov 2018 12:43:03 GMT
  Content-Type: application/json
}}

【问题讨论】:

  • 您是否尝试过,让用户获取其用户 ID(.id 属性),然后使用以下图形查询? $"graph.microsoft.com/v1.0/users{id}/messages"
  • 另外,如果您遇到错误,您能告诉我们它是什么吗? (我不清楚您是否收到错误,或者您不知道使用哪个 URL 来实现您的目标)
  • @Jean-MarcPrieur - 用户的 ID 是什么?是objectID还是userName?此外,我得到的错误是查询“graph.microsoft.com/v1.0/me/messages”的“错误请求”
  • 当你得到用户列表时,这是返回的 json 中名为 id 的属性(这是一个 guid)。它可能是某些 SDK 中的 objectId。响应的主体是什么? (有关为什么这是一个错误请求的详细信息)。我假设您在 graph.microsoft.com 前面有 https:// :)
  • 由于您使用的是客户端凭据,因此您不能使用“我”,因为您不是代表用户调用图表,而是代表应用程序。您应该能够使用 /users/id: like https://graph.microsoft.com/v1.0/users/48d31887-5fad-4d73-a9f5-3c356e68a038/mailFolders/Inbox/messages 其中 guid 是您要查看邮件的用户的 ID

标签: c# microsoft-graph-api outlook-restapi


【解决方案1】:

您正在使用 Client_Credentials 对应用进行身份验证并且在您的 REST 调用中使用 /me 路径。这两个不能一起工作。

在幕后/me 被转换为当前已通过身份验证的用户(即/users/user@domain。由于您没有经过身份验证的用户,它只是' Graph 不可能将您的请求转化为可操作的调用。

您需要使用他们的id or their userPrincipalName 明确引用用户:

 /v1.0/users/123e4567-e89b-12d3-a456-426655440000/mailFolders('Inbox')/messages
 /v1.0/users/user@yourdomain.com/mailFolders('Inbox')/messages

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    相关资源
    最近更新 更多