SmtpException : 전송 연결에서 데이터를 읽을 수 없음 : net_io_connectionclosed


103

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".

방화벽이 문제가 아님을 확인했습니다. 포트는 클라이언트와 서버 사이에서 잘 열립니다. 이 오류가 발생할 수있는 다른 방법을 모르겠습니다.

답변:


190

편집 : Super Redux 버전

465 대신 포트 587을 사용해보십시오. 포트 465는 기술적으로 더 이상 사용되지 않습니다.


많은 패킷 스니핑 후 나는 그것을 알아 냈습니다. 먼저, 짧은 대답은 다음과 같습니다.

.NET 은 STARTTLS를 통한 암호화 SmtpClient 지원합니다. 는 IF EnableSsl플래그를 설정하는 STARTTLS로 EHLO에 서버 필수의 응답은, 그렇지 않으면 예외가 발생합니다. 자세한 내용은 MSDN 설명서를 참조하십시오.

둘째, 향후이 문제에 직면 한 사람들을위한 간단한 SMTP 기록 강의 :

예전에는 서비스가 암호화를 제공하기를 원했을 때 다른 포트 번호가 할당되었으며 해당 포트 번호에서 즉시 SSL 연결을 시작했습니다. 시간이 지남에 따라 그들은 하나의 서비스에 대해 두 개의 포트 번호를 낭비하는 것이 어리 석다는 것을 깨달았고 STARTTLS를 사용하여 동일한 포트에서 일반 텍스트와 암호화를 허용하는 서비스 방법을 고안했습니다. 통신은 일반 텍스트를 사용하여 시작한 다음 STARTTLS 명령을 사용하여 암호화 된 연결로 업그레이드합니다. STARTTLS는 SMTP 암호화의 표준이되었습니다. 안타깝게도 새로운 표준이 구현 될 때 항상 발생하는 것처럼 모든 클라이언트 및 서버와의 호환성이 뒤죽박죽입니다.

제 경우에는 사용자가 즉시 SSL 연결을 강제하는 서버에 소프트웨어를 연결하려고했습니다. 이는 Microsoft에서 .NET에서 지원하지 않는 레거시 방법입니다.


연결중인 서버에 동일한 문제가 있는지 어떻게 알 수 있습니까? yahoo 및 / 또는 gmail과 함께 SmtpClient를 사용하고 설명 된 오류가 발생합니다. 2013 교환 서버에 대해 시도하면 코드가 제대로 작동합니다.
raider33

11
가장 간단한 테스트 방법은 465가 아닌 587 포트를 사용하는 것입니다. 일부 SMTP 서버는 465 (때로는 25)에서 TLS를 지원하지만 TLS를 지원하려면 포트 587 만 필요합니다. 그 외에도 포트 465의 사용은 1998 년 ( en.wikipedia.org/wiki/SMTPS ) 이후로 더 이상 사용되지 않지만 실제로는 많은 서버에서 레거시 클라이언트를 사용할 수 있습니다.
Jake C

1
예, 587로 변경하면 트릭이 발생했습니다. 올바른 방향을 알려 주셔서 감사합니다.
raider33 2014 년

2
smtp.att.yahaoo.com에서 465를 사용한다고 말했지만 587은 작동합니다. 감사합니다.

1
실제 솔루션은 암시 적 SSL을 지원하는 (더 이상 사용되지 않는) System.Web.Mail 사용에 대한 stackoverflow.com/a/1014876/247702 를 참조하십시오 .
user247702

20

포트를 465에서 587로 변경하면 작동합니다.


3
나는 무슨 일이 일어 났는지 잘 모르겠지만 이것은 gmail smtp를 사용하여 나를 작동합니다. 이것이 왜 작동하는지 설명 할 수 있습니까?
Crismogram

20

솔루션을 찾고 있으며 Azure를 통해 SMTP sendgrid를 설정 한이 게시물을 우연히 발견 한 사람을 위해.

사용자 이름은 Azure에서 sendgrid 개체를 만들 때 설정 한 사용자 이름이 아닙니다. 사용자 이름을 찾으려면

  • Azure에서 sendgrid 개체를 클릭하고 관리를 클릭합니다. SendGrid 사이트로 리디렉션됩니다.
  • 이메일을 확인한 다음 거기에 표시된 사용자 이름을 복사합니다. 자동 생성 된 사용자 이름입니다.
  • SendGrid의 사용자 이름을 web.config 파일의 SMTP 설정에 추가합니다.

도움이 되었기를 바랍니다!


2
이것은 어리석은 것처럼 보일 수 있지만 확인해야 할 다른 것은 SMTP SendGrid 설정에 대한 암호가 올바른지 여부입니다. 우리의 설정은 원래 작동했고 어느 날 OP의 예외 메시지를 받기 시작했습니다. WWW에 대한 검색은 대부분 다른 SMTP 서버 구성을 살펴보고 결국 암호가 올바르지 않은 것으로 밝혀졌습니다. 팀의 누군가가 구성 파일의 암호를 첫 글자가 대문자가 아닌 변형으로 변경했습니다.
methon.dagger

1
제 경우에는 사용자 이름이 잘못되었고 오타가있었습니다. 그러나 잘못된 암호는 "전송 연결에서 데이터를 읽을 수 없습니다 : net_io_connectionclosed"를 제공 할 수도 있습니다. 오류. 따라서 사용자 이름과 비밀번호를 모두 확인하십시오. Azure 사용자의 경우 사용자 이름은 "azure_guid-withoutdashes@azure.com"형식입니다 (예 : azure_e9e062db4bfd491296bec77bcff49ed9@azure.com)
Raj Rao

10

Gmail 계정에서 "보안 수준이 낮은 앱"설정을 변경해야 할 수도 있습니다. EnableSsl, 포트 587을 사용하고 "보안 수준이 낮은 앱"을 활성화합니다. 보안 수준이 낮은 앱 부분을 Google에 검색하는 경우 계정 페이지로 바로 연결되는 Google 도움말 페이지가 있습니다. 그게 내 문제 였지만 위의 모든 답변 덕분에 모든 것이 작동하고 있습니다.


감사합니다 빌. 이것은 여전히 ​​내 표준 Gmail 계정에서 작동합니다. "보안 수준이 낮은 앱"설정을 사용하지 않는 경우 OAuth2 2 파트 인증을 사용해야합니다. 웹 사이트에서 확인 이메일을 보내려는 경우에는 실용적이지 않습니다.
Dan Randolph

1
"보안 수준이 낮은 앱"설정은 어디에 있습니까? 내 Gmail 계정에서 찾고 있습니다.
Sam

1
'보안 수준이 낮은 앱'설정을
찾았

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으로 변경하여 문제를 해결했습니다. System.Net.Mail Smtp 클라이언트는 이제 보안 문제로 인해 Microsoft에서 사용하지 않는 것이 좋으며 대신 MailKit을 사용해야합니다. Mailkit을 사용하면 문제의 근본 원인 (라이선스 문제)을 찾을 수있는 명확한 오류 메시지가 표시되었습니다. 메일 킷을 Nuget 패키지 로 다운로드하여 얻을 수 있습니다 .

자세한 내용은 Smtp 클라이언트에 대한 설명서를 참조하십시오. https://docs.microsoft.com/es-es/dotnet/api/system.net.mail.smtpclient?redirectedfrom=MSDN&view=netframework-4.7.2

MailKit으로 SmtpClient를 구현 한 방법은 다음과 같습니다.

        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 핸드 셰이크없이 연결을 닫을 수 있습니다.


기본 .NET SmtpClient라이브러리이며 암호화를 지원하며 서버에 암호화가 필요하며 client.EnableSssl = true;. Wireshark로 이것을 조금 더 설득 할 것이라고 생각하지만.
Jake C

3

같은 상자에서 SMTP 서버를 사용하고 있고 SMTP가 "Any Assigned"대신 IP 주소에 바인딩 된 경우 SMTP가 현재 작동하지 않는 IP 주소 (예 : 127.0.0.1)를 사용하려고하므로 실패 할 수 있습니다. 의 위에.


2

주석에서 언급 한 기수를 높이기 위해이 스레드에서 언급하는 모든 작업을 수행하고 눈에 띄게했습니다. 루프를 처음 통과 한 후에는 때때로 실패합니다. 항상 루프를 통해 처음으로 작업했습니다.

명확하게 말하면 루프에는 SmtpClient 생성과 올바른 데이터로 .Send 수행이 포함됩니다. SmtpClient는 try / catch 블록 내부에 생성되어 오류를 포착하고 루프의 맨 아래 이전에 객체가 파괴되었는지 확인합니다.

필자의 경우 해결책은 루프에서 매번 SmtpClient가 폐기되었는지 확인하는 것이 었습니다 (using () 문을 통해 또는 수동 폐기를 수행하여). SmtpClient 개체가 루프에서 암시 적으로 소멸되는 경우에도 .NET은 다음 시도와 충돌하기 위해 주변에 물건을두고있는 것처럼 보입니다.



2

풀이

client.UseDefaultCredentials = false; 

나를 위해 그것을 해결하는 것 같았습니다.


1

위의 모든 솔루션이 작동하지 않는 경우 다음 파일을 서버에 업데이트하십시오 (내 말은 게시하면 도움이 될 것입니다).

bin-> projectname.dll 

업데이트 후이 오류가 표시됩니다. 이 솔루션으로 해결했습니다.


1
놀랍게도 이것은 나를 위해 일했습니다! 안전하지 않은 앱 허용이 켜져 있고 포트가 이미 587로 설정되었습니다.
TechyGypo

고마워,이 문제를 가진 사람이 내가 유일한 사람이 아니라는 것을 깨달았다. 도와 줄 수있어서 기뻐.
Ajay Kumar

1

제 경우에는 고객이 SMTP 설정에 새 IP 주소를 추가하는 것을 잊었습니다. smtp를 설정하는 서버에서 IIS 6.0을 열고 Smtp 가상 서버를 마우스 오른쪽 버튼으로 클릭하고 속성, 액세스 탭, 연결을 클릭하고 새 서버의 IP 주소를 추가합니다. 그런 다음 릴레이를 클릭하고 새 서버의 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

나에게 오류를주지 않는 다음 설정을 사용하십시오.

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에서는 24 시간당 최대 2000 개의 메일 만 SMTP를 통해 보낼 수 있습니다.


0

SSL과 함께 포트 587을 사용하여 smtp.office365.com을 사용할 때 이것을 만났습니다. portal.office.com을 사용하여 계정에 로그인 할 수 있었고 계정에 라이선스가 있는지 확인할 수있었습니다. 그러나 이메일을 보내기 위해 코드를 실행했을 때 net_io_connectionclosed 오류가 계속 발생했습니다.

알아내는 데 시간이 좀 걸렸지 만 Exchange 관리자가 범인을 찾았습니다. 우리는 O365를 사용하고 있지만 Exchange 서버는 하이브리드 환경에있었습니다. 사용하려는 계정이 Azure AD에 동기화되었고 유효한 O365 라이선스가 있었지만 어떤 이유로 사서함은 Exchange 온라인이 아닌 하이브리드 Exchange 서버에 계속 남아있었습니다. 교환 관리자가 "Move-Mailbox"명령을 사용하여 사서함을 하이브리드 교환 서버에서 O365로 이동 한 후 코드를 사용하여 o365를 사용하여 전자 메일을 보낼 수 있습니다.


-1

준비 : 1. 호스트 A가 기본 포트 25 2. 호스트 B와 SMTP 가상 서버 것은 내가려면 SmtpClient로 메일을 보내거나 불안정한 네트워크 시뮬레이션하는 워크 스테이션입니다 I 사용 서투른를

사례 1 HostB가 2008R2 인 경우 이메일을 보낼 때. 그러면이 문제가 발생합니다.

사례 2 HostB가 2012 년 이상 버전이면 주어집니다. 그런 다음 메일이 발송되었습니다.

결론 :이 근본 원인은 Windows Server 2008R2와 관련이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.