如何在没有交互式登录的情况下通过EWS访问具有受限权限的邮箱?

问题描述:

我们需要从专用交换/外观邮箱(O365)的联系人文件夹中读取通讯组列表.该过程必须作为服务运行,且无需用户干预.

We need to read out distribution lists from a contact folder of a dedicated exchange/outlook mailbox (O365). The process must run as a service with no user interaction.

不幸的是,Graph API不支持通讯组列表(甚至Graph beta版本也不支持).因此,我们必须使用另一个API-我尝试使用EWS.

Unfortunately the Graph API does not support distribution lists (not even the Graph beta version does). Because of this we have to use another API - I tried using EWS.

我成功授予了我们服务的full_access_as_app权限.但是,这允许读取和修改ANY邮箱中的ANY数据,这是安全隐患.仅授予此权限以从一个邮箱中读取某些通讯组列表是不可接受的.

I succeeded by granting full_access_as_app permission to our service. However this allows to read and modify ANY data in ANY mailbox which is a security risk. Granting this permission only to read out some distribution lists from one mailbox is not acceptable.

因此,我尝试使用ROPC流,该流应允许对用户进行身份验证,然后使用该用户的权限访问邮箱.我在这里关注了以下信息:

So I tried to use the ROPC flow that should allow authenticating a user and then accessing the mailbox with the permissions of this user. I followed the information here: How to get OAuth2 access token for EWS managed API in service/daemon application

(顺便说一句,我发现此帖子已链接到此处的讨论中: https://github.com/microsoftgraph/microsoft-graph-docs/issues/5659 ,其中包含有关该主题的更多信息.)

(Btw I found this post linked in the discussion here: https://github.com/microsoftgraph/microsoft-graph-docs/issues/5659 which has some more information about the topic.)

我完全按照上面提到的步骤进行操作,但是不幸的是,这没有用:在进行EWS调用(OAuth调用成功)时,我总是收到"401未经授权"的异常,并且没有其他信息.

I exactly followed the steps mentioned above but unfortunately this is not working: I always get a "401 Unauthorized" exception when doing the EWS calls (OAuth calls succeed) and no additional information.

根据

According to https://developer.microsoft.com/en-us/graph/blogs/upcoming-changes-to-exchange-web-services-ews-api-for-office-365/ this is no longer working. So how can I read out distribution lists from a specific mailbox without giving full access and without an interactive login?

编辑 此处按要求提供完整代码:

EDIT Here as requested the full code:

string[] ewsScopes = { "https://outlook-tdf-2.office.com/EWS.AccessAsUser.All" };

IPublicClientApplication clientApplication = PublicClientApplicationBuilder.Create(appId).WithAuthority(AzureCloudInstance.AzurePublic, tenantId).Build();
NetworkCredential credentials = new NetworkCredential(appUsername, appPassword);

AuthenticationResult authResult = await clientApplication.AcquireTokenByUsernamePassword(ewsScopes, credentials.UserName, credentials.SecurePassword).ExecuteAsync().ConfigureAwait(false);

ExchangeService exchangeService = new ExchangeService
{
    Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
    Credentials = new OAuthCredentials(authResult.AccessToken),
};

ItemView view = new ItemView(int.MaxValue)
{
    PropertySet = new PropertySet(ItemSchema.Id),
};
SearchFilter.IsEqualTo filter = new SearchFilter.IsEqualTo(ItemSchema.ItemClass, "IPM.Contact");

FindItemsResults<Item> ewsResult = await exchangeService.FindItems(WellKnownFolderName.Contacts, filter, view).ConfigureAwait(false);

我还尝试了其他范围,例如"https://outlook.office.com/EWS.AccessAsUser.All"或"https://outlook.office365.com/EWS.AccessAsUser.All"但没有成功.我觉得问题可能与范围有关?我可以看到添加权限时Azure UI中列出的Exchange旧版API现在已经消失了...?

I have also tried with other scopes such as "https://outlook.office.com/EWS.AccessAsUser.All" or "https://outlook.office365.com/EWS.AccessAsUser.All" but without success. I feel the problem might be related to the scope? I can see that the Exchange legacy API that was listed in the Azure UI when adding permissions is now gone...?

昨天11月19日,Microsoft更新了文档:

Yesterday Nov 19th Microsoft has updated the documentation: https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth

遵循新的文档,它再次起作用.主要区别在于使用缩短的范围"EWS.AccessAsUser.All".而不是在许多示例和帖子中找到的所有完整范围,例如"https://outlook.office.com/EWS.AccessAsUser.All"、https://outlook.office365.com/EWS.AccessAsUser.All"等

Following the new documentation it works (again). The main difference is to use the shortened scope "EWS.AccessAsUser.All" and not any of the full scopes found in many examples and posts such as "https://outlook.office.com/EWS.AccessAsUser.All", "https://outlook.office365.com/EWS.AccessAsUser.All" etc.

感谢MS浪费我的时间.

Thank you MS for wasting my time.