简体   繁体   English

Microsoft.Exchange.WebServices.Data.ServiceResponseException:“没有可用的公用文件夹服务器。”

[英]Microsoft.Exchange.WebServices.Data.ServiceResponseException: 'There are no public folder servers available.'

further to this question , i have the same problem.除了这个问题,我也有同样的问题。 PubFolder on Prem, users in O365 Prem 上的 PubFolder,O365 中的用户

I have fetched and added the routing headers from Glen's post but still get the error我已经从 Glen 的帖子中获取并添加了路由标头,但仍然出现错误

GetToken works... https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth GetToken 有效... https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth

GetX headers works... https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/public-folder-access-with-ews-in-exchange GetX 标头有效... https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/public-folder-access-with-ews-in-exchange

--->> ewsClient.FindFolders(WellKnownFolderName.PublicFoldersRoot, new FolderView(10)) --->> ewsClient.FindFolders(WellKnownFolderName.PublicFoldersRoot, new FolderView(10))

Microsoft.Exchange.WebServices.Data.ServiceResponseException: 'There are no public folder servers available.' Microsoft.Exchange.WebServices.Data.ServiceResponseException:“没有可用的公用文件夹服务器。”

       static async System.Threading.Tasks.Task Test3()
{
    string ClientId = ConfigurationManager.AppSettings["appId"];
    string TenantId = ConfigurationManager.AppSettings["tenantId"];
    string secret = ConfigurationManager.AppSettings["clientSecret"];
    string uMbox = ConfigurationManager.AppSettings["userId"];
    string uPwd = ConfigurationManager.AppSettings["userPWD"];

// Using Microsoft.Identity.Client 4.22.0
//https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-authenticate-an-ews-application-by-using-oauth//
    var cca = ConfidentialClientApplicationBuilder
        .Create(ClientId)
        .WithClientSecret(secret)
        .WithTenantId(TenantId)
        .Build();

    var ewsScopes = new string[] { "https://outlook.office365.com/.default" };

    try
    {
        var authResult = await cca.AcquireTokenForClient(ewsScopes)
            .ExecuteAsync();

        // Configure the ExchangeService with the access token
        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, uMbox);


        AutodiscoverService autodiscoverService = GetAutodiscoverService(uMbox, uPwd);

        GetUserSettingsResponse userResponse = GetUserSettings(autodiscoverService, uMbox, 3, UserSettingName.PublicFolderInformation, UserSettingName.InternalRpcClientServer);
        string pfAnchorHeader= userResponse.Settings[UserSettingName.PublicFolderInformation].ToString();
        string pfMailboxHeader = userResponse.Settings[UserSettingName.InternalRpcClientServer].ToString(); ;

        // Make an EWS call
        var folders = ewsClient.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(10));
        foreach (var folder in folders)
        {
            Console.WriteLine($"Folder: {folder.DisplayName}");
        }

        //get Public folder root
        //Include x-anchormailbox header
        Console.WriteLine("X-AnchorMailbox value for public folder hierarchy requests: {0}", pfAnchorHeader);
        Console.WriteLine("X-PublicFolderMailbox value for public folder hierarchy requests: {0}", pfMailboxHeader);

        //var test3 = GetMailboxGuidAddress(ewsClient, pfAnchorHeader, pfMailboxHeader, uMbox);

        ///https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-route-public-folder-content-requests <summary>
        ewsClient.HttpHeaders.Add("X-AnchorMailbox", userResponse.Settings[UserSettingName.PublicFolderInformation].ToString());
        //ewsClient.HttpHeaders.Add("X-AnchorMailbox", "SharedPublicFolder@contoso.com");
        ewsClient.HttpHeaders.Add("X-PublicFolderMailbox", userResponse.Settings[UserSettingName.InternalRpcClientServer].ToString());

        try
        {
            var pubfolders = ewsClient.FindFolders(WellKnownFolderName.PublicFoldersRoot, new FolderView(10));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            throw;
        }
        
        foreach (var folder in folders)
        {
            Console.WriteLine($"Folder: {folder.DisplayName}");
        }

    }
    catch (MsalException ex)
    {
        Console.WriteLine($"Error acquiring access token: {ex}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error: {ex}");
    }

    if (System.Diagnostics.Debugger.IsAttached)
    {
        Console.WriteLine("Hit any key to exit...");
        Console.ReadKey();
    }
}

public static AutodiscoverService GetAutodiscoverService(string username, string pwd)
{
    AutodiscoverService adAutoDiscoverService = new AutodiscoverService();
    adAutoDiscoverService.Credentials = new WebCredentials(username, pwd);
    adAutoDiscoverService.EnableScpLookup = true;
    adAutoDiscoverService.RedirectionUrlValidationCallback = RedirectionUrlValidationCallback;
    adAutoDiscoverService.PreAuthenticate = true;
    adAutoDiscoverService.TraceEnabled = true;
    adAutoDiscoverService.KeepAlive = false;
    return adAutoDiscoverService;
}

public static GetUserSettingsResponse GetUserSettings(
         AutodiscoverService service,
         string emailAddress,
         int maxHops,
         params UserSettingName[] settings)
{
    Uri url = null;
    GetUserSettingsResponse response = null;

    for (int attempt = 0; attempt < maxHops; attempt++)
{
        service.Url = url;
        service.EnableScpLookup = (attempt < 2);

        response = service.GetUserSettings(emailAddress, settings);

        if (response.ErrorCode == AutodiscoverErrorCode.RedirectAddress)
        {
            url = new Uri(response.RedirectTarget);
        }
        else if (response.ErrorCode == AutodiscoverErrorCode.RedirectUrl)
        {
            url = new Uri(response.RedirectTarget);
        }
        else
        {
            return response;
        }
    }

    throw new Exception("No suitable Autodiscover endpoint was found.");
}
    

Your code won't work against an OnPrem Public folder tree as EWS in Office365 won't proxy to an OnPrem Exchange Org (even if hybrid is setup).您的代码不适用于 OnPrem 公共文件夹树,因为 Office365 中的 EWS 不会代理到 OnPrem Exchange Org(即使设置了混合)。 (Outlook MAPI is a little different and allows this via versa setup but in that case it never proxies either it just makes a different connection to that store and its all the Outlook client doing this). (Outlook MAPI 有点不同,它允许通过 versa 设置进行此操作,但在那种情况下,它从不代理,它只是与该商店建立不同的连接,所有 Outlook 客户端都这样做)。

Because your trying to use the client credentials oauth flow for that to work onPrem you must have setup hybrid modern authentication https://learn.microsoft.com/en-us/microsoft-365/enterprise/hybrid-modern-auth-overview?view=o365-worldwide .因为您尝试使用客户端凭据 oauth 流程才能在 Prem 上工作,所以您必须设置混合现代身份验证https://learn.microsoft.com/en-us/microsoft-365/enterprise/hybrid-modern-auth-overview?查看=o365-全球 Then you need to acquire a token with an audience set to the local OnPrem endpoint.然后,您需要获取一个将受众设置为本地 OnPrem 端点的令牌。 (this is usually just your onPrem ews endpoint's host name but it should be one of the service principal names configured in your hybrid auth setup Get-MsolServicePrincipal). (这通常只是您的 onPrem ews 端点的主机名,但它应该是在您的混合身份验证设置 Get-MsolServicePrincipal 中配置的服务主体名称之一)。 So in your code you would change所以在你的代码中你会改变

var ewsScopes = new string[] { "https://outlook.office365.com/.default" };

to

var ewsScopes = new string[] { "https://OnPrem.whatever.com/.default" }; var ewsScopes = new string[] { "https://OnPrem.whatever.com/.default" };

which will then give you a token with an audience set for the onprem server then you need to send the EWS request to that endpoint so change that eg然后将为您提供一个令牌,其中包含为 onprem 服务器设置的受众然后您需要将 EWS 请求发送到该端点,以便更改例如

ewsClient.Url = new Uri("https://OnPrem.whatever.com/EWS/Exchange.asmx"); ewsClient.Url = new Uri("https://OnPrem.whatever.com/EWS/Exchange.asmx");

if Hybird Modern Auth is setup then you need to default back to use Integrated or Basic Authenticaiton.如果设置了 Hybird Modern Auth,则需要默认返回使用 Integrated 或 Basic Authenticaiton。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM