views:

149

answers:

6

I have an application that uses SmtpClient to send E-Mail, but the E-Mails are not sent until the application closes. I have searched and searched to find a solution to the problem, but I am not able to find one.

The system does have Symantec anti-virus installed, which could possibly be the problem.

Does anybody have a solution to this problem?

Here is the code I am using.

public class EMail
{
    private string server;
    public string Server {get{return this.server;}set{this.server = value;}}
    private string to;
    public string To {get{return this.to;}set{this.to = value;}}
    private string from;
    public string From {get{return this.from;}set{this.from = value;}}
    private string subject;
    public string Subject {get{return this.subject;}set{this.subject = value;}}
    private string body;
    public string Body {get{return this.body;}set{this.body = value;}}

    public EMail()
    {}
    public EMail(string _server, string _to, string _from, string _subject, string _body)
    {
        this.Server = _server;
        this.To = _to;
        this.From = _from;
        this.Subject = _subject;
        this.Body = _body;
    }   

    public void Send()
    {
        using(System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(this.From, this.To, this.Subject, this.Body))
        {        
            message.IsBodyHtml = true;
            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(this.Server);
            client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
            //I have tried this, but it still does not work.
            //client.ServicePoint.ConnectionLeaseTimeout = 0;
            try 
            {
                client.Send(message);
            }  
            catch(System.Exception ex) 
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString());              
            }
        }
    }
}

Edit:

It turns out the email does eventually send after 2-3 minutes. It seems as though it is being queued by the exchange server, or the SmtpClient connection eventually times out and is closed by the server.

Edit:

I have tried.

client.ServicePoint.ConnectionLeaseTimeout = 1;
client.ServicePoint.MaxIdleTime = 1;
+2  A: 

A possible cause is that the connection is being kept open. Try closing the connection at the end of the Send method and see if that works.

Laplace
I don't believe SMTPClient inherits IDisposable nor does it have a close connection method. So I don't think this is possible.
icemanind
SMTPClient Does not have a Dispose or Close method, despite what the documentation says. I have tried to call Dispose(), but the code will not compile.
Tester101
Yeah it will not compile because it does not implement IDisposable, meaning there is no Dispose() method.
icemanind
How annoying. I see you tried the time out trick, have you tried setting it to 1 instead of 0 and seeing if that properly closes the socket?
Laplace
@Laplace: yes I have used 1 and a few other low values.
Tester101
+3  A: 

I am betting you have Norton Antivirus installed. This seems to be a known issue with Norton Antivirus. You can fix this by opening Norton antivirus and disabling the email tools. Let me know if that works for you.

icemanind
This is not a practical solution.
Tester101
Maybe not but it is definately the cause of this issue
icemanind
So the solution would be to tell all clients to shut off their antivirus? seems like there must be a better option.
Tester101
I'm not saying that. All I am saying is that the code you posted works fine. From a coding standpoint, your program works! As far as norton goes, you need to find a solution to that program. That is a separate issue then this one.
icemanind
Fair enough. So the solution is to get a job with Norton and fix their code. haha. Thanks for your help.
Tester101
lol I reposted a new answer down below. Try it out and see if it fixes the problem your having.
icemanind
A: 

Also, for any disposable types like System.Net.Mail.MailMessage you should used a "using" block:

public void Send() 
{ 
    using (System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(this.From, this.To, this.Subject, this.Body))
    {
        message.IsBodyHtml = true; 
        System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(this.Server); 
        client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; 
        try  
        { 
            client.Send(message); 
        }   
        catch(System.Exception ex)  
        { 
            System.Windows.Forms.MessageBox.Show(ex.ToString());               
        }
    } 
} 
ShellShock
This is not production code, it was just typed up to demonstrate the problem. But yes I do use using most of the time, but this does not solve the problem in this situation.
Tester101
A: 

System.Net.Mail.MailMessage and System.Net.Mail.SmtpClient both implement IDisposable, which means that you need to call Dispose on them after you're done. IE:

using (System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(this.From, this.To, this.Subject, this.Body))
{
    message.IsBodyHtml = true; 
    using(System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(this.Server))
    {
        client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; 
        try  
        { 
            client.Send(message); 
        }   
        catch(System.Exception ex)  
        { 
            System.Windows.Forms.MessageBox.Show(ex.ToString());               
        }
    }
} 
JSBangs
As mentioned before SmtpClient DOES NOT implement IDisposable
Tester101
@Tester101: Yes it does. I just made and compiled a project that calls `SmtpClient.Dispose`, and I verified in the metadata that `IDisposable` is properly implemented. Something else is going on.
JSBangs
Wait--the `IDisposable` interface wasn't added until 4... 3.5 and earlier don't have it.
JSBangs
So updating to version 4 would solve the problem?
Tester101
@Tester, it probably would.
JSBangs
A: 

ok Tester...If you want to get around the Norton Issue, its pretty simple. Add the following line:

message.EnableSsl = true;

This will cause the smtp client to encrypt your connection, thus sending it on a different port then what norton monitors. See if that works!

icemanind
System.Net.Mail.MailMessage does not have an EnableSsl property, but setting the SmtpClient's EnableSsl property to true reveled that the sever does not support secure connections.
Tester101
Sure is a head scratcher. Without disabling norton or using SSL, I'm not sure how this can work. But I will find a solution. Give me a few
icemanind
Is there a way to register my application with Norton or something, so it does not scan messages sent by it?
Tester101
Well that's not really the issue. What's going on is .NET 2.0 - .NET 3.5 does not implement a dispose() method. A proper dispose() method should send a QUIT command to the smtp server and this would be when Norton would send it. Microsoft fixed this with .NET 4.0. So one solution may be to upgrade your project to .NET 4.0. If this is not possible, another possibility is to use a 3rd party SMTP control.
icemanind
It turns out the message does eventually send after 2-3 minutes. Any thoughts on this behavior?
Tester101
@icemanind: Thanks for the help, I found the solution.
Tester101
+1  A: 

I finally; after all the help from StackOverflow and other various research sources, have found the solution. By setting System.Net.ServicePointManager.MaxServicePointIdleTime = 1, the mail is sent immediately.

Here is the final code.

public class EMail
{
    private string server;
    public string Server {get{return this.server;}set{this.server = value;}}
    private string to;
    public string To {get{return this.to;}set{this.to = value;}}
    private string from;
    public string From {get{return this.from;}set{this.from = value;}}
    private string subject;
    public string Subject {get{return this.subject;}set{this.subject = value;}}
    private string body;
    public string Body {get{return this.body;}set{this.body = value;}}

    public EMail()
    {}
    public EMail(string _server, string _to, string _from, string _subject, string _body)
    {
        this.Server = _server;
        this.To = _to;
        this.From = _from;
        this.Subject = _subject;
        this.Body = _body;
    }   

    public void Send()
    {
        using(System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(this.From, this.To, this.Subject, this.Body))
        {        
            message.IsBodyHtml = true;
            System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(this.Server);
            client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;

            int temp = System.Net.ServicePointManager.MaxServicePointIdleTime; //<- Store the original value.
            System.Net.ServicePointManager.MaxServicePointIdleTime = 1; //<- Change the idle time to 1.

            try 
            {
                client.Send(message);
            }  
            catch(System.Exception ex) 
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString());              
            }
            finally
            {
                System.Net.ServicePointManager.MaxServicePointIdleTime = temp; //<- Set the idle time back to what it was.
            }
        }
    }
}

Thank you all for your help! Especially icemanind.

Tester101