Domanda

Questo sembra essere piuttosto semplice. Ho bisogno di inviare e-mail da alcune applicazioni ASP.NET. Ho bisogno di fare questo in modo coerente, senza strani errori e senza l'utilizzo della CPU passare attraverso il tetto. Non sto parlando di mail di massa, messaggi di posta elettronica solo occasionali.

System.Net.Mail appare di essere orribilmente rotto. Lo SmtpClient non emette il comando Quit (può essere perché Microsoft (R) non è interessato a seguire le specifiche), quindi una connessione viene lasciata aperta. Pertanto, se qualcuno cerca di posta elettronica prima che il collegamento infine chiude, è possibile ottenere gli errori del server SMTP circa troppe connessioni aperte. Questo è un bug che Microsoft (R) è completamente disinteressato di fissaggio. Vedi qui:

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

Inoltre, se si guarda intorno un po 'di suggerire di utilizzare questo codice per risolvere questo problema:

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

Ok, sì che significa "risolvere" il problema dei collegamenti essere lasciata aperta. Tuttavia, questo in modo coerente, provare su un server, se vi piace, fa sì che la CPU su cui il processo (in questo caso w3wp.exe) sia in esecuzione a saltare e rimanere al 100% fino a quando il pool di applicazioni viene riciclato. Per qualsiasi motivo, il filo che corre mscorwks.dll! CreateApplicationContext è il colpevole.

Questo ha l'molto piacevole effetto collaterale che se si esegue su un host web che aggrotta la fronte dell'utilizzo sostenibile al 100% della CPU, avrete il vostro pool di applicazioni disabilitato. Quindi questo non è così banale come alcuni suggeriscono.

Quindi la mia domanda è che cosa fare? Quello che devo fare è così semplice; tuttavia ottenere quei "troppe connessioni aperte" errori non è accettabile e non è l'utilizzo della CPU al 100%. Non voglio acquistare un componente di terze parti, non perché sono a buon mercato, ma compro abbastanza componenti e abbonamento MSDN che sembra folle a sborsare $ 100- $ 300 per la funzionalità SMTP semplice.

Ho letto che l'impostazione del MaxIdleTime superiore può aiutare ma io sono scettico di questo. Non voglio rischiare la mia piscina app essere disattivato solo perché Microsoft non vuole seguire la specifica SMTP.

Modifica Ho guardato componenti quiksoft.com, tuttavia non supporta l'autenticazione SMTP e costa 500 $. Ci deve essere una soluzione a questo problema.

È stato utile?

Soluzione

Ho affrontato lo stesso problema di utilizzo della CPU con le impostazioni descritte. Ho finito per l'apertura di un biglietto con Microsoft per determinare la causa del problema. Il problema di utilizzo della CPU risiede nella classe ServicePoint. Internamente nella classe ServicePoint, c'è un timer che passa ogni (MaxIdleTime / 2) millisecondi. Vedere il problema? Modificando il valore MaxIdleTime a 2, l'utilizzo della CPU scenderà a livelli normali.

Altri suggerimenti

In .NET 4.0, SmtpClient è ora usa e getta. SMTP QUIT comando viene emesso al momento della dismissione come quando utilizzato in un blocco utilizzando.

Ho sempre usato i componenti del Quiksoft EasyMail .NET senza problemi a tutti.

home page del prodotto: http://www.quiksoft.com/emdotnet/

Essi hanno anche una versione gratuita del componente, se avete solo bisogno di inviare e-mail:

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

Abbiamo usato hMailServer con grande successo. La configurazione può prendere un po 'per abituarsi, ma è stato un grande - e gratuito -. Prodotto server di posta elettronica

Se si desidera ripristinare il proprio (che ho fatto anni fa, quando ho avuto un orso di un tempo con CDONTS), si può iniziare con il codice qui sotto e personalizzare a vostro piacimento. Esso utilizza il TcpClient per creare una connessione TCP direttamente al server di posta. Non che io consiglierei questo quando ci sono così tante soluzioni consolidate e il debug, ma ho trovato questo molto utile per il debug e determinare dove il problema era con i componenti di posta MS prefabbricate.

    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

    }

Anche se non ho avuto problemi specifici con System.Net.Mail finora, si può sempre utilizzare il più vecchio System.Web.Mail API che è un involucro per CDOSYS.

Ho usato Quicksoft in passato e non ho lamentele. Un'altra cosa che si può provare è il passaggio dalla configurazione SMTP per utilizzare una cartella di prelievo invece di inviare utilizzando la rete che dovrebbe aggirare il problema "non invia QUIT".

mando la maggior parte della mia posta utilizzando uno Sproc. Posso anche allegare un file.

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  

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top