SmtpException: nie można odczytać danych z połączenia transportowego: net_io_connectionclosed

103

Korzystam z SmtpClientbiblioteki do wysyłania e-maili za pomocą:

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");

Kod działa dobrze w moim środowisku testowym, ale kiedy używam produkcyjnych serwerów SMTP, kod kończy się niepowodzeniem z komunikatem SmtpException„Niepowodzenie wysyłania poczty”. z wewnętrznym IOException„Nie można odczytać danych z połączenia transportowego: net_io_connectionclosed”.

Potwierdziłem, że zapory nie stanowią problemu. Port otwiera się dobrze między klientem a serwerem. Nie jestem pewien, co jeszcze może spowodować ten błąd.

Jake C.
źródło

Odpowiedzi:

190

EDYCJA: Wersja Super Redux

Spróbuj portu 587 zamiast 465. Port 465 jest przestarzały ze względów technicznych.


Po kilku węszeniu pakietów odkryłem to. Po pierwsze, oto krótka odpowiedź:

.NET obsługuje SmtpClient tylko szyfrowanie przez STARTTLS. Jeśli EnableSslflaga jest ustawiona, serwer musi odpowiedzieć EHLO za pomocą STARTTLS, w przeciwnym razie zgłosi wyjątek. Więcej informacji można znaleźć w dokumentacji MSDN .

Po drugie, krótka lekcja historii SMTP dla tych, którzy napotkają ten problem w przyszłości:

Kiedyś, gdy usługi chciały również oferować szyfrowanie, przydzielano im inny numer portu i na tym porcie natychmiast inicjowały połączenie SSL. W miarę upływu czasu zdali sobie sprawę, że marnowanie dwóch numerów portów na jedną usługę jest głupotą i wymyślili sposób, w jaki usługi zezwalają na zwykły tekst i szyfrowanie na tym samym porcie przy użyciu STARTTLS. Komunikacja rozpocznie się przy użyciu zwykłego tekstu, a następnie użyj polecenia STARTTLS w celu uaktualnienia do połączenia szyfrowanego. STARTTLS stał się standardem dla szyfrowania SMTP. Niestety, jak to zawsze bywa, gdy wdrażany jest nowy standard, istnieje mieszanina kompatybilności ze wszystkimi klientami i serwerami.

W moim przypadku mój użytkownik próbował połączyć oprogramowanie z serwerem, który wymuszał natychmiastowe połączenie SSL, co jest starszą metodą, która nie jest obsługiwana przez firmę Microsoft w .NET.

Jake C.
źródło
po czym mogę sprawdzić, czy serwer, z którym się łączę, ma te same problemy? Próbuję używać SmtpClient z Yahoo i / lub Gmailem i otrzymuję opisany błąd. Kiedy próbuję z serwerem Exchange 2013, mój kod działa dobrze.
raider33
11
Najprostszym sposobem na przetestowanie jest użycie portu 587, a nie 465. Podczas gdy niektóre serwery SMTP obsługują TLS na 465 (a czasem nawet 25), do obsługi TLS wymagany jest tylko port 587. Oprócz tego, korzystanie z portu 465 jest przestarzałe od 1998 r. ( En.wikipedia.org/wiki/SMTPS ), chociaż w praktyce wiele serwerów ma go włączonego dla starszych klientów.
Jake C,
1
Tak, zmiana na 587 załatwiła sprawę. Dzięki za wskazanie mi właściwego kierunku.
raider33
2
587 działa, chociaż smtp.att.yahaoo.com mówi, że użyj 465. Dzięki stary.
Sam
1
Aby uzyskać rzeczywiste rozwiązanie, zobacz stackoverflow.com/a/1014876/247702 na temat korzystania z (przestarzałego) System.Web.Mail, który obsługuje niejawny protokół SSL.
user247702
21

Dla każdego, kto natknie się na ten post w poszukiwaniu rozwiązania i skonfigurowałeś SMTP sendgrid za pośrednictwem platformy Azure.

Nazwa użytkownika nie jest nazwą użytkownika skonfigurowaną podczas tworzenia obiektu sendgrid w lazurowym. Aby znaleźć swoją nazwę użytkownika;

  • Kliknij obiekt sendgrid w kolorze lazurowym i kliknij zarządzaj. Nastąpi przekierowanie do witryny SendGrid.
  • Potwierdź swój adres e-mail, a następnie skopiuj wyświetloną tam nazwę użytkownika. To jest automatycznie wygenerowana nazwa użytkownika.
  • Dodaj nazwę użytkownika z SendGrid do ustawień SMTP w pliku web.config.

Mam nadzieję że to pomoże!

brak loga
źródło
2
Może się to wydawać głupie, ale możesz chcieć sprawdzić, czy hasło jest prawidłowe dla konfiguracji SMTP SendGrid. Nasza konfiguracja pierwotnie działała i pewnego dnia zaczęliśmy otrzymywać komunikat o wyjątku OP. Wyszukiwania w sieci WWW wskazywały głównie na przyjrzenie się innym konfiguracjom serwera SMTP, kiedy ostatecznie okazało się, że hasło jest nieprawidłowe. Ktoś z zespołu zmienił hasło w pliku konfiguracyjnym na takie, w którym pierwsza litera nie była wielka.
methon.dagger,
1
W moim przypadku nazwa użytkownika była niepoprawna i zawierała literówkę. Ale nieprawidłowe hasło może również spowodować wyświetlenie komunikatu „Nie można odczytać danych z połączenia transportowego: net_io_connectionclosed”. błąd. Sprawdź więc zarówno nazwę użytkownika, jak i hasło. W przypadku użytkowników platformy Azure nazwa użytkownika ma postać „[email protected]” (np .: [email protected])
Raj Rao
20

Zmień port z 465 na 587 i będzie działać.

PRZYZNAĆ
źródło
3
Nie jestem pewien, co się stało, ale działa to przy użyciu Gmaila SMTP. czy możesz wyjaśnić, dlaczego to działa?
Kryzmogram
10

Może być też konieczna zmiana ustawienia „mniej bezpieczne aplikacje” na koncie Gmail. EnableSsl, użyj portu 587 i włącz „mniej bezpieczne aplikacje”. Jeśli wyszukujesz w Google mniej bezpieczną część dotyczącą aplikacji, są strony pomocy Google, które prowadzą bezpośrednio do strony Twojego konta. To był mój problem, ale dzięki wszystkim powyższym odpowiedziom wszystko działa.

Bill Mahoney
źródło
Dzięki Bill. To nadal działa z moim standardowym kontem Gmail. Jeśli nie używasz ustawienia „mniej bezpieczne aplikacje”, musisz użyć 2-częściowego uwierzytelniania OAuth2. Nie jest to praktyczne, gdy chcesz po prostu wysłać wiadomość e-mail z potwierdzeniem ze strony internetowej.
Dan Randolph
1
Gdzie jest ustawienie „mniej bezpiecznych aplikacji”. Szukam tego na moim koncie Gmail.
Sam
1
Znalazłem ustawienie „Mniej bezpieczne aplikacje” - nie ma go w ustawieniach Gmaila, ale w ustawieniach konta Google: Moje konto> Logowanie i zabezpieczenia myaccount.google.com/…
HFloyd
9

Wypróbowałem wszystkie powyższe odpowiedzi, ale nadal otrzymuję ten błąd na koncie Office 365. Wydaje się, że kod działa dobrze z kontem Google i smtp.gmail.com, zezwalając na mniej bezpieczne aplikacje.

Jakieś inne sugestie, które mógłbym wypróbować?

Oto kod, którego używam

int port = 587;
string host = "smtp.office365.com";
string username = "[email protected]";
string password = "password";
string mailFrom = "[email protected]";
string mailTo = "[email protected]";
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);
}

AKTUALIZACJA I JAK TO ROZWIĄZAŁEM:

Rozwiązany problem poprzez zmianę klienta Smtp na Mailkit. Klient System.Net.Mail Smtp nie jest obecnie zalecany do używania przez firmę Microsoft ze względu na problemy z bezpieczeństwem i zamiast tego należy używać MailKit. Korzystanie z Mailkit dało mi wyraźniejsze komunikaty o błędach, które mogłem zrozumieć, znajdując główną przyczynę problemu (problem z licencją). Możesz pobrać Mailkit, pobierając go jako pakiet Nuget .

Przeczytaj dokumentację dotyczącą klienta Smtp, aby uzyskać więcej informacji: https://docs.microsoft.com/es-es/dotnet/api/system.net.mail.smtpclient?redirectedfrom=MSDN&view=netframework-4.7.2

Oto jak zaimplementowałem SmtpClient z MailKit

        int port = 587;
        string host = "smtp.office365.com";
        string username = "[email protected]";
        string password = "password";
        string mailFrom = "[email protected]";
        string mailTo = "[email protected]";
        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);
        }
Martin Jaensson
źródło
3

Czy Twoja biblioteka SMTP obsługuje szyfrowane połączenie? Serwer poczty może oczekiwać bezpiecznego połączenia TLS i dlatego może je zamknąć w przypadku braku uzgadniania TLS

1234varun
źródło
To tylko domyślna SmtpClientbiblioteka .NET , obsługuje szyfrowanie, serwer wymaga szyfrowania, a ja ustawiłem client.EnableSssl = true;. Chociaż myślę, że zamierzam to trochę dalej przekonywać w przypadku Wiresharka.
Jake C
3

Jeśli używasz serwera SMTP w tym samym urządzeniu i SMTP jest powiązany z adresem IP zamiast „Dowolne przypisane”, może się nie powieść, ponieważ próbuje użyć adresu IP (np. 127.0.0.1), którego SMTP obecnie nie działa na.

Josiah
źródło
2

Aby podnieść to, o czym żartobliwie wspomniał w komentarzu, robiłem wszystko, o czym wspomniano w tym wątku i wykreślałem ... ponieważ mój był w pętli do powtarzania; po pierwszym przejściu przez pętlę czasami kończyło się niepowodzeniem. Zawsze pracowałem za pierwszym razem przez pętlę.

Dla jasności: pętla obejmuje utworzenie SmtpClient, a następnie wykonanie .Send z odpowiednimi danymi. SmtpClient został utworzony wewnątrz bloku try / catch, aby wychwycić błędy i upewnić się, że obiekt został zniszczony przed końcem pętli.

W moim przypadku rozwiązaniem było upewnienie się, że SmtpClient został usunięty za każdym razem w pętli (za pomocą instrukcji using () lub ręcznie). Nawet jeśli obiekt SmtpClient jest niejawnie niszczony w pętli, wydaje się, że .NET pozostawia rzeczy leżące w pobliżu, aby spowodować konflikt przy następnej próbie.

Andy
źródło
2

Zmień numer portu na 587 z 465

Abdus Salam Azad
źródło
2

usuwanie

client.UseDefaultCredentials = false; 

wydawało się, że rozwiązuje to za mnie.

Goner Doug
źródło
1

W moim przypadku klient zapomniał dodać nowy adres IP w swoich ustawieniach SMTP. Otwórz IIS 6.0 na serwerze, który konfiguruje smtp, kliknij prawym przyciskiem myszy serwer wirtualny Smtp, wybierz Właściwości, zakładka Dostęp, kliknij Połączenia, dodaj adres IP nowego serwera. Następnie kliknij Relay, dodaj także adres IP nowego serwera. To rozwiązało mój problem.

Nora
źródło
0

Spróbuj tego: Oto kod, którego używam do wysyłania e-maili do wielu użytkowników.

 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;
            }
        }
    }
yasmuru
źródło
1
SmtpClientjest również jednorazowego using
użytku
0

W przypadku, gdy wszystkie powyższe rozwiązania nie działają, spróbuj zaktualizować następujący plik na swoim serwerze (przez publikację, mam na myśli, a kompilacja wcześniejsza byłaby pomocna).

bin-> projectname.dll 

Po aktualizacji zobaczysz ten błąd. jak rozwiązałem za pomocą tego rozwiązania.

Ajay Kumar
źródło
1
O dziwo, to zadziałało! Zezwalaj na niezabezpieczone aplikacje były włączone, a port był już ustawiony na 587.
TechyGypo
Dzięki, właśnie zdałem sobie sprawę, że nie byłem jedyny z tym problemem. chętnie pomoże.
Ajay Kumar
0

W przypadku programu Outlook użyj następującego ustawienia, które nie powoduje błędu

Nazwa serwera SMTP smtp-mail.outlook.com

Port SMTP 587

Hisham shahid
źródło
0

Ten błąd jest bardzo ogólny. Może być spowodowany wieloma przyczynami, na przykład nieprawidłowym serwerem poczty. Niektóre firmy hostingowe używają formatu mail.domainname. Jeśli użyjesz tylko nazwy domeny, to nie zadziała. w razie potrzeby sprawdź dane logowania nazwa hosta nazwa użytkownika hasło Skontaktuj się z firmą hostingową.

<smtp from="[email protected]">
        <!-- Uncomment to specify SMTP settings -->
        <network host="domain.com" port="25" password="Jin@" userName="[email protected]"/>
      </smtp>
    </mailSettings>
Jin Thakur
źródło
0

W moim przypadku adres IP serwera WWW został zablokowany na serwerze poczty, musi zostać odblokowany przez firmę hostingową i umieszczony na białej liście. Użyj również portu 587.

Zsolt
źródło
0

Jeśli Twoim serwerem pocztowym jest Gmail (smtp.google.com), ten błąd pojawi się po osiągnięciu limitu wiadomości. Gmail umożliwia wysyłanie przez SMTP tylko do 2000 wiadomości w ciągu 24 godzin.

Evgeny Sobolev
źródło
0

Napotkałem to podczas korzystania z smtp.office365.com, używając portu 587 z SSL. Mogłem zalogować się na konto za pomocą portalu portal.office.com i potwierdzić, że konto ma licencję. Ale kiedy uruchomiłem kod, aby wysłać e-maile, ciągle otrzymywałem błąd net_io_connectionclosed.

Zajęło mi trochę czasu, zanim to rozgryzłem, ale administrator Exchange znalazł winowajcę. Używamy O365, ale serwer Exchange był w środowisku hybrydowym. Chociaż konto, którego próbowaliśmy użyć, było zsynchronizowane z usługą Azure AD i miało ważną licencję O365, z jakiegoś powodu skrzynka pocztowa nadal znajdowała się na hybrydowym serwerze Exchange, a nie na serwerze Exchange online. Po tym, jak administrator giełdy użył polecenia „Move-Mailbox”, aby przenieść skrzynkę pocztową z hybrydowego serwera wymiany do O365, mogliśmy użyć kodu do wysyłania e-maili za pomocą o365.

iki58762
źródło
-1

Przygotowanie: 1. HostA to wirtualny serwer SMTP z domyślnym portem 25 2. HostB to stacja robocza, na której wysyłam pocztę za pomocą SmtpClient i symuluję niestabilną sieć używam niezdarnie

Przypadek 1 podany, jeśli HostB to 2008R2, kiedy wysyłam e-mail. Następnie pojawia się ten problem.

Przypadek 2 podany Jeśli HostB to wersja 2012 lub nowsza Kiedy wysyłam e-mail. Następnie poczta została wysłana.

Wniosek: ta główna przyczyna jest związana z systemem Windows Server 2008R2.

Shawn Wang
źródło