SmtpException: невозможно прочитать данные из транспортного соединения: net_io_connectionclosed

105

Я использую SmtpClientбиблиотеку для отправки электронных писем, используя следующее:

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

Код отлично работает в моей тестовой среде, но когда я использую производственные SMTP-серверы, код не работает с сообщением SmtpException«Ошибка отправки почты». с внутренним IOException«Невозможно прочитать данные из транспортного соединения: net_io_connectionclosed».

Я подтвердил, что брандмауэры не проблема. Порт между клиентом и сервером открывается нормально. Я не уверен, что еще может вызвать эту ошибку.

Джейк С
источник

Ответы:

191

РЕДАКТИРОВАТЬ: Версия Super Redux

Попробуйте порт 587 вместо 465. Порт 465 технически устарел.


После кучи обнюхивания пакетов я понял это. Во-первых, вот краткий ответ:

.NET поддерживает шифрование SmtpClient только через STARTTLS. Если EnableSslфлаг установлен, сервер должен ответить на EHLO сообщением STARTTLS, в противном случае он выдаст исключение. См. Документацию MSDN для получения более подробной информации.

Во-вторых, небольшой урок истории SMTP для тех, кто столкнется с этой проблемой в будущем:

Раньше, когда сервисы хотели также предлагать шифрование, им был назначен другой номер порта, и на этом номере порта они немедленно инициировали SSL-соединение. Со временем они поняли, что было бы глупо тратить два номера порта на одну службу, и разработали способ для служб, позволяющий использовать открытый текст и шифрование на одном и том же порте с использованием STARTTLS. Связь начнется с использованием открытого текста, а затем будет использоваться команда STARTTLS для обновления до зашифрованного соединения. STARTTLS стал стандартом для шифрования SMTP. К сожалению, как это всегда бывает при внедрении нового стандарта, существует мешанина совместимости со всеми клиентами и серверами.

В моем случае мой пользователь пытался подключить программное обеспечение к серверу, который вызывал немедленное соединение SSL, что является устаревшим методом, который не поддерживается Microsoft в .NET.

Джейк С
источник
как я могу узнать, есть ли у сервера, к которому я подключаюсь, такие же проблемы? Я пытаюсь использовать SmtpClient с Yahoo и / или gmail и получаю описанную ошибку. Когда я пытаюсь использовать сервер обмена 2013 года, мой код работает нормально.
raider33
11
Самый простой способ проверить - попробовать использовать порт 587, а не 465. Хотя некоторые SMTP-серверы поддерживают TLS на 465 (а иногда даже на 25), для поддержки TLS требуется только порт 587. Кроме того, использование порта 465 не рекомендуется с 1998 года ( en.wikipedia.org/wiki/SMTPS ), хотя на практике на многих серверах он включен для устаревших клиентов.
Jake C
1
Да, переход на 587 помог. Спасибо, что указали мне правильное направление.
raider33
2
587 работает, хотя smtp.att.yahaoo.com говорит, что используется 465. Спасибо, чувак.
Сэм
1
Фактическое решение см. На странице stackoverflow.com/a/1014876/247702 об использовании (устаревшего) System.Web.Mail, который поддерживает неявный SSL.
user247702
22

Для всех, кто наткнется на этот пост и ищет решение, и вы настроили SMTP sendgrid через Azure.

Имя пользователя - это не имя пользователя, которое вы указали при создании объекта sendgrid в лазурном. Чтобы найти свое имя пользователя;

  • Нажмите на свой объект sendgrid в лазурном цвете и нажмите «Управление». Вы будете перенаправлены на сайт SendGrid.
  • Подтвердите свой адрес электронной почты, а затем скопируйте отображаемое там имя пользователя ... это автоматически созданное имя пользователя.
  • Добавьте имя пользователя из SendGrid в настройки SMTP в файле web.config.

Надеюсь это поможет!

нолого
источник
2
Это может показаться глупым, но еще кое-что, что вы можете захотеть проверить, это правильность пароля для настройки SMTP SendGrid. Наша установка изначально работала, и однажды мы начали получать сообщение об исключении OP. Поиски в WWW в основном указывали на поиск других конфигураций SMTP-сервера, когда в конце концов выяснялось, что пароль неверен. Кто-то из команды изменил пароль в файле конфигурации на вариант, в котором первая буква не была заглавной.
methon.dagger
1
В моем случае имя пользователя было неверным и содержало опечатку. Но неправильный пароль также может дать сообщение «Невозможно прочитать данные из транспортного соединения: net_io_connectionclosed». ошибка. Поэтому проверьте и имя пользователя, и пароль. А для пользователей Azure имя пользователя имеет форму «azure_guid-withoutdashes@azure.com» (например: azure_e9e062db4bfd491296bec77bcff49ed9@azure.com)
Радж Рао
20

Измените порт с 465 на 587, и он будет работать.

ПРИЗНАВАТЬ
источник
3
Я не уверен, что случилось, но это помогает мне использовать gmail smtp. можешь объяснить, почему это работает?
Крисмограмма,
10

Возможно, вам также придется изменить настройку «менее безопасные приложения» в вашей учетной записи Gmail. EnableSsl, используйте порт 587 и включите «менее безопасные приложения». Если вы используете Google для менее безопасных приложений, есть справочные страницы Google, которые свяжут вас прямо со страницей вашей учетной записи. Это была моя проблема, но теперь все работает благодаря всем приведенным выше ответам.

Билл Махони
источник
Спасибо, Билл. Это все еще работает с моей стандартной учетной записью Gmail. Если вы не используете настройку «менее безопасные приложения», вам необходимо использовать двухэтапную аутентификацию OAuth2. Это непрактично, если вы просто хотите отправить письмо с подтверждением с веб-сайта.
Дэн Рэндольф
1
Где устанавливается "менее безопасные приложения". Я ищу его в своей учетной записи Gmail.
Сэм
1
Я нашел параметр «Менее безопасные приложения» - его нет в настройках Gmail, а в настройках учетной записи Google: Моя учетная запись> Вход и безопасность myaccount.google.com/…
HFloyd,
9

Я пробовал все ответы выше, но все еще получаю эту ошибку с учетной записью Office 365. Код, похоже, отлично работает с учетной записью Google и smtp.gmail.com при разрешении менее безопасных приложений.

Есть ли другие предложения, которые я мог бы попробовать?

Вот код, который я использую

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

ОБНОВЛЕНИЕ И КАК Я ЭТО РЕШИЛ:

Решил проблему, изменив Smtp Client на Mailkit. Клиент Smtp System.Net.Mail теперь не рекомендуется для использования Microsoft из-за проблем с безопасностью, и вместо этого вы должны использовать MailKit. Использование Mailkit давало мне более четкие сообщения об ошибках, которые я мог понять, обнаружив основную причину проблемы (проблема с лицензией). Вы можете получить Mailkit, загрузив его как пакет Nuget .

Для получения дополнительной информации прочтите документацию о Smtp Client: https://docs.microsoft.com/es-es/dotnet/api/system.net.mail.smtpclient?redirectedfrom=MSDN&view=netframework-4.7.2

Вот как я реализовал SmtpClient с 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

Поддерживает ли ваша библиотека SMTP зашифрованное соединение? Почтовый сервер может ожидать безопасное соединение TLS и, следовательно, закрывать соединение при отсутствии подтверждения TLS.

1234varun
источник
Это просто SmtpClientбиблиотека .NET по умолчанию , она поддерживает encrytpion, сервер требует шифрования, и я установил client.EnableSssl = true;. Хотя я думаю, что собираюсь продолжить это с Wireshark.
Jake C
3

Если вы используете SMTP-сервер в том же самом поле, и ваш SMTP привязан к IP-адресу вместо «Any Assigned», это может привести к сбою, потому что он пытается использовать IP-адрес (например, 127.0.0.1), который в настоящее время не работает. на.

Иосия
источник
2

Чтобы улучшить то, что jocull упомянул в комментарии, я делал все, что упоминалось в этой ветке, и вычеркивал ... потому что мой был в цикле, который нужно запускать снова и снова; после первого прохождения цикла иногда происходил сбой. Всегда работал с первого раза через петлю.

Для ясности: цикл включает создание SmtpClient, а затем выполнение .Send с правильными данными. SmtpClient был создан внутри блока try / catch, чтобы перехватывать ошибки и быть уверенным, что объект был уничтожен до конца цикла.

В моем случае решение заключалось в том, чтобы убедиться, что SmtpClient удаляется после каждого раза в цикле (либо с помощью оператора using (), либо путем удаления вручную). Даже если объект SmtpClient неявно уничтожается в цикле, .NET, похоже, оставляет вещи, лежащие без дела, чтобы вступить в конфликт со следующей попыткой.

Энди
источник
2

Измените номер порта на 587 с 465

Абдус Салам Азад
источник
2

удаление

client.UseDefaultCredentials = false; 

казалось, решил это для меня.

Гонер Дуг
источник
1

В моем случае клиент забыл добавить новый IP-адрес в свои настройки SMTP. Откройте IIS 6.0 на сервере, который настраивает smtp, щелкните правой кнопкой мыши виртуальный сервер Smtp, выберите «Свойства», вкладку «Доступ», щелкните «Подключения», добавьте IP-адрес нового сервера. Затем нажмите Relay, также добавьте IP-адрес нового сервера. Это решило мою проблему.

Нора
источник
0

Попробуйте это: вот код, который я использую для отправки писем нескольким пользователям.

 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также одноразовый, поэтому его нужно завернуть в usingблок
jocull
0

В случае, если все вышеперечисленные решения не работают для вас, попробуйте обновить следующий файл на своем сервере (я имею в виду публикацию, и сборка до этого была бы полезна).

bin-> projectname.dll 

После обновления вы увидите эту ошибку. как я решил с этим решением.

Аджай Кумар
источник
1
Удивительно, это сработало для меня! Разрешить небезопасные приложения было включено, и для порта уже установлено значение 587.
TechyGypo
Спасибо, только что понял, что не только я столкнулся с этой проблемой. рад помочь.
Аджай Кумар
0

Для Outlook используйте следующую настройку, которая не дает мне ошибки

Имя SMTP-сервера smtp-mail.outlook.com

SMTP-порт 587

Хишам шахид
источник
0

Эта ошибка является очень общей. Она может быть вызвана многими причинами, например, неправильным почтовым сервером. Некоторые хостинговые компании используют формат mail.domainname. Если вы просто используете доменное имя, это не сработает. проверьте учетные данные имя хоста имя пользователя пароль, если необходимо. Свяжитесь с хостинговой компанией.

<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

В моем случае IP-адрес веб-сервера был заблокирован на почтовом сервере, он должен быть разблокирован вашей хостинговой компанией и внесен в белый список. Также используйте порт 587.

Жолт
источник
0

Если ваш почтовый сервер - Gmail (smtp.google.com), вы получите эту ошибку, когда достигнете лимита сообщений. Gmail позволяет отправлять по SMTP до 2000 сообщений в сутки.

Евгений Соболев
источник
0

Я столкнулся с этим при использовании smtp.office365.com, используя порт 587 с SSL. Мне удалось войти в учетную запись с помощью portal.office.com и подтвердить, что у учетной записи есть лицензия. Но когда я запускал код для отправки электронных писем, я продолжал получать ошибку net_io_connectionclosed.

Мне потребовалось некоторое время, чтобы понять это, но администратор Exchange нашел виновника. Мы используем O365, но сервер Exchange был в гибридной среде. Хотя учетная запись, которую мы пытались использовать, была синхронизирована с Azure AD и имела действующую лицензию O365, по какой-то причине почтовый ящик все еще находился на гибридном сервере Exchange, а не на Exchange Online. После того, как администратор обмена использовал команду «Move-Mailbox» для перемещения почтового ящика с гибридного сервера обмена в O365, мы могли использовать код для отправки электронной почты с помощью o365.

iki58762
источник
-1

Подготовьтесь: 1. HostA - это виртуальный SMTP-сервер с портом по умолчанию 25 2. HostB - это рабочая станция, на которой я отправляю почту с помощью SmtpClient и имитирую нестабильную сеть. Я использую неуклюже

Случай 1 Учитывая, что HostB - 2008R2 Когда я отправляю электронное письмо. Затем возникает эта проблема.

Случай 2 Учитывая, что HostB - это версия 2012 года или выше. Затем письмо было разослано.

Заключение: эта основная причина связана с Windows Server 2008R2.

Шон Ван
источник