SmtpException: impossibile leggere i dati dalla connessione di trasporto: net_io_connectionclosed


103

Sto usando la SmtpClientlibreria per inviare e-mail utilizzando quanto segue:

SmtpClient client = new SmtpClient();
client.Host = "hostname";
client.Port = 465;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.EnableSsl = true;
client.Credentials = new NetworkCredential("User", "Pass);
client.Send("from@hostname", "to@hostname", "Subject", "Body");

Il codice funziona correttamente nel mio ambiente di test, ma quando utilizzo server SMTP di produzione, il codice non riesce con un SmtpException"Errore durante l'invio della posta". con un interno IOException"Impossibile leggere i dati dalla connessione di trasporto: net_io_connectionclosed".

Ho confermato che i firewall non sono un problema. La porta si apre perfettamente tra il client e il server. Non sono sicuro di cos'altro potrebbe generare questo errore.

Risposte:


190

EDIT: versione Super Redux

Prova la porta 587 invece della 465. La porta 465 è tecnicamente deprecata.


Dopo un sacco di analisi dei pacchetti, l'ho capito. Innanzitutto, ecco la risposta breve:

.NET supporta SmtpClient solo la crittografia tramite STARTTLS. Se il EnableSslflag è impostato, il server deve rispondere a EHLO con un STARTTLS, altrimenti genererà un'eccezione. Vedere la documentazione di MSDN per ulteriori dettagli.

In secondo luogo, una rapida lezione di storia SMTP per coloro che si imbatteranno in questo problema in futuro:

In passato, quando i servizi volevano offrire anche la crittografia, veniva assegnato loro un numero di porta diverso e su quel numero di porta avviavano immediatamente una connessione SSL. Col passare del tempo si sono resi conto che era sciocco sprecare due numeri di porta per un servizio e hanno escogitato un modo per i servizi per consentire il testo in chiaro e la crittografia sulla stessa porta utilizzando STARTTLS. La comunicazione inizierebbe utilizzando il testo normale, quindi utilizzare il comando STARTTLS per eseguire l'aggiornamento a una connessione crittografata. STARTTLS è diventato lo standard per la crittografia SMTP. Sfortunatamente, come sempre accade quando viene implementato un nuovo standard, c'è un miscuglio di compatibilità con tutti i client e server là fuori.

Nel mio caso, il mio utente stava cercando di connettere il software a un server che stava forzando una connessione SSL immediata, che è il metodo legacy non supportato da Microsoft in .NET.


come posso sapere se il server con cui mi sto connettendo ha gli stessi problemi? Sto cercando di usare SmtpClient con yahoo e / o gmail e ottengo l'errore descritto. Quando provo contro un server Exchange 2013, il mio codice funziona bene.
raider33

11
Il modo più semplice per eseguire il test è provare a utilizzare la porta 587 e non la 465. Sebbene alcuni server SMTP supportino TLS su 465 (e talvolta anche su 25), per supportare TLS è necessaria solo la porta 587. In aggiunta a ciò, l'uso della porta 465 è stato deprecato dal 1998 ( en.wikipedia.org/wiki/SMTPS ), sebbene in pratica molti server l'hanno abilitata per i client legacy.
Jake C

1
Sì, il passaggio a 587 ha funzionato. Grazie per avermi indicato la giusta direzione.
raider33

2
587 funziona anche se smtp.att.yahaoo.com dice di usare 465. Grazie amico.
Sam

1
Per una soluzione effettiva, vedere stackoverflow.com/a/1014876/247702 sull'utilizzo di System.Web.Mail (deprecato) che supporta SSL implicito.
user247702

20

Cambia la porta da 465 a 587 e funzionerà.


3
Non sono sicuro di cosa sia successo, ma questo mi funziona usando gmail smtp. puoi spiegare perché funziona?
Crismogramma

20

Per tutti coloro che si imbattono in questo post alla ricerca di una soluzione e hanno configurato sendgrid SMTP tramite Azure.

Il nome utente non è il nome utente che hai impostato quando hai creato l'oggetto sendgrid in azzurro. Per trovare il tuo nome utente;

  • Fare clic sull'oggetto sendgrid in azure e fare clic su gestisci. Verrai reindirizzato al sito SendGrid.
  • Conferma la tua email e poi copia il nome utente visualizzato lì .. è un nome utente generato automaticamente.
  • Aggiungi il nome utente da SendGrid nelle impostazioni SMTP nel file web.config.

Spero che questo ti aiuti!


2
Potrebbe sembrare sciocco, ma qualcos'altro che potresti voler controllare è se la password è corretta per la configurazione di SendGrid SMTP. Inizialmente la nostra configurazione funzionava e poi un giorno abbiamo iniziato a ricevere il messaggio di eccezione dell'OP. Le ricerche sul WWW puntavano principalmente a guardare altre configurazioni del server SMTP quando alla fine si è scoperto che la password non era corretta. Qualcuno nel team aveva cambiato la password nel file di configurazione con una variazione in cui la prima lettera non era maiuscola.
methon.dagger

1
Nel mio caso il nome utente non era corretto e aveva un errore di battitura. Ma una password errata può anche dare il messaggio "Impossibile leggere i dati dalla connessione di trasporto: net_io_connectionclosed". errore. Quindi controlla sia il nome utente che la password. E per gli utenti di Azure, il nome utente è nel formato "azure_guid-withoutdashes@azure.com" (ad esempio: azure_e9e062db4bfd491296bec77bcff49ed9@azure.com)
Raj Rao

10

Potrebbe anche essere necessario modificare l'impostazione "app meno sicure" nel tuo account Gmail. EnableSsl, usa la porta 587 e abilita le "app meno sicure". Se cerchi su Google la parte delle app meno sicure, ci sono pagine della guida di Google che ti collegheranno direttamente alla pagina del tuo account. Questo era il mio problema, ma ora funziona tutto grazie a tutte le risposte sopra.


Grazie Bill. Funziona ancora con il mio account Gmail standard. Se non utilizzi l'impostazione "app meno sicure", devi utilizzare l'autenticazione in due parti OAuth2. Ciò non è pratico quando si desidera inviare solo un'e-mail di conferma da un sito Web.
Dan Randolph

1
Dove si trovano le "app meno sicure". Sto cercando nel mio account Gmail.
Sam

1
Ho individuato l'impostazione "App meno sicure": non si trova nelle impostazioni di Gmail, ma nelle impostazioni dell'account Google: Account personale> Accesso e sicurezza myaccount.google.com/…
HFloyd

9

Ho provato tutte le risposte sopra ma ricevo ancora questo errore con l'account di Office 365. Il codice sembra funzionare bene con l'account Google e smtp.gmail.com quando si autorizzano app meno sicure.

Qualche altro suggerimento che potrei provare?

Ecco il codice che sto usando

int port = 587;
string host = "smtp.office365.com";
string username = "smtp.out@mail.com";
string password = "password";
string mailFrom = "noreply@mail.com";
string mailTo = "to@mail.com";
string mailTitle = "Testtitle";
string mailMessage = "Testmessage";

using (SmtpClient client = new SmtpClient())
{
    MailAddress from = new MailAddress(mailFrom);
    MailMessage message = new MailMessage
    {
        From = from
    };
    message.To.Add(mailTo);
    message.Subject = mailTitle;
    message.Body = mailMessage;
    message.IsBodyHtml = true;
    client.DeliveryMethod = SmtpDeliveryMethod.Network;
    client.UseDefaultCredentials = false;
    client.Host = host;
    client.Port = port;
    client.EnableSsl = true;
    client.Credentials = new NetworkCredential
    {
        UserName = username,
        Password = password
    }; 
    client.Send(message);
}

AGGIORNAMENTO E COME L'HO RISOLTO:

Problema risolto cambiando Smtp Client in Mailkit. Il client System.Net.Mail Smtp non è ora consigliato da Microsoft a causa di problemi di sicurezza e dovresti invece usare MailKit. L'uso di Mailkit mi ha fornito messaggi di errore più chiari che potevo capire trovando la causa principale del problema (problema di licenza). Puoi ottenere Mailkit scaricandolo come pacchetto Nuget .

Leggere la documentazione sul client Smtp per ulteriori informazioni: https://docs.microsoft.com/es-es/dotnet/api/system.net.mail.smtpclient?redirectedfrom=MSDN&view=netframework-4.7.2

Ecco come ho implementato SmtpClient con MailKit

        int port = 587;
        string host = "smtp.office365.com";
        string username = "smtp.out@mail.com";
        string password = "password";
        string mailFrom = "noreply@mail.com";
        string mailTo = "mailto@mail.com";
        string mailTitle = "Testtitle";
        string mailMessage = "Testmessage";

        var message = new MimeMessage();
        message.From.Add(new MailboxAddress(mailFrom));
        message.To.Add(new MailboxAddress(mailTo));
        message.Subject = mailTitle;
        message.Body = new TextPart("plain") { Text = mailMessage };

        using (var client = new SmtpClient())
        {
            client.Connect(host , port, SecureSocketOptions.StartTls);
            client.Authenticate(username, password);

            client.Send(message);
            client.Disconnect(true);
        }

3

La tua libreria SMTP supporta la connessione crittografata? Il server di posta potrebbe aspettarsi una connessione TLS sicura e quindi chiudere la connessione in assenza di handshake TLS


È solo la SmtpClientlibreria .NET predefinita , supporta la crittografia, il server richiede la crittografia e ho impostato client.EnableSssl = true;. Anche se penso che lo approfondirò ancora un po 'con Wireshark.
Jake C

3

Se stai utilizzando un server SMTP sulla stessa casella e il tuo SMTP è associato a un indirizzo IP invece di "Qualsiasi assegnato" potrebbe non riuscire perché sta cercando di utilizzare un indirizzo IP (come 127.0.0.1) che SMTP non funziona attualmente sopra.


2

Per elevare ciò che Jocull ha menzionato in un commento, stavo facendo tutto ciò che è menzionato in questo thread e colpendo ... perché il mio era in un ciclo per essere eseguito più e più volte; dopo la prima volta attraverso il ciclo, a volte falliva. Ha sempre funzionato la prima volta attraverso il ciclo.

Per essere chiari: il ciclo include la creazione di SmtpClient e quindi l'esecuzione di .Invia con i dati giusti. Lo SmtpClient è stato creato all'interno di un blocco try / catch, per rilevare gli errori e per essere sicuri che l'oggetto sia stato distrutto prima della fine del ciclo.

Nel mio caso, la soluzione era assicurarsi che SmtpClient fosse eliminato dopo ogni volta nel ciclo (tramite l'istruzione using () o eseguendo uno smaltimento manuale). Anche se l'oggetto SmtpClient viene implicitamente distrutto nel ciclo, .NET sembra lasciare cose in giro per entrare in conflitto con il tentativo successivo.



2

rimozione

client.UseDefaultCredentials = false; 

sembrava risolverlo per me.


1

Nel mio caso, il cliente ha dimenticato di aggiungere un nuovo indirizzo IP nelle proprie impostazioni SMTP. Apri IIS 6.0 nel server che configura smtp, fai clic con il pulsante destro del mouse sul server virtuale Smtp, scegli Proprietà, scheda Accesso, fai clic su Connessioni, aggiungi l'indirizzo IP del nuovo server. Quindi fare clic su Relay, aggiungere anche l'indirizzo IP del nuovo server. Questo ha risolto il mio problema.


0

Prova questo: ecco il codice che sto usando per inviare e-mail a più utenti.

 public string gmail_send()
    {
        using (MailMessage mailMessage =
        new MailMessage(new MailAddress(toemail),
    new MailAddress(toemail)))
        {
            mailMessage.Body = body;
            mailMessage.Subject = subject;
            try
            {
                SmtpClient SmtpServer = new SmtpClient();
                SmtpServer.Credentials =
                    new System.Net.NetworkCredential(email, password);
                SmtpServer.Port = 587;
                SmtpServer.Host = "smtp.gmail.com";
                SmtpServer.EnableSsl = true;
                mail = new MailMessage();
                String[] addr = toemail.Split(','); // toemail is a string which contains many email address separated by comma
                mail.From = new MailAddress(email);
                Byte i;
                for (i = 0; i < addr.Length; i++)
                    mail.To.Add(addr[i]);
                mail.Subject = subject;
                mail.Body = body;
                mail.IsBodyHtml = true;
                mail.DeliveryNotificationOptions =
                    DeliveryNotificationOptions.OnFailure;
                //   mail.ReplyTo = new MailAddress(toemail);
                mail.ReplyToList.Add(toemail);
                SmtpServer.Send(mail);
                return "Mail Sent";
            }
            catch (Exception ex)
            {
                string exp = ex.ToString();
                return "Mail Not Sent ... and ther error is " + exp;
            }
        }
    }

1
SmtpClientè anche usa e getta, quindi dovrebbe essere avvolto in un usingblocco
jocull

0

Nel caso in cui tutte le soluzioni di cui sopra non funzionassero per te, prova ad aggiornare il seguente file sul tuo server (per pubblicazione intendo, e una build precedente sarebbe utile).

bin-> projectname.dll 

Dopo l'aggiornamento vedrai questo errore. come ho risolto con questa soluzione.


1
Sorprendentemente questo ha funzionato per me! Consenti app non sicure era attivo e la porta era già impostata su 587.
TechyGypo

Grazie, ho appena capito che non ero l'unico con questo problema. felice di aiutare.
Ajay Kumar

0

Per Outlook utilizzare la seguente impostazione che non mi dà errori

Nome del server SMTP smtp-mail.outlook.com

Porta SMTP 587


0

Questo errore è molto generico e può essere dovuto a molti motivi, ad esempio il server di posta non è corretto. Alcune società di hosting utilizzano il formato mail.domainname. Se usi solo il nome di dominio, non funzionerà. controllare le credenziali nome host nome utente password se necessario Verificare con la società di hosting.

<smtp from="info@india.uu.com">
        <!-- Uncomment to specify SMTP settings -->
        <network host="domain.com" port="25" password="Jin@" userName="info@india.xx.com"/>
      </smtp>
    </mailSettings>

0

Nel mio caso l'IP del server web è stato bloccato sul server di posta, deve essere sbloccato dalla tua società di hosting e inserirlo nella whitelist. Inoltre, usa la porta 587.


0

Se il tuo server di posta è Gmail (smtp.google.com), riceverai questo errore quando raggiungi il limite di messaggi. Gmail consente di inviare tramite SMTP fino a solo 2000 messaggi ogni 24 ore.


0

Mi sono imbattuto in questo durante l'utilizzo di smtp.office365.com, utilizzando la porta 587 con SSL. Sono stato in grado di accedere all'account utilizzando portal.office.com e ho potuto confermare che l'account aveva una licenza. Ma quando ho attivato il codice per inviare e-mail, ho continuato a ricevere l'errore net_io_connectionclosed.

Mi ci è voluto del tempo per capirlo, ma l'amministratore di Exchange ha trovato il colpevole. Stiamo usando O365 ma il server Exchange era in un ambiente ibrido. Sebbene l'account che stavamo cercando di utilizzare fosse sincronizzato con Azure AD e avesse una licenza valida per O365, per qualche motivo la cassetta postale risiedeva ancora sul server ibrido di Exchange, non su Exchange online. Dopo che l'amministratore di Exchange ha utilizzato il comando "Move-Mailbox" per spostare la casella di posta dal server di scambio ibrido a O365, potremmo utilizzare il codice per inviare e-mail utilizzando o365.


-1

Preparare: 1. HostA è un server virtuale SMTP con porta predefinita 25 2. HostB è una workstation su cui invio la posta con SmtpClient e simulo una rete instabile che uso goffo

Caso 1 Dato se HostB è 2008R2 quando invio e-mail. Quindi si verifica questo problema.

Caso 2 Dato se HostB è la versione 2012 o successiva quando invio l'email. Quindi la posta è stata spedita.

Conclusione: questa causa principale è correlata a Windows Server 2008R2.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.