locked
SMTP Client Throwing Exception on Second Email RRS feed

  • Question

  • Hi,

                I am trying to send an email specifying the Local IP Address. In the code below, I get a list of all local IP Addresses, and attempt to send out emails on each of them. If I comment out the line:

    client.ServicePoint.BindIPEndPointDelegate += new System.Net.BindIPEndPoint(BindIPEndPointCallback);

    There is no exception, but then I cannot select the outgoing IP Address for each email. So this is not a solution. The Exception I get is as below.

    A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
    A first chance exception of type 'System.Net.WebException' occurred in System.dll
    A first chance exception of type 'System.Net.WebException' occurred in System.dll
    A first chance exception of type 'System.Net.WebException' occurred in System.dll
    A first chance exception of type 'System.Net.Mail.SmtpException' occurred in System.dll
    A first chance exception of type 'System.Net.Mail.SmtpException' occurred in MyEXEName.exe

    The code is as below

    using System;
    using System.Linq;
    using System.Diagnostics;
    using System.Net;
    using System.Net.Mail;
     
    namespace EmailCampaign
    {
        class Program
        {
            private static IPAddress sendEmail; //Set in the Loop, used in the Callback.
            static void Main(string[] args)
            {
                IPHostEntry entry = Dns.GetHostEntry(Dns.GetHostName());
                foreach (IPAddress ipa in entry.AddressList.Where(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork))
                {
                    sendEmail = ipa;
                    string ipAddressStr = ipa.ToString();
     
                    Debug.WriteLine("Sending Email from IP: {0}"new object[] { ipAddressStr });
                    using (MailMessage msg = new MailMessage())
                    {
                        msg.Body = String.Format("Email sent from IP: {0}", ipAddressStr);
                        msg.From = new MailAddress("me@me.com");
                        msg.IsBodyHtml = false;
                        msg.Subject = String.Format("Test Email from IP: {0}", ipAddressStr);
                        msg.To.Add(new MailAddress("to@to.com"));
     
                        
                        using (SmtpClient client = new SmtpClient())
                        {
                            client.Host = "10.50.1.83";
                            client.Port = 25;
                            client.EnableSsl = false;
                            //This is the Problem -> Commenting out this line would supress the exception.
                            client.ServicePoint.BindIPEndPointDelegate += new System.Net.BindIPEndPoint(BindIPEndPointCallback);
                            client.ServicePoint.ConnectionLeaseTimeout = 0;
                            client.Send(msg);
                        }
                    }
                   
                }
                
            }
     
            private static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
            {
                return new IPEndPoint(sendEmail, 0);
            }
        }
    }
    

    I can swear I could get this to work a month ago, but it does not work right now. I’d be grateful for any ideas.

    Thank you,

    O. O.


    • Edited by o-o-o-o Monday, June 4, 2012 8:33 PM
    Monday, June 4, 2012 8:31 PM

Answers

  • As to the exception.  Isn't that EXACTLY what you were expecting???  Aren't you expecting that some local IP address won't be useable to send email to the SMTP server?  That's exactly what that exception is telling you.  "I tried to access the SMTP server, but it timed out" -- because it wasn't accessible from the address I used that time from the list of all addresses.

    I think there is no problem with your program.  If you could send for all local address last month, then I suggest that the set-up of the network has changed, or the list of local addresses has changed...

    If I've misunderstoor please explain why you are getting all the local IP addresses and trying to send the same email from each one.

     

    So to filter the list of addresses to IPv4 only just add a WHERE clause, i.e. use:

    var myAddresses = from ni in NetworkInterface.GetAllNetworkInterfaces()
        from addr in ni.GetIPProperties().UnicastAddresses
        where addr.Address.AddressFamily == AddressFamily.InterNetwork
        select addr.Address;
    

    .


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

    • Marked as answer by o-o-o-o Thursday, June 7, 2012 4:16 PM
    Wednesday, June 6, 2012 9:24 PM

All replies

  • You don't need to create a new client for each message.  Your error is probably is caused by you attempting to make a 2nd connection with the same source IP, destination IP, and prot number.  I moved the client initialization code towards the beginning of the code.  The last time you  ran the code you probably only sent one email.  Now you are looping through a number of emails.

    using System;
    using System.Linq;
    using System.Diagnostics;
    using System.Net;
    using System.Net.Mail;
    namespace EmailCampaign
    {
        class Program 
        {
            private static IPAddress sendEmail; //Set in the Loop, used in the Callback.
            static void Main(string[] args)
            {
                IPHostEntry entry = Dns.GetHostEntry(Dns.GetHostName());
                SmtpClient client = new SmtpClient();
                client.Host = @"10.50.1.83";
                client.Port = 25;
                client.EnableSsl = false;
                //This is the Problem -> Commenting out this line would supress the exception.
                client.ServicePoint.BindIPEndPointDelegate += new System.Net.BindIPEndPoint(BindIPEndPointCallback);
                client.ServicePoint.ConnectionLeaseTimeout = 0;
                foreach (IPAddress ipa in entry.AddressList.Where(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork))
                {
                    sendEmail = ipa;
                    string ipAddressStr = ipa.ToString();
                    Console.WriteLine("Sending Email from IP: {0}", new object[] { ipAddressStr });
                    using (MailMessage msg = new MailMessage())
                    {
                        msg.Body = String.Format("Email sent from IP: {0}", ipAddressStr);
                        msg.From = new MailAddress("me@me.com");
                        msg.IsBodyHtml = false;
                        msg.Subject = String.Format("Test Email from IP: {0}", ipAddressStr);
                        msg.To.Add(new MailAddress("to@to.com"));
                        client.Send(msg);
                    }
                }
            }
            private static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
            {
                return new IPEndPoint(sendEmail, 0);
            }
        }
    }


    jdweng

    • Proposed as answer by MusicDemon Tuesday, June 5, 2012 12:48 PM
    • Unproposed as answer by o-o-o-o Wednesday, June 6, 2012 5:12 PM
    Monday, June 4, 2012 10:37 PM
  • I can see no unhandled exception occurring.  All the debug logging that you show there is just information.  It just shows exceptions that are handled successfully, that's what "first chance" means.  Is that the correct logging?

    Are you expecting that sending SMTP from some of the local addresses will fail?  If so then you will get an exception from some of the sends.  You'll need a try/catch inside the loop to handle the failing attempts.

    I never understand why Dns.GetHostEntry is used to ask a remote DNS server to get the list of my PC's local addresses?!?  To get the list of local addresses I'd do the following.

    var myAddresses = from ni in NetworkInterface.GetAllNetworkInterfaces()
        from addr in ni.GetIPProperties().UnicastAddresses
        select addr.Address;

    Perhaps the DNS server now has a different send of addresses for your machine than it did a month ago?


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.



    Wednesday, June 6, 2012 3:09 PM
  • Dear Joel,

                This will not work for me because the BindIPEndPointCallback never gets called subsequent times if SmtpClient.Dispose() is not called first.

                Is it possible to call SmtpClient.Dispose() for each email sent out? I don’t understand why making a 2<sup>nd</sup> connection to the same IP is the problem, when I can just run the application again and it would work for the second connection. Do you have any idea where this connection is being saved? I tried sending this out on a separate appdomain and unloading it before making the next connection and it does not work too?? i.e. I still get the exception.

    Thank you for your help,

    O. O.

    Wednesday, June 6, 2012 5:13 PM
  • Dear Alan,

                I am not experienced with the method you are showing to get the network addresses. What I currently have, I copied it from the web and verified that it worked. As far as your suggestion could you show me how to restrict it to IPv4 addresses only. I seem to get a bunch of IPv6 addresses too.

                Yes, I did not post the exception before. I could not get it into the debugger window where it is easy to copy. I am getting the exception at the line client.Send(msg);. Here I selected the option to copy the exception to the clipboard, and it is as below. (I changed the project and usernames to protect my identity.)

    System.Net.Mail.SmtpException was unhandled
      Message=Failure sending mail.
      Source=System
      StackTrace:
           at System.Net.Mail.SmtpClient.Send(MailMessage message)
           at EmailCampaign.Program.Main(String[] args) in C:\Users\user\Documents\Visual Studio 2010\Projects\EmailCampaign\EmailCampaign\Program.cs:line 52
           at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
           at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
           at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           at System.Threading.ThreadHelper.ThreadStart()
      InnerException: System.Net.WebException
           Message=Unable to connect to the remote server
           Source=System
           StackTrace:
                at System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6, Int32 timeout)
                at System.Net.PooledStream.Activate(Object owningObject, Boolean async, Int32 timeout, GeneralAsyncDelegate asyncCallback)
                at System.Net.PooledStream.Activate(Object owningObject, GeneralAsyncDelegate asyncCallback)
                at System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralAsyncDelegate asyncCallback, Int32 creationTimeout)
                at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
                at System.Net.Mail.SmtpTransport.GetConnection(ServicePoint servicePoint)
                at System.Net.Mail.SmtpClient.GetConnection()
                at System.Net.Mail.SmtpClient.Send(MailMessage message)
           InnerException: System.Net.Sockets.SocketException
                Message=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.50.1.83:25
                Source=System
                ErrorCode=10060
                NativeErrorCode=10060
                StackTrace:
                     at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
                     at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
                InnerException: 


    Thank you,

    O. O.




    • Edited by o-o-o-o Wednesday, June 6, 2012 5:48 PM
    Wednesday, June 6, 2012 5:47 PM
  • A connection consists of a source IP, a Destination IP, and a Port Number.  You can't have more than one connection at any time wiht all 3 numbers being the same.  Most people when trying to make multiple connections will use a different port number of each connection, but you are using SMTP which need port number 25.

    I had a similar porting with SMTP a couple of months ago the solution was very simple.  Make the class disposable and then use dispose.  I can't find the solution.  I don't remember if setting the client to null worked or we did something else.  If I have time tonight I will look for the old posting.  the changes below I think will work.

    using System;
    using System.Linq;
    using System.Diagnostics;
    using System.Net;
    using System.Net.Mail;
    namespace EmailCampaign
    {
        class Program 
        {
            private static IPAddress sendEmail; //Set in the Loop, used 
            static void Main(string[] args)
            {
               IPHostEntry entry = Dns.GetHostEntry(Dns.GetHostName());
               foreach (IPAddress ipa in entry.AddressList.Where(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork))
               {
                   sendEmail = ipa;
                   string ipAddressStr = ipa.ToString();
                   Console.WriteLine("Sending Email from IP: {0}", new object[] { ipAddressStr });
                   using (MailMessage msg = new MailMessage())
                   {
                       msg.Body = String.Format("Email sent from IP: {0}", ipAddressStr);
                       msg.From = new MailAddress("me@me.com");
                       msg.IsBodyHtml = false;
                       msg.Subject = String.Format("Test Email from IP: {0}", ipAddressStr);
                       msg.To.Add(new MailAddress("to@to.com"));
                       new SNTP(msg, sendEmail);
                   }
               }
             }
            public static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
            {
                return new IPEndPoint(sendEmail, 0);
            }
        }
        class SNTP : IDisposable
        {
            public SNTP(MailMessage msg, IPAddress sendEmail)
            {
                SmtpClient client = new SmtpClient();
                client.Host = @"10.50.1.83";
                client.Port = 25;
                client.EnableSsl = false;
                //This is the Problem -> Commenting out this line would supress the exception.
                client.ServicePoint.BindIPEndPointDelegate += new System.Net.BindIPEndPoint(Program.BindIPEndPointCallback);
                client.ServicePoint.ConnectionLeaseTimeout = 0;
                client.Send(msg);
                client = null;
             }
            public void Dispose()
            {
            }
     
        }    
    }


    jdweng

    Wednesday, June 6, 2012 5:53 PM
  • Is it still failing the second send message?  If so then try adding the line below.  It will dispose the client and close tthe underlining ethernet connection.  this is exactly what we did last time to resolve the issue

    below is the previous posting where we used dispose to fix the problem

    http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/e2df7327-91ba-443d-9738-ed6915d17300

    From

    new SNTP(msg, sendEmail);

    To

    SNTP mailclient = new SNTP(msg, sendEmail);
    mailclient.Dispose();


    jdweng

    Wednesday, June 6, 2012 7:28 PM
  • Dear Joel,

                Thank you for taking interest. I am changing the source IP Address each time I make the connection. (That’s what the foreach loop does.)

                Did you intend to keep the Dispose() method empty?? If it does nothing what is the point of calling it?

                The code you posted does not call the SmtpClient.Dispose(). Because of this the call to BindIPEndPointCallback only occurs once and the emails get sent out only using the first IP Address. This is not what I intended.

                Yes, that link: http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/e2df7327-91ba-443d-9738-ed6915d17300 is where we used Dispose() to fix the issue. I have not changed anything on my machine, but it seems that does not work now.

                What is see differently now is that if you call client.Dispose(); the next call to client.Send(); generates the exception I posted above. I think Microsoft has pushed out some update that has made some changes. I can swear this worked, and I also incorporated the technique in my project and test it. 

    And yes, I was sending multiple emails before and am sending multiple emails now. This is because I am sending an email for each local IPv4 address I have.

    Thanks again,

    O. O.


    • Edited by o-o-o-o Wednesday, June 6, 2012 8:10 PM
    Wednesday, June 6, 2012 8:09 PM
  • I made the class disposable by adding Idisposible.  Once you do that you need to have a dispose method for the code to compile.  Microsoft must of pushed a change to the net library that broke your code???  I still have net 3.5 on my PC and with 3.5 I can't get client.dispose to compile.  that is why I set the client to null.  I would put wireshark trace and see if the conenction is actually closing.  Also check the dos command netstat -a.  In both test I would put a break point after the 1st email to see if the connection is actually closing.  With Net 4.5 microsoft changes a number of default settings.  I had one problem where we had to set the delivery method to Network (see below).  The perrson who had the problem said it worked with 4.0 and then stopped working with 4.5. But you are saying the 1st email works so I don't think this is a problem.

     smtp.DeliveryMethod = SmtpDeliveryMethod.Network;


    jdweng

    Wednesday, June 6, 2012 9:07 PM
  • As to the exception.  Isn't that EXACTLY what you were expecting???  Aren't you expecting that some local IP address won't be useable to send email to the SMTP server?  That's exactly what that exception is telling you.  "I tried to access the SMTP server, but it timed out" -- because it wasn't accessible from the address I used that time from the list of all addresses.

    I think there is no problem with your program.  If you could send for all local address last month, then I suggest that the set-up of the network has changed, or the list of local addresses has changed...

    If I've misunderstoor please explain why you are getting all the local IP addresses and trying to send the same email from each one.

     

    So to filter the list of addresses to IPv4 only just add a WHERE clause, i.e. use:

    var myAddresses = from ni in NetworkInterface.GetAllNetworkInterfaces()
        from addr in ni.GetIPProperties().UnicastAddresses
        where addr.Address.AddressFamily == AddressFamily.InterNetwork
        select addr.Address;
    

    .


    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

    • Marked as answer by o-o-o-o Thursday, June 7, 2012 4:16 PM
    Wednesday, June 6, 2012 9:24 PM
  • Joel, what are you doing?  You make a class and add a Dispose method to make it compile, but the Dispose method does NOTHING...  Please explain how that could possibly help in disposing previous instances of network classes...

    http://www.alanjmcf.me.uk/ Please follow-up in the newsgroup. If I help, please vote and/or mark the question answered. Available for contract programming.

    Wednesday, June 6, 2012 9:26 PM
  • Dear Joel & Alan,

                I am grateful to both of you for taking interest. I am sorry for wasting your time.

                This was a network issue. Alan you guessed correctly. For some reason the SMTP server was rejecting this second IP. I changed it to some other IP and everything works now i.e. I can send the second email with the IP of my choice.

    Thank you guys,

    O. O.

      

    Thursday, June 7, 2012 4:16 PM