简体   繁体   中英

Office365 EWS API The Autodiscover service couldn't be located

I have written a .Net c# console app to extract emails from an Office365 mailbox with specific credentials. This app works perfectly on my development PC. I now need to deploy this onto a Windows server (2019) and run via a job scheduler. However on the server it does not work and I get a "The Autodiscover service couldn't be located." error. Please see my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Exchange.WebServices.Data;
using System.Configuration;
using System.Globalization;
using System.IO;

namespace DWMailProcessor
{
    class Program
    {
        static void Main(string[] args)
        {
            string emailName = ConfigurationManager.AppSettings["emailName"];
            string emailPassWord = ConfigurationManager.AppSettings["emailPassWord"];
            string filterSubject = ConfigurationManager.AppSettings["filterSubject"];
            string extractFilePath = ConfigurationManager.AppSettings["extractFilePath"];
            string emailFolder = ConfigurationManager.AppSettings["emailFolder"];
            string logFilePath = ConfigurationManager.AppSettings["logFilePath"] + $@"\DWMailProcessor.ErrorLog"; ;

            try
            {
                ExchangeService exchange = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
                exchange.Credentials = new WebCredentials(emailName, emailPassWord);
                exchange.AutodiscoverUrl(emailName, RedirectionUrlValidationCallback);

                if (exchange != null)
                {
                    Folder rootFolder = Folder.Bind(exchange, WellKnownFolderName.MsgFolderRoot);
                    SearchFilter ff = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, emailFolder);
                    FindFoldersResults fresult = rootFolder.FindFolders(ff, new FolderView(1));

                    FindItemsResults<Item> result;
                    do
                    {
                        SearchFilter sf = new SearchFilter.IsEqualTo(EmailMessageSchema.Subject, filterSubject);
                        result = exchange.FindItems(WellKnownFolderName.Inbox, sf, new ItemView(100));

                        foreach (Item item in result)
                        {
                            EmailMessage message = EmailMessage.Bind(exchange, item.Id);
                            FileAttachment attachment = (FileAttachment)message.Attachments[0];
                            attachment.Load(extractFilePath + @"\" + attachment.Name);
                            item.Move(fresult.Folders[0].Id);
                        }
                    } while (result.TotalCount > 0);
                }
            }
            catch (Exception e)
            {
                using (StreamWriter sw = new StreamWriter(logFilePath, append: true))
                {
                    sw.WriteLine($"Fatal[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InstalledUICulture)}]: {e.Message}");
                }
                //throw;
                return;
            }
        }

        private static bool RedirectionUrlValidationCallback(string redirectionUrl)
        {
            // The default for the validation callback is to reject the URL.
            bool result = false;
            Uri redirectionUri = new Uri(redirectionUrl);
            // Validate the contents of the redirection URL. In this simple validation
            // callback, the redirection URL is considered valid if it is using HTTPS
            // to encrypt the authentication credentials. 
            if (redirectionUri.Scheme == "https")
            {
                result = true;
            }
            return result;
        }
    }
}

Note: the credentials are all fetched from the App.Config file I have only limited rights on the server and our IT does not have much of a clue about how to troubleshoot this issue. Could this be a firewall issue ? as the server is pretty restricted to the internet. ie (only specific url's and ports are open. And IT have said they opened https://outlook.office365.com/EWS/Exchange.asmx ) What firewall rules (if any) need to be in place to use the EWS API ? Are there any other way to troubleshoot this from the server ?

Many thanks in advance.

For Autodiscover the URL it will use will be autodiscover-s.outlook.com. The outlook.office365.com is the EWS endpoint which is basically what the Autodiscover code will always return for Office365 as this is a static endpoint. If your using Office365 then you could consider the Autodiscover redundant as it will only ever return https://outlook.office365.com/EWS/Exchange.asmx so I would suggest you try the following to hard code the URL.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Exchange.WebServices.Data;
using System.Configuration;
using System.Globalization;
using System.IO;

namespace DWMailProcessor
{
    class Program
    {
        static void Main(string[] args)
        {
            string emailName = ConfigurationManager.AppSettings["emailName"];
            string emailPassWord = ConfigurationManager.AppSettings["emailPassWord"];
            string filterSubject = ConfigurationManager.AppSettings["filterSubject"];
            string extractFilePath = ConfigurationManager.AppSettings["extractFilePath"];
            string emailFolder = ConfigurationManager.AppSettings["emailFolder"];
            string logFilePath = ConfigurationManager.AppSettings["logFilePath"] + $@"\DWMailProcessor.ErrorLog"; ;

            try
            {
                ExchangeService exchange = new ExchangeService(ExchangeVersion.Exchange2016);
                exchange.Credentials = new WebCredentials(emailName, emailPassWord);
                exchange.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
                exchange.HttpHeaders.Add("X-AnchorMailbox", emailName);

                if (exchange != null)
                {
                    Folder rootFolder = Folder.Bind(exchange, WellKnownFolderName.MsgFolderRoot);
                    SearchFilter ff = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, emailFolder);
                    FindFoldersResults fresult = rootFolder.FindFolders(ff, new FolderView(1));

                    FindItemsResults<Item> result;
                    do
                    {
                        SearchFilter sf = new SearchFilter.IsEqualTo(EmailMessageSchema.Subject, filterSubject);
                        result = exchange.FindItems(WellKnownFolderName.Inbox, sf, new ItemView(100));

                        foreach (Item item in result)
                        {
                            EmailMessage message = EmailMessage.Bind(exchange, item.Id);
                            FileAttachment attachment = (FileAttachment)message.Attachments[0];
                            attachment.Load(extractFilePath + @"\" + attachment.Name);
                            item.Move(fresult.Folders[0].Id);
                        }
                    } while (result.TotalCount > 0);
                }
            }
            catch (Exception e)
            {
                using (StreamWriter sw = new StreamWriter(logFilePath, append: true))
                {
                    sw.WriteLine($"Fatal[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InstalledUICulture)}]: {e.Message}");
                }
                //throw;
                return;
            }
        }

    }
}

One other issue with your code is the its using Basic authentication which is going way in October https://support.microsoft.com/en-au/help/4521831/exchange-online-deprecating-basic-auth so consider using oAuth instead.

Probably the last thing just looking at the code your using is that this could all be done in the Microsoft Graph API (PowerAutomate probably as well) which will let you reduce the number of permissions your app needs, give you more flexibility in how/where you run it and give whatever process your working on a extended life (in the Case EWS is switched off at any point in the future).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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