Pergunta

Este parece ser bastante simples. Eu preciso enviar e-mail a partir de algumas aplicações ASP.NET. Eu preciso fazer isso de forma consistente, sem erros estranhos e sem a utilização da CPU atravessando o telhado. Eu não estou falando de e-mail em massa, e-mails apenas ocasionais.

System.Net.Mail aparece para ser horrivelmente quebrado. faz o SmtpClient não emitir o comando Quit (pode ser porque o Microsoft (R) não está interessado em seguintes especificações), portanto, uma conexão é deixada em aberto. Portanto, se alguém tenta enviar e-mail antes que conexão finalmente fecha, você pode obter erros do servidor SMTP sobre muitas conexões abrir. Este é um bug que a Microsoft (R) é completamente desinteressado na fixação. Veja aqui:

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

Além disso, se você olhar em volta alguns sugerem usar este código para resolver este problema:

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

Ok, sim, que significa "resolver" o problema de conexões sendo deixada em aberto. No entanto, isso de forma consistente, experimentá-lo em um servidor, se quiser, faz com que a CPU na qual o processo (neste caso w3wp.exe) está sendo executado para saltar e permanecem em 100% até o seu pool de aplicativos é reciclado. Por alguma razão, o fio que corre MSCORWKS.DLL! CreateApplicationContext é o culpado.

Isto tem o efeito colateral muito agradável que, se você estiver executando em um host que franze a testa sobre o uso da CPU sustentada 100%, você vai ter o seu pool de aplicativos desativado. Então isso não é tão trivial como alguns sugerem.

Então, minha pergunta é o que fazer? O que eu preciso fazer é tão simples; no entanto obter essas "muitas conexões abertas" erros não é aceitável e nem é o uso de CPU de 100%. Eu não quero comprar um componente de terceiros, não porque eu sou barato, mas eu comprar suficientes componentes e assinatura do MSDN que parece loucura ter que desembolsar US $ 100- $ 300 para a funcionalidade SMTP simples.

Eu li que a configuração da MaxIdleTime maior pode ajudar, mas eu sou cético em relação a isso. Eu não quero arriscar meu pool de aplicativo que está sendo desativada só porque a Microsoft não quer seguir a especificação do SMTP.

Editar: Eu olhei para quiksoft.com componentes, no entanto, ele não suporta a autenticação SMTP e custa US $ 500. Tem que ser uma solução para este problema.

Foi útil?

Solução

I enfrentou o mesmo problema de utilização da CPU com as configurações descritas. Acabei de abrir um ticket com a Microsoft para determinar a causa do problema. O problema a utilização da CPU está na classe ServicePoint. Internamente na classe ServicePoint, há um temporizador que sai a cada (MaxIdleTime / 2) milissegundos. Ver o problema? Alterando o valor MaxIdleTime a 2, a utilização da CPU irá cair para níveis normais.

Outras dicas

Em .NET 4.0, SmtpClient agora é descartável. O SMTP QUIT comando é emitido quando da alienação tal como quando usado em um bloco usando.

Eu sempre usei componentes do Quiksoft EasyMail .NET sem problemas em tudo.

Produtos home page: http://www.quiksoft.com/emdotnet/

Eles também têm uma versão gratuita do componente se você só precisa enviar e-mails:

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

Temos usado hMailServer com grande sucesso. A configuração pode demorar um pouco para se acostumar, mas ele tem sido um grande - e gratuita -. Correio produto de servidor

Se você desejar construir sua própria (que eu fiz anos atrás, quando eu estava tendo um urso de um tempo com CDONTS), você pode começar com o código abaixo e personalização para o conteúdo do seu coração. Ele usa o TcpClient para criar uma conexão TCP diretamente para o servidor de correio. Não que eu recomendo este quando há tantas soluções estabelecidas e depurado, mas eu achei isso muito útil para depuração e determinar onde o problema era com os componentes pré-fabricada de correio 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's port 25
            myTCP.Connect(mailserver, 25);

            // Open a network stream which sends data to/from the TcpClient's 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:from@address.com\n";
            strMail += "RCPT TO:" + recipient + "\n";
            strMail += "DATA\n";
            strMail += "Subject: mySubject\n";
            strMail += "To:" + recipient + "\n";
            strMail += "From: \"From Real Name\" <from@address.com>\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

    }

Enquanto eu não tive quaisquer problemas específicos com System.Net.Mail até agora, você sempre pode usar o velho System.Web.Mail API que é um wrapper para CDOSYS.

Eu usei Quicksoft no passado e não tenho queixas. Outra coisa que você pode tentar é mudar a configuração SMTP para usar uma pasta de retirada em vez de enviar usando a rede que deve começar em torno do "ele não envia SAIR" a questão.

I enviar a maioria de meu e-mail usando um Sproc. Eu até posso anexar um arquivo.

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  

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top