Письмо не отправляется до закрытия приложения

У меня есть приложение, которое использует SmtpClient для отправки электронной почты, но электронные письма не отправляются, пока приложение не закроется. Я искал и искал, чтобы найти решение проблемы, но я не могу его найти.

В системе установлен антивирус Symantec, что может быть проблемой.

У кого-нибудь есть решение этой проблемы?

Вот код, который я использую.

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());              
            }
        }
    }
}

Изменить:

Оказывается, электронная почта в конечном итоге отправляется через 2-3 минуты. Кажется, что он поставлен в очередь сервером обмена или соединение SmtpClient в конечном итоге истекает и закрывается сервером.

Изменить:

Я пытался.

client.ServicePoint.ConnectionLeaseTimeout = 1;
client.ServicePoint.MaxIdleTime = 1;

person Tester101    schedule 25.05.2010    source источник


Ответы (6)


Я, наконец; после всей помощи StackOverflow и других различных исследовательских источников мы нашли решение. Установив System.Net.ServicePointManager.MaxServicePointIdleTime = 1, почта будет отправлена ​​немедленно.

Вот окончательный код.

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.
            }
        }
    }
}

Спасибо за вашу помощь! Особенно ледяной человек.

person Tester101    schedule 26.05.2010

Возможной причиной является то, что соединение остается открытым. Попробуйте закрыть соединение в конце метода Send и посмотрите, работает ли это.

Изменить: похоже, это имеет место в .NET 4.0 теперь, когда SmtpClient реализует IDispose.

person Laplace    schedule 25.05.2010
comment
Я не верю, что SMTPClient наследует IDisposable и не имеет метода близкого соединения. Поэтому я не думаю, что это возможно. - person Icemanind; 25.05.2010
comment
SMTPClient не имеет метода Dispose или Close, несмотря на то, что говорится в документации. Я пытался вызвать Dispose(), но код не компилируется. - person Tester101; 25.05.2010
comment
Да, он не скомпилируется, потому что не реализует IDisposable, то есть нет метода Dispose(). - person Icemanind; 25.05.2010
comment
Как раздражает. Я вижу, вы пробовали трюк с тайм-аутом, пытались ли вы установить его на 1 вместо 0 и посмотреть, правильно ли это закрывает сокет? - person Laplace; 25.05.2010

Могу поспорить, что у вас установлен Norton Antivirus. Похоже, это известная проблема с Norton Antivirus. Вы можете исправить это, открыв антивирус Norton и отключив инструменты электронной почты. Дайте мне знать, если это работает для вас.

person Icemanind    schedule 25.05.2010
comment
Это не практическое решение. - person Tester101; 25.05.2010
comment
Может быть, нет, но это определенно причина этой проблемы - person Icemanind; 25.05.2010
comment
Таким образом, решением было бы сказать всем клиентам отключить антивирус? кажется, должен быть лучший вариант. - person Tester101; 25.05.2010
comment
Я этого не говорю. Все, что я говорю, это то, что код, который вы разместили, работает нормально. С точки зрения кодирования ваша программа работает! Что касается нортона, вам нужно найти решение этой программы. Это отдельная тема, тогда эта. - person Icemanind; 25.05.2010
comment
Справедливо. Таким образом, решение состоит в том, чтобы устроиться на работу в Norton и исправить их код. хаха. Спасибо за вашу помощь. - person Tester101; 25.05.2010
comment
лол, я разместил новый ответ ниже. Попробуйте и посмотрите, решит ли это проблему, с которой вы столкнулись. - person Icemanind; 25.05.2010

хорошо, тестер... Если вы хотите обойти проблему с Norton, это довольно просто. Добавьте следующую строку:

message.EnableSsl = true;

Это приведет к тому, что smtp-клиент зашифрует ваше соединение, таким образом отправив его на порт, отличный от того, который отслеживает norton. Посмотрите, работает ли это!

person Icemanind    schedule 25.05.2010
comment
System.Net.Mail.MailMessage не имеет свойства EnableSsl, но установка для свойства EnableSsl SmtpClient значения true показала, что сервер не поддерживает безопасные соединения. - person Tester101; 25.05.2010
comment
Конечно, это головная боль. Без отключения norton или использования SSL я не уверен, как это может работать. Но я найду решение. Дай мне несколько - person Icemanind; 25.05.2010
comment
Есть ли способ зарегистрировать мое приложение в Norton или что-то в этом роде, чтобы оно не сканировало отправленные им сообщения? - person Tester101; 25.05.2010
comment
Ну, это не совсем проблема. Что происходит, так это .NET 2.0 - .NET 3.5 не реализует метод dispose(). Правильный метод dispose() должен отправлять команду QUIT на smtp-сервер, и это будет тогда, когда ее отправит Norton. Microsoft исправила это в .NET 4.0. Таким образом, одним из решений может быть обновление вашего проекта до .NET 4.0. Если это невозможно, другой возможностью является использование стороннего элемента управления SMTP. - person Icemanind; 25.05.2010
comment
Оказывается, сообщение все-таки отправляется через 2-3 минуты. Есть мысли по поводу такого поведения? - person Tester101; 25.05.2010

Кроме того, для любых одноразовых типов, таких как System.Net.Mail.MailMessage, вы должны использовать блок «using»:

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());               
        }
    } 
} 
person Polyfun    schedule 25.05.2010
comment
Это не производственный код, он просто набран для демонстрации проблемы. Но да, я использую using большую часть времени, но это не решает проблему в этой ситуации. - person Tester101; 25.05.2010

System.Net.Mail.MailMessage и System.Net.Mail.SmtpClient оба реализуют IDisposable, а это значит, что вам нужно вызвать для них Dispose после того, как вы закончите. 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());               
        }
    }
} 
person JSBձոգչ    schedule 25.05.2010
comment
Как упоминалось ранее, SmtpClient НЕ реализует IDisposable. - person Tester101; 25.05.2010
comment
@ Tester101: Да, это так. Я только что сделал и скомпилировал проект, который вызывает SmtpClient.Dispose, и проверил в метаданных, что IDisposable реализован правильно. Происходит что-то еще. - person JSBձոգչ; 25.05.2010
comment
Подождите - интерфейс IDisposable не добавлялся до 4... 3.5 и более ранних версий. - person JSBձոգչ; 25.05.2010