Share via


Exchange webservice: The underlying connection was closed: An unexpected error occurred on a send.

Question

Tuesday, November 5, 2013 12:25 PM

I am just creating an windows service to check the  unread mails (outlook.office365.com) using EWS 2.0 

When i run 

The request failed. The underlying connection was closed: An unexpected error occurred on a send.
File: CheckEmail.cs Method : ReadEmailContent Line: 77
System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. > System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. > System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
   at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
    End of inner exception stack trace
   at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
   at System.Net.PooledStream.EndWrite(IAsyncResult asyncResult)
   at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
    End of inner exception stack trace
   at System.Net.HttpWebRequest.GetResponse()
   at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.GetResponse()
   at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request)

I can't able to reproduce this error while debugging 

  public void ReadEmailContent()
        {         
            try
            {
                if (!string.IsNullOrEmpty(emailConfig.EmailID))
                {
                    ExchangeService service = new ExchangeService();
                    service.Credentials = new WebCredentials(emailConfig.EmailID, emailConfig.Password);
                    service.UseDefaultCredentials = false;
                    service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");           

                    Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);
                    SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
                    if (inbox.UnreadCount > 0)
                    {
                        ItemView view = new ItemView(inbox.UnreadCount);
                        FindItemsResults<Item> findResults = inbox.FindItems(sf, view);
                        PropertySet itempropertyset = new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.From, EmailMessageSchema.ToRecipients);
                        itempropertyset.RequestedBodyType = BodyType.Text;
                        //inbox.UnreadCount
                        ServiceResponseCollection<GetItemResponse> items = service.BindToItems(findResults.Select(item => item.Id), itempropertyset);
                        MailItem[] msit = getMailItem(items, service);

                        foreach (MailItem item in msit)
                        {
                            item.Message.IsRead = true;
                            item.Message.Update(ConflictResolutionMode.AlwaysOverwrite);
                            foreach (Attachment attachment in item.Attachment)
                            {
                                if (attachment is FileAttachment)
                                {
                                    string extName = attachment.Name.Substring(attachment.Name.LastIndexOf('.'));
                                    FileAttachment fileAttachment = attachment as FileAttachment;
                                    fileAttachment.Load(emailConfig.TargetFolder.ToString() + attachment.Name);
                                    Console.WriteLine("Attachment name: " + fileAttachment.Name + fileAttachment.Content + fileAttachment.ContentType + fileAttachment.Size);
                                }
                            }
                        }
                    }
                    DeleteMail();
                }
            }
            catch (Exception ex)
            {                             
                Logger.Write(ex);
            }
            finally
            {

            }
        }

        // To delete the old emails
        public void DeleteMail()
        {
            try
            {
               // ExchangeService service = new ExchangeService();
                if (!string.IsNullOrEmpty(emailConfig.EmailID))
                {
                    ExchangeService service = new ExchangeService();
                    service.Credentials = new WebCredentials(emailConfig.EmailID, emailConfig.Password);
                    service.UseDefaultCredentials = false;
                    service.Url = new Uri(emailConfig.ServerName);     

                    DateTime searchdate = DateTime.Now;
                    searchdate = searchdate.AddDays(-4);
                    SearchFilter greaterthanfilter = new SearchFilter.IsGreaterThanOrEqualTo(ItemSchema.DateTimeReceived, searchdate);
                    SearchFilter lessthanfilter = new SearchFilter.IsLessThan(ItemSchema.DateTimeReceived, searchdate);
                    SearchFilter filter = new SearchFilter.SearchFilterCollection(LogicalOperator.Or, lessthanfilter);
                    Folder folder = Folder.Bind(service, WellKnownFolderName.Inbox);
                    //Or the folder you want to search in
                    if (folder.TotalCount > 0)
                    {
                        FindItemsResults<Item> results = folder.FindItems(filter, new ItemView(folder.TotalCount));
                        if (results.Count() > 0)
                        {
                            foreach (Item i in results.Items)
                            {
                                i.Delete(DeleteMode.MoveToDeletedItems);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Write(ex);
            }
            finally
            {

            }
        }

        //To parse the email content
        private MailItem[] getMailItem(ServiceResponseCollection<GetItemResponse> items, ExchangeService service)
        {
            MailItem[] mainItems = null;
            try
            {
                mainItems = items.Select(item =>
                {
                    return new MailItem()
                    {
                        Message = EmailMessage.Bind(service, item.Item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments, ItemSchema.HasAttachments)),
                        From = ((Microsoft.Exchange.WebServices.Data.EmailAddress)item.Item[EmailMessageSchema.From]).Address,
                        Recipients = ((Microsoft.Exchange.WebServices.Data.EmailAddressCollection)item.Item[EmailMessageSchema.ToRecipients]).Select(recipient => recipient.Address).ToArray(),
                        Subject = item.Item.Subject,
                        Body = item.Item.Body.ToString(),
                        Attachment = item.Item.Attachments.ToList(),
                        ReceivedDateTime = item.Item.DateTimeReceived
                    };
                }).ToArray();
            }
            catch (Exception ex)
            {
                Logger.Write(ex);
            }
            finally
            {

            }
            return mainItems;
        }

jayakumar

All replies (5)

Wednesday, November 6, 2013 1:58 AM

Generally that means the other end has dropped the connection while it was in use. If your application is trying to run against multiple accounts using multiple threads then it could be throttling http://msdn.microsoft.com/en-us/library/office/jj945066(v=exchg.150).aspx.

The other time I've seen this is when you have a intermittent network link eg the link drops before the operations completed and then restabilises back and the client tries to continue to use the TCP connection that the other end has already dropped. There isn't much you can do in this instance other then catch the exception and retry the operation.

Cheers
Glen


Wednesday, November 6, 2013 4:31 AM

Hi Glen Scales,

Thanks for your reply

In this service application i uses timer to perform the operation

Whether this will be reason for connection drop.

   public void _CheckMail()
        {
            ReadEmailContent();
            timer = new System.Timers.Timer();
            timer.Interval = 80000D;
            timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Enabled = true;
            timer.Start();
        }
  protected void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            ReadEmailContent();
        }

Whether there is any other option to overcome it, for reading the exchange server mails without any error log. 
Thanks in advance

jayakumar


Wednesday, November 6, 2013 6:01 AM

Hi Glen Scales

I didn't got those error initially. ie i coded this one month before but at that time it works fine 

jayakumar


Wednesday, November 6, 2013 6:02 AM

If your underlying network link isn't reliable, other then catching the exception and retrying the operation there isn't much you can do.

The code itself your using isn't that efficient if your processing a large number of items which may explain why you getting throttled (if you are).

a few things Eg instead of using Bind eg

   Message = EmailMessage.Bind(service, item.Item.Id,

 to load items one at time which will makes a separate request for each item you should look at using LoadPropertiesfromItems http://blogs.msdn.com/b/exchangedev/archive/2010/03/16/loading-properties-for-multiple-items-with-one-call-to-exchange-web-services.aspx . This will reduce the number of calls you application needs to make and reduce the likely hood of errors or throttling issues.

You should also batch the Deletes your making using deleteitems http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.exchangeservice.deleteitems(v=exchg.80).aspx rather then calling the delete method on each item separately which will also reduce the number of calls your making to the server.

Also instead of using the SearchFilter like you have you would be better using an AQS query which will use the Exchange indexes and you also need to Page your searches in batches of 1000 (throttling will restrict this anyway so the query your using if your expecting to process any more then 1000 objects won't work as it is to process all the available items.).

eg

            DateTime searchdate = DateTime.Now;
            searchdate = searchdate.AddDays(-4);
            Folder folder = Folder.Bind(service, WellKnownFolderName.Inbox);
            String AQSQueryString = "System.Message.DateReceived:<" + searchdate.ToString("MM/dd/yyyy");
            ItemView iv = new ItemView(1000);
            //iv.PropertySet = new PropertySet(BasePropertySet.IdOnly);
            //Or the folder you want to search in
            if (folder.TotalCount > 0)
            {
                FindItemsResults<Item> results = null;
                do
                {
                    results = folder.FindItems(AQSQueryString, iv);
                    if (results.Count() > 0)
                    {
                        foreach (Item i in results.Items)
                        {
                            if (i.DateTimeReceived < searchdate)
                            {
                                Console.WriteLine(i.Subject);
                            }
                        }
                    }
                    iv.Offset += results.Items.Count;
                } while (results.MoreAvailable);
            }

Cheers
Glen


Thursday, November 7, 2013 8:00 AM

Hi Glen,

After gone through this http://msdn.microsoft.com/en-us/library/office/jj945066(v=exchg.150).aspx
i
 understand your points. 

Thanks for your Comments 

jayakumar