I have been working with Exchange Web Services(EWS) for a long time and this is the first time I saw that the EWS was lying to me! The code was executing a FindItem call on a list of folders and all of a sudden it threw the following error: “Error occurred: The request failed. The remote server returned an error: (401) Unauthorized”.
Why would that happen? If it was an authentication problem then why did my previous call work? The first step was to check the IIS Logs on the CAS server and below is what we find:
7/11/2012 10.171.230.40 POST /EWS/Exchange.asmx SoapAction=FindItem 443 ExchangeServicesClient/14.03.0067.001 200 630257/11/2012 10.171.230.40 POST /EWS/Exchange.asmx SoapAction=FindItem 443 ExchangeServicesClient/14.03.0067.001 200 218097/11/2012 10.171.230.40 POST /EWS/Exchange.asmx SoapAction=FindItem 443 ExchangeServicesClient/14.03.0067.001 302 1967527/11/2012 10.171.230.40 POST /EWS/Exchange.asmx SoapAction=FindItem 443 ExchangeServicesClient/14.03.0067.001 302 196643
But, why do I get the 302? I turned my attention to the Event Logs on the CAS box and I did not have to search too much. Below is what I saw:
Log Name: ApplicationSource: ASP.NET 2.0.50727.0Date: 7/11/2012 12:58:05 PMEvent ID: 1309Task Category: Web EventLevel: WarningKeywords: ClassicUser: N/AComputer: myserver.contoso.comDescription:Event code: 3001 Event message: The request has been aborted. Event time: 7/11/2012 12:58:05 PM Event time (UTC): 7/11/2012 4:58:05 PM Event ID: 38a627eada914200923e244e9c83f7c8 Event sequence: 6230694 Event occurrence: 37 Event detail code: 0 Application information: Application domain: /LM/W3SVC/1/ROOT/EWS-1-129851299999841294 Trust level: Full Application Virtual Path: /EWS Application Path: C:\Program Files\Microsoft\Exchange Server\ClientAccess\exchweb\EWS\ Machine name: myserver Process information: Process ID: 1152 Process name: w3wp.exe Account name: NT AUTHORITY\SYSTEM Exception information: Exception type: HttpException Exception message: Request timed out. Request information: Request URL: https://myserver.contoso.com:443/EWS/Exchange.asmx Request path: /EWS/Exchange.asmx User host address: 10.171.230.40 User: DOMAIN\Username Is authenticated: True Authentication Type: Negotiate Thread account name: NT AUTHORITY\SYSTEM Thread information: Thread ID: 26 Thread account name: NT AUTHORITY\SYSTEM Is impersonating: False Stack trace:
Now the picture is clearer! Since the request was running for more that 110 seconds which is default timeout in ASP.NET 2.0, the request was being aborted, which resulted in a 302 in the IIS logs. Now why did EWS Managed API return 401, frankly I did not bother to find!
To validate the cause we went ahead and increased the executionTimeout from 110 to 240 in the Web.Config for EWS and then we did not see the issue any more. This was done for TESTING only and is definitely not recommended.
There are two possible solutions to this issue:
1) Optimize your code and use filters and paging while doing FindItems (Recommended).
2) Increase the executionTimeout setting in the Web.Config(Not Recommended – can be tried only If optimization does not work ).
Not sure developers using System.Net.Mail are not complaining about this issue? The issue is very easy to reproduce, all you need to do is create a new mail with someone on Bcc and drop it to the Pickup folder In Exchange. Most likely not to many people use Bcc or use Port instead of Pickup.
MailMessage message = new MailMessage("User1@mycompany.com", "User2@mycompany.com", "Sent Using Pickup", "This Message was sent using Pickup");message.Bcc.Add(new MailAddress("User3@mycompany.com"));SmtpClient client = new SmtpClient();client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;client.PickupDirectoryLocation = @"C:\Program Files\Microsoft\Exchange Server\TransportRoles\Pickup";client.Send(message);
What could the difference be? I stopped the Transport service on my Exchange 2007(installed on Windows 2003) so that the mail do not get delivered by the transport and then examined the .eml to check what the difference could be. Below is what I find:
System.Net.Mail uses X-Headers to add the Recipient information to the mail.Below is what the MIME look like on my Windows 2003 box:
X-Sender: User1@mycompany.comX-Receiver: User2@mycompany.comX-Receiver: User3@mycompany.com <- This is the BCCMIME-Version: 1.0From: User1@mycompany.comTo: User2@mycompany.comDate: 19 Jul 2012 13:53:05 -0400Subject: Sent Using PickupContent-Type: text/plain; charset=us-asciiContent-Transfer-Encoding: quoted-printableThis Message was sent using Pickup
thread-index: Ac1l181oBFqzycOSRFaCD7mjVftgqw==Thread-Topic: This is a test CDOSYS message (Sent via Pickup)From: <User1@mycompany.com>To: <User2@mycompany.com>Bcc: <User3@mycompany.com>Subject: This is a test CDOSYS message (Sent via Pickup)Date: Thu, 19 Jul 2012 13:56:20 -0400Message-ID: <D76CF8D778AE43A096B10F2281A9914F@mycompany.com>MIME-Version: 1.0...
MailMessage message = new MailMessage("User1@mycompany.com", "User2@mycompany.com", "Sent Using Pickup", "This Message was sent using Pickup");message.Bcc.Add(new MailAddress("User3@mycompany.com"));SmtpClient client = new SmtpClient();client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;client.PickupDirectoryLocation = @"C:\Program Files\Microsoft\Exchange Server\TransportRoles\Replay";client.Send(message);