1
votes

We are using EWS Managed API 2.2 to detect when new messages are received in multiple email account hosted in Office365. We've adapted this sample program.

Using Streaming Notifications with Exchange 2010

Basically this windows command line application will contact an Exchange server and wait for new messages to arrive. This is done using a single instance of ExchangeService. To get notifications we use the StreamingSubscription object to perform a hanging HTTP Get.

The sample program works great, until we attempt to connect to multiple accounts. With each instance in its own Thread, with two different exchange accounts, with two ExchangeService and two StreamingSubscription, the exact same code throws errors.

The error is thrown in different locations but let's focus on this one for now.

In the StreamingSubscription OnNotificationEvent callback, this code will throw "the operation has timed out".

ExchangeService.SyncFolderItems(folderId,PropertySet.IdOnly,null,5,SyncFolderItemsScope.NormalItems, State);

If we catch this error and ignore it on subsequent calls we see these errors:

  • "Unable to retrieve events for this subscription. The subscription must be recreated., The events couldn't be read"

  • "Microsoft.Exchange.WebServices.Data.ServiceLocalException: You must add at least one subscription to this connection before it can be opened"

Now we understand that the EWS library is NOT THREAD SAFE, but we are creating two totally parallel instances where no objects in another thread is changed.

We also have found that if the code is run in two separate Processes not Threads, the error disappears.

Our theories are:

  • Simple Bug or use of static in StreamingSubscription?
  • Could the ExchangeService Affinity cookies somehow be overwritten, so the information about which slot in the CAS server is being reused by the second thread?

Is this the right way to accomplish our goal? In the video:

Exchange Web Services Affinity and Throttling at minute 47:00

They discuss a process architecture where subscriptions are managed in multiple processes and mailbox access is managed in a separate process. The speaker states that this is a load balancing strategy and not a requirement of use.

Any help would be appreciated.

Update:

We found that it appears possible to damage the account if two users run the two same email accounts at the same time.

user 1 : runs account 1,account 2

user 2: runs account 1,account 2

Now both users experience timeouts for the same account.

1
Update: Damaged account was caused by the "Clutter" filter rerouting the messages to "Clutter" folder.mbalsam
Are you using impersonation?rojobo
Update: When running in two seporate processes we eventually got the same error.mbalsam
We attempted to use Impersonation and followed the steps in this article: blog.kloud.com.au/2014/12/02/… Even with this code we got O365 Oauth permissions errors. The error was "ErrorImpersonateUserDenied" with an inner exception of “The account does not have permission to impersonate the requested user.” So we needed to give up on that approach for now.mbalsam
Update: We also found that we were not starting the threads correctly. Initailly we said: var theTask = tfactory.StartNew(() => { } But realized that we need to add the option to run a LongRunning Thread or a background thread pool would not be created. So we added this to the ending brace , CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);mbalsam

1 Answers

1
votes

It was a simple oversight.

ServicePointManager.MaxServicePoints = 100

Solved the problem.