Подтвердить что ты не робот

.NET Лучший способ отправки электронной почты (System.Net.Mail имеет проблемы)

Это кажется довольно прямым. Мне нужно отправить электронное письмо из некоторых приложений ASP.NET. Мне нужно сделать это последовательно без странных ошибок и без использования процессора, проходящего через крышу. Я не говорю о массовом рассылке по электронной почте, просто по электронной почте.

System.Net.Mail выглядит ужасно нарушенным. SmtpClient не выполняет команду Quit (возможно, Microsoft (R) не интересуется следующими спецификациями), поэтому соединение остается открытым. Поэтому, если кто-то пытается отправить сообщение по электронной почте до этого соединения наконец, вы можете получить ошибки с SMTP-сервера относительно слишком большого количества подключений. Это ошибка, по которой Microsoft (R) полностью не заинтересована в исправлении. См. Здесь:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=146711

Кроме того, если вы посмотрите вокруг, предложите использовать этот код для решения этой проблемы:

smtpClient.ServicePoint.MaxIdleTime = 1;
smtpClient.ServicePoint.ConnectionLimit = 1;

Хорошо, да, что "решает" проблему закрытия соединений. Тем не менее, это последовательно, попробуйте на сервере, если хотите, вызывает процессор, на котором выполняется процесс (в данном случае w3wp.exe), для перехода и остаётся на уровне 100%, пока ваш пул приложений не будет повторно использован. По какой-то причине причиной является поток, запускающий mscorwks.dll! CreateApplicationContext.

Это имеет очень хороший побочный эффект: если вы работаете на веб-хостинге, который хмурится устойчивым 100% -ным использованием ЦП, вы отключите свой пул приложений. Так что это не так тривиально, как предлагают некоторые.

Итак, мой вопрос - что делать? Что мне нужно сделать, так просто; однако получение этих ошибок "слишком много подключений открыто" неприемлемо и не является 100% -ным использованием ЦП. Я не хочу покупать сторонний компонент, а не потому, что я дешевый, но я покупаю достаточно компонентов и подписку на MSDN, что кажется сумасшедшим, чтобы выложить $100-300 за простую функциональность SMTP.

Я читал, что настройка MaxIdleTime выше может помочь, но я скептически отношусь к этому. Я не хочу, чтобы мой пул приложений был отключен только потому, что Microsoft не хочет следовать спецификации SMTP.

Изменить: Я смотрел на компоненты quiksoft.com, однако он не поддерживает аутентификацию SMTP и стоит 500 долларов. Должно быть решение этой проблемы.

4b9b3361

Ответ 1

Я столкнулся с такой же проблемой использования ЦП с описанными настройками. В итоге я открыл билет с Microsoft, чтобы определить причину проблемы. Проблема использования ЦП лежит в классе ServicePoint. Внутри класса ServicePoint есть таймер, который запускает каждую (MaxIdleTime/2) миллисекунды. См. Проблему? Изменив значение MaxIdleTime на 2, загрузка процессора снизится до нормального уровня.

Ответ 2

В .NET 4.0 SmtpClient теперь доступен. Команда SMTP QUIT выдается после удаления, например, при использовании в используемом блоке.

Ответ 3

Я всегда использовал компоненты Quiksoft EasyMail.NET без каких-либо проблем.

Домашняя страница продукта: http://www.quiksoft.com/emdotnet/

У них также есть бесплатная версия компонента, если вам нужно только отправлять электронные письма:

http://www.quiksoft.com/freesmtp/

Ответ 4

Мы с большим успехом использовали hMailserver. Конфигурация может занять некоторое время, чтобы привыкнуть, но это был отличный и бесплатный почтовый сервер.

Если вы хотите перевернуть свой собственный (что я сделал много лет назад, когда у меня был медведь времени с CDONTS), вы можете начать с кода ниже и настроить его на содержание вашего сердца. Он использует TcpClient для создания TCP-соединения непосредственно с почтовым сервером. Не то, чтобы я рекомендовал это, когда было так много установленных и отлаженных решений, но я нашел, что это очень полезно для отладки и определения того, где проблема связана с почтовыми компонентами сборной MS.

    private void Send_Email() 
    {
        #region Email Sending Function
        string strMail = "";

        try 
        {
            // See RFC821 http://www.faqs.org/rfcs/rfc821.html for more specs
            // TcpClient is an abstraction of a TCP Socket connection
            TcpClient myTCP = new TcpClient();

            // Connect to the mail server port 25
            myTCP.Connect(mailserver, 25);

            // Open a network stream which sends data to/from the TcpClient socket
            System.Net.Sockets.NetworkStream ns = myTCP.GetStream();

            // The data to send to the mail server, basically a raw SMTP mail message
            strMail = "HELO\n";
            strMail += "MAIL FROM:[email protected]\n";
            strMail += "RCPT TO:" + recipient + "\n";
            strMail += "DATA\n";
            strMail += "Subject: mySubject\n";
            strMail += "To:" + recipient + "\n";
            strMail += "From: \"From Real Name\" <[email protected]>\n";
            strMail += "\n";
            strMail += " ---------------------------------------\n";
            strMail += "Name:     " + txtName.Text + "\n";
            strMail += "Address1: " + txtAddress1.Text + "\n";
            strMail += "Address2: " + txtAddress2.Text + "\n";
            strMail += "City:     " + txtCity.Text + "\n";
            strMail += "State:    " + txtState.Text + "\n";
            strMail += "Zip:      " + txtZip.Text + "\n";
            strMail += "Email:    " + txtEmail.Text + "\n";
            strMail += "Dealer:   " + txtDealer.Text + "\n";
            strMail += " ---------------------------------------\n";
            strMail += "THIS IS AN AUTOMATED EMAIL SYSTEM. DO NOT REPLY TO THIS ADDRESS.\n";
            strMail += "\n.\n";

            // Defines encoding of string into Bytes (network stream needs
            // an array of bytes to send -- can't send strings)
            ASCIIEncoding AE = new ASCIIEncoding();
            byte[] ByteArray = AE.GetBytes(strMail);

            // send the byte-encoded string to the networkstream -> mail server:25
            ns.Write(ByteArray, 0, ByteArray.Length);

            //ns.Read(ByteArray, 0, ByteArray.Length);
            //lblStatus.Text = ByteArray.ToString();

            // close the network stream
            ns.Close();

            // close the TCP connection
            myTCP.Close();
        }
        catch(Exception ex) 
        {
            throw new Exception("Couldn't send email: <p>" + ex.Message);
        }

        #endregion

    }

Ответ 5

Пока у меня не было особых проблем с System.Net.Mail, вы всегда можете использовать более старый System.Web.Mail API, который является оберткой для CDOSYS.

Ответ 6

Я использовал Quicksoft в прошлом и не имею жалоб. Еще одна вещь, которую вы можете попробовать - переключить конфигурацию SMTP, чтобы использовать папку с пикапом вместо отправки с использованием сети, которая должна обойти проблему "не отправлять QUIT".

Ответ 7

Я отправляю большую часть своей почты с помощью Sproc. Я даже могу прикрепить файл.

CREATE PROCEDURE [dbo].[sendMail_With_CDOMessage]  
    @to VARCHAR(64), 
    @CC VARCHAR(1024)='',
    @BCC VARCHAR(1024)='',
    @subject VARCHAR(500)='', 
    @body VARCHAR(8000)='' ,
    @from VARCHAR(64),
    @filename VARCHAR(255)='',
    @priority INT = 0
AS  
BEGIN  
    SET NOCOUNT ON  

    DECLARE  
        @handle INT,  
        @return INT,  
        @s VARCHAR(64),  
        @sc VARCHAR(1024),  
        @up CHAR(27),   
        @server VARCHAR(255)  

    SET @s = '"http://schemas.microsoft.com/cdo/configuration/'  

    SELECT  
        @s = 'Configuration.Fields(' + @s,  
        @up = 'Configuration.Fields.Update',
        @server = 'smtp.yourdomain.com' 



    EXEC @return = sp_OACreate 'CDO.Message', @handle OUT  
    SET @sc = @s + 'sendusing").Value'  
    EXEC @return = sp_OASetProperty @handle, @sc, '2'  
    SET @sc = @s + 'smtpserver").Value'  
    EXEC @return = sp_OASetProperty @handle, @sc, @server  
    EXEC @return = sp_OAMethod @handle, @up, NULL  
    EXEC @return = sp_OASetProperty @handle, 'To', @to  
    EXEC @return = sp_OASetProperty @handle, 'CC', @CC 
    EXEC @return = sp_OASetProperty @handle, 'BCC', @BCC 
    EXEC @return = sp_OASetProperty @handle, 'From', @from  
    EXEC @return = sp_OASetProperty @handle, 'Subject', @subject  
    EXEC @return = sp_OASetProperty @handle, 'HTMLBody', @body    
    EXEC @return = sp_OASetProperty @handle, 'Priority', 'cdoHigh'  

    IF @filename IS NOT NULL  
        EXEC @return = sp_OAMethod @handle, 'AddAttachment', NULL, @filename  

    EXEC @return = sp_OAMethod @handle, 'Send', NULL  
    IF @return  0  
    BEGIN  
        PRINT 'Mail failed.'  
        IF @from IS NULL  
            PRINT 'From address undefined.'  
        ELSE  
            PRINT 'Check that server is valid.' 
    END 
    ELSE  
        PRINT 'Mail sent.'  

    EXEC @return = sp_OADestroy @handle  
END