Search code examples
serviceexchangewebservices

How to Handle WebServices.Data.ServiceRequestException?


I have a Windows Service that access a mailbox periodically to process new emails via EWS.

After having it up and running for several days, it hit the following error, causing the service to stop. (something like Exchange Service not available)

I am still investigating if the error is just be temporary as I am still in development environment that is shared with other teams who might be doing some implementation which caused this error.


Question: May I know if the best way to handle this is to use a try-catch, where the catch will run the GetNewEmail method again in my main program?


Below is my code snippet:

List<EmailMessage> emailList = GetNewEmail(category);

public static List<EmailMessage> GetNewEmail(string folderName)
{
    FindItemsResults<Item> emailItemList;
    List<EmailMessage> retrievedEmailList = new List<EmailMessage>();
    int offset = 0;
    bool MoreItems = true;
    const int pageSize = 9999;

    if (service != null)
    {
        try
        {
            InitExchangeService();

            SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
            FolderView fView = new FolderView(1000);
            fView.Traversal = FolderTraversal.Deep;

            //error hit at the following line
            FindFoldersResults findFolderResults = service.FindFolders(
                WellKnownFolderName.Inbox,
                new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep });

            if (findFolderResults.Folders.Count == 0)
            {
                AppLogger.LogInfo("No folders found in Inbox.");
                return retrievedEmailList;
            }

            else
            {
                foreach (Microsoft.Exchange.WebServices.Data.Folder folder in findFolderResults.Folders)
                {
                    if (folder.DisplayName == folderName)
                    {
                        while (MoreItems)
                        {
                            ItemView view = new ItemView(pageSize, offset, OffsetBasePoint.Beginning);
                            emailItemList = service.FindItems(folder.Id, sf, view);

                            foreach (var emailItem in emailItemList.Items)
                            {
                                EmailMessage email = EmailMessage.Bind(service, emailItem.Id);
                                retrievedEmailList.Add((EmailMessage)email);
                            }

                            if (!emailItemList.MoreAvailable)
                                MoreItems = false;

                            if (MoreItems)
                                offset += pageSize;
                        }
                        return retrievedEmailList;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            AppLogger.LogError(ex, "");
            throw ex;
        }
    }
    return retrievedEmailList;
}

Thank you.


Solution

  • Because the EWS Managed API is a client library anytime you use a Method that will send a Request to the Exchange server you should have a Try Catch block around that code. Errors can come from Client (eg Network, DNS, local client issue) or from the Server as either a generic 501 type error or where you receive a SOAP response with a underlying Service Response Error code like Throttling (ServerBusy) which has a backoff you need to process. So if you writing resilient code you handler should be looking for and dealing with each of these exception differently (although most will just need a retry but the interval of the retry may need to change if your getting throttled or in Office365 if the Mailbox is being moved between data-centers and is temporarily unavailable etc).