Click here to Skip to main content
15,884,177 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
In the following code snippet i attempt to save (with rename) an attachment to an email to a disk location.

Most of the time this works correctly but occasionaly it fails in the fAttachment.Load(filename) statement and an empty file is saved to disk.
When this occurs I get this exception:-

System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 10.0.0.1:443
   at System.Net.Sockets.Socket.EndConnect(IAsyncResult asyncResult)
   at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
   --- 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) By System On BMXS04


To get to the positionn where fAttachment.Load is being used requires that
a) I have already established a valid ExchangeService connection
b) I have sucessfully obtained a list of emails with attachments
c) The particular email I am working on has been sucessfully loaded
d) I am able to check the properties of the attachment to validate that it is of the type I want to save

so, when it comes to issue the fAttachment.Load everything should be good.

The exchange server is sitting on an internal SBS2011 box with Exchange 2010 SP3. All fully patched.
The machine (live) or development are both domain computers.

The attachments never exceed 4kb and are plain text.

Any advice would be gratefully accepted.

(P.S. First post here so I hope I did it correctly)

I have sanitised the following code follows:
C#
public static void HandleWeborder(string mhSavePath, string mhEmail)
{

    //
    try
    {
        var service = GetExchangeService();
        //
        if (service != null)
        {
            //
            var StartTime = DateTime.Now;
            bool wasOrder;
            // Allow a maximum of 150 emails per run.
            var view = new ItemView(150);
            var lookUp = mhEmail;
            var searchFilter = new SearchFilter.IsEqualTo(EmailMessageSchema.HasAttachments, true);
            var results = service.FindItems(new FolderId(WellKnownFolderName.Inbox, new Mailbox(lookUp)), searchFilter, view);
            if (results.TotalCount > 0)
            {
                foreach (EmailMessage email in results)
                {
                     wasOrder = false;
                     email.Load(new PropertySet(ItemSchema.Attachments));
                     foreach (Microsoft.Exchange.WebServices.Data.Attachment attachment in email.Attachments)
                     {
                         FileAttachment fAttachment = attachment as FileAttachment;
                         var test = fAttachment.Name.Substring(attachment.Name.Length - 3);
                         if (test == "xtx")
                         {
                            wasOrder = true;
                            var newName = fAttachment.Name.Substring(0, fAttachment.Name.IndexOf(".", StringComparison.Ordinal));
                            if (newName.Substring(0, 5) == "Order")
                            {
                                newName = newName.Substring(6);
                                newName = mhSavePath + "W" + newName;
                                //
                                var suf = ".txt";
                                if (File.Exists(newName + suf)) suf = ".dup";
                                if (File.Exists(newName + suf + ".bak")) suf = ".dup";
                                 newName += suf;
                                 bool dountiltrue = false;
                                 int attempts = 0;
                                 while (!dountiltrue)
                                 {
                                    try
                                    {
                                        fAttachment.Load(newName);
                                        wasOrder = true;
                                        dountiltrue = true;
                                    }
                                    catch (Exception ex)
                                    {
                                       if (attempts < 5)
                                       {
                                           attempts += 1;
                                           var innerEx = ex.InnerException.ToString();
                                           RunParms[PosLogMsg] = "Attempt " + attempts + " - Error " + newName + " May Have timed out - " + innerEx;
                                           RunParms[PosLogType] = LogError;
                                           AddActivity();
                                        }
                                     }
                                  }
                               }
                            }
                         }
                     }
                     if (wasOrder)
                     {
                        email.Delete(DeleteMode.HardDelete);
                     }
                }
            }
        }
    }
    catch (Exception ex)
    {
        //
        //TODO need to log error somehow
        //
        // might disable this logging because it may be pointless
        var innerEx = ex.InnerException.ToString();
        RunParms[PosLogMsg] = "Error 264-9 - " + innerEx;
        RunParms[PosLogType] = LogError;
        AddActivity();
    }
}


What I have tried:

I have added all these Try/Catch and manually stepped through but it does not error when stepping, only when in full run mode :-(

Note: Edited to remove all error recording as the Try/Catch handling was confusing some commenters. The Try/Catch were created simply to get a physical recording of the exception occurrence because it would take a day to step through the code to wait for the intermittent failure (the failure only occurs 3-5% of the times the code is called and always occurs at the fAttachment.Load(newName) statement
Posted
Updated 1-Aug-17 13:31pm
v2
Comments
Graeme_Grant 1-Aug-17 2:49am    
"on occasion, I catch an exception" - what is the exception? Do you mean error or from-time-to-time?

Umm, I see a couple of load commands, but no save commands. Am I missing something?
WoodseyAU 1-Aug-17 18:09pm    
Thanks for your response. To be able to assist me it would help if you were familiar with the EWS API 2.2. The fAttachment.LOAD(string) function takes an email attachment and saves it to the location and name specified in string.
David_Wimbley 1-Aug-17 12:54pm    
So just some comments as your code is hard to follow.

* You've got an ungodly amount of try catch statements in your code. You are probably eating an exception somewhere and not realizing it. If you need all those try catchs, fine, but for debugging purposes I would remove all of them but the first one, the highest level, so that way you can clearly see where your issues are.

* You've got if statements that look like this if (test != "xtx") continue; throughout your code. I'm not sure what their purpose is, and my personal preference is to always include brackets for if statements regardless of how many lines it is as it is easy to overlook stuff like this. For all you know, because you are relying on try/catch for debugging, you might be hitting one of these conditions and not realizing it.

* Instead of relying on try/catch to do your debugging, set break points and step through your code to pinpoint the issue. Try/catch is great as a postmortem of your problem but break points let you look at your app while its running, you might spot something on the locals tab or whatever that you can't see from a try/catch exception being logged.

* If you were hitting a time out or whatever your exception would say so. You need to provide the output of your exception, right now its as much a guessing game for us as it is apparently for you. Your error isn't clear

* It looks as though you are missing code. As Graeme_Grant said, I don't see anywhere in your code snippet where you are trying to save anything to a file. I would expect to see something like email.Save(filepath) or something to that effect.
WoodseyAU 1-Aug-17 18:13pm    
Thank you for your comments. Yes, this is full of try/catch statements which were used to allow tracing of the application in run mode rather than debug mode. Because the issue is intermittent (i.e. 95% of the times this process runs it has no issues) I can't sit in debug mode and step through it. This would take all day :-(
The if (test !- '"xtx") continue construct was the result of using resharper. This (so they say) stops the code becoming too indented. I also doubt this at times and it does make clarity more difficult.
You are correct, I did not put the exception in. I shall edit the question now.


Graeme_Grant 1-Aug-17 18:38pm    
To make the code easier to read, I would refactor repetitive code to a single method.
This appears multiple times:
RunParms[PosLogType] = LogMail;RunParms[PosLogMsg] = "Checking For New eMails";AddActivity();

To:
private void LogActivity(LogTypeEnum type, string msg)
{
    RunParms[PosLogType] = type;
    RunParms[PosLogMsg] = msg;
    AddActivity();
}

allowing:
LogActivity(LogMail, "Checking For New eMails");

And this:
var innerEx = ex.InnerException.ToString();
RunParms[PosLogMsg] = "Error 264-3 - " + innerEx;
RunParms[PosLogType] = LogError;
AddActivity();

To this:
LogActivity(LogError, $"Error 264-3 - {ex.InnerException.ToString()}");

Your code will become infinitely easier to read.

1 solution

Just another thought, without knowing if the app and the storage server are in remote locations to each other, or are on the same server, it could be simply a network lag issue causing a transient issue.

If the two are remote to each other, then you may need a better retry mechanism. Here is a RetryOperationHelper[^] that could be adapted to your requirements. I would also recommend implementing an Exponential backoff[^] strategy to allow for greater durability.
 
Share this answer
 
Comments
WoodseyAU 1-Aug-17 19:46pm    
Exchange Server/ Storage server (SBS2011 Domain Controller etc.) and App PC (Server 2012 with SQL Server and other applications running) are physically about 3 inches from each other. By lan cabling approx 2metres through a 1gb switch. Lag should be very close to zero :-)
I will look at your references when I get opportunity. As single IT in small company I am typically firefighting many different issues daily, particularly after M$ updates get brute forced into us).

I implemented the lock and it has not changed performance at all. Code is running perfectly so far and waiting for the exceprtion to occur (as it does 2-3 times a day).
Graeme_Grant 1-Aug-17 20:01pm    
Yes, it should not happen but the problem indicates that the local app gave up on the remote server. Maybe the problem then is on the remote server taking too long to process the task given causing the local server to timeout. Maybe either improve the time it takes the remote server or extend the timeout time on the local server to accomodate.

Another question: Does the remote server run any periodical tasks/jobs that could cause any latency? Does the remote server have a scheduled reboot or a daily backup plan? These could also cause the problems experienced.
WoodseyAU 1-Aug-17 20:21pm    
The exception occurred.
Because I put it into that retry loop (which I only implemented today) it tried again and handled it sucessfully. As you suggest, this points to an issue on the exchange service itself. It already has a 60 second timeout set in its initliasation. I will extend that to 120 and see if I still get the exception.
As to reasons for the timeout, that particular box is running at cpu 4-7%, mem at 90% (because of exchange store being allocated heaps). I think the exception, even though pointing to exchange being the culprit, may actually be a diskio queue latency as the server is also the primary drive map share for the domain. If that is the case then extending the exchange timeout should not solve the problem.
Graeme_Grant 1-Aug-17 20:37pm    
Let us hope that extending the timeout resolves it for you then.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900