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"Unable to read data from the transport connection: net_io_connectionclosed"

ฉันยืนยันว่าไฟร์วอลล์ไม่ใช่ปัญหา พอร์ตเปิดได้ดีระหว่างไคลเอนต์และเซิร์ฟเวอร์ ฉันไม่แน่ใจว่ามีอะไรอีกที่ทำให้เกิดข้อผิดพลาดนี้ได้

คำตอบ:


191

แก้ไข: เวอร์ชัน Super Redux

ลองใช้พอร์ต 587 แทน 465 พอร์ต 465 เลิกใช้งานทางเทคนิคแล้ว


หลังจากดมกลิ่นแพ็คเก็ตฉันก็คิดออก ก่อนอื่นนี่คือคำตอบสั้น ๆ :

สุทธิSmtpClient เพียงสนับสนุนการเข้ารหัสผ่าน STARTTLS หากEnableSslตั้งค่าแฟล็กเซิร์ฟเวอร์จะต้องตอบสนองต่อ EHLO ด้วย STARTTLS มิฉะนั้นจะเกิดข้อยกเว้น ดูเอกสารMSDNสำหรับรายละเอียดเพิ่มเติม

ประการที่สองบทเรียนประวัติ SMTP ฉบับย่อสำหรับผู้ที่พบปัญหานี้ในอนาคต:

ย้อนกลับไปในวันที่บริการต้องการเสนอการเข้ารหัสพวกเขาได้รับการกำหนดหมายเลขพอร์ตที่แตกต่างกันและหมายเลขพอร์ตนั้นได้เริ่มการเชื่อมต่อ SSL ทันที เมื่อเวลาผ่านไปพวกเขาตระหนักว่ามันโง่ที่ต้องเสียหมายเลขพอร์ตสองหมายเลขสำหรับบริการเดียวและพวกเขาคิดหาวิธีให้บริการอนุญาตข้อความธรรมดาและการเข้ารหัสบนพอร์ตเดียวกันโดยใช้ STARTTLS การสื่อสารจะเริ่มต้นโดยใช้ข้อความธรรมดาจากนั้นใช้คำสั่ง STARTTLS เพื่ออัปเกรดเป็นการเชื่อมต่อที่เข้ารหัส STARTTLS กลายเป็นมาตรฐานสำหรับการเข้ารหัส SMTP น่าเสียดายที่มันเกิดขึ้นเสมอเมื่อมีการใช้มาตรฐานใหม่จึงมีความเข้ากันได้กับไคลเอนต์และเซิร์ฟเวอร์ทั้งหมด

ในกรณีของฉันผู้ใช้ของฉันพยายามเชื่อมต่อซอฟต์แวร์กับเซิร์ฟเวอร์ที่บังคับให้เชื่อมต่อ SSL ในทันทีซึ่งเป็นวิธีเดิมที่ Microsoft ไม่รองรับใน. NET


ฉันจะทราบได้อย่างไรว่าเซิร์ฟเวอร์ที่ฉันกำลังเชื่อมต่อมีปัญหาเดียวกัน ฉันพยายามใช้ SmtpClient กับ yahoo และ / หรือ gmail และได้รับข้อผิดพลาดที่อธิบายไว้ เมื่อฉันลองใช้เซิร์ฟเวอร์ Exchange 2013 รหัสของฉันใช้งานได้ดี
raider33

11
วิธีทดสอบที่ง่ายที่สุดคือลองใช้พอร์ต 587 ไม่ใช่ 465 ในขณะที่เซิร์ฟเวอร์ SMTP บางตัวรองรับ TLS บน 465 (และบางครั้งถึง 25) แต่ต้องใช้พอร์ต 587 เท่านั้นเพื่อรองรับ TLS นอกจากนั้นการใช้พอร์ต 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)
Raj Rao

20

เปลี่ยนพอร์ตจาก 465 เป็น 587 และจะใช้งานได้


3
ฉันไม่แน่ใจว่าเกิดอะไรขึ้น แต่สิ่งนี้ใช้ได้กับฉันโดยใช้ gmail smtp คุณช่วยอธิบายได้ไหมว่าทำไมถึงได้ผล
Crismogram

10

คุณอาจต้องเปลี่ยนการตั้งค่า "แอปที่มีความปลอดภัยน้อย" ในบัญชี Gmail ของคุณ EnableSsl ใช้พอร์ต 587 และเปิดใช้งาน "แอปที่มีความปลอดภัยน้อย" หากคุณ Google ส่วนแอปที่มีความปลอดภัยน้อยจะมีหน้าความช่วยเหลือของ Google ที่จะเชื่อมโยงคุณไปยังหน้าสำหรับบัญชีของคุณ นั่นเป็นปัญหาของฉัน แต่ตอนนี้ทุกอย่างทำงานได้ดีด้วยคำตอบทั้งหมดข้างต้น


ขอบคุณบิล สิ่งนี้ยังใช้ได้กับบัญชี gmail มาตรฐานของฉัน หากคุณไม่ใช้การตั้งค่า "แอปที่มีความปลอดภัยน้อย" คุณต้องใช้การตรวจสอบสิทธิ์แบบ 2 ส่วนของ OAuth2 สิ่งนี้ใช้ไม่ได้จริงเมื่อคุณเพียงแค่ต้องการส่งอีเมลยืนยันจากเว็บไซต์
Dan Randolph

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 ขณะนี้ Microsoft ไม่แนะนำให้ใช้ไคลเอ็นต์ System.Net.Mail Smtp เนื่องจากปัญหาด้านความปลอดภัยและคุณควรใช้ MailKit แทน การใช้ Mailkit ทำให้ฉันมีข้อความแสดงข้อผิดพลาดที่ชัดเจนขึ้นซึ่งฉันสามารถเข้าใจการค้นหาสาเหตุที่แท้จริงของปัญหา (ปัญหาใบอนุญาต) คุณสามารถรับ Mailkit ได้โดยดาวน์โหลดเป็นแพ็คเกจNuget

อ่านเอกสารเกี่ยวกับไคลเอ็นต์ Smtp สำหรับข้อมูลเพิ่มเติม: 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


มันเป็นเพียงการเริ่มต้น .NET SmtpClientห้องสมุดก็ไม่สนับสนุน encrytpion client.EnableSssl = true;เซิร์ฟเวอร์ไม่จำเป็นต้องเข้ารหัสและฉันมีชุด แม้ว่าฉันคิดว่าฉันจะพยายามต่อไปอีกเล็กน้อยด้วย Wireshark
Jake C

3

หากคุณกำลังใช้เซิร์ฟเวอร์ SMTP ในช่องเดียวกันและ SMTP ของคุณถูกผูกไว้กับที่อยู่ IP แทนที่จะเป็น "มอบหมายใด ๆ " อาจล้มเหลวเนื่องจากพยายามใช้ที่อยู่ IP (เช่น 127.0.0.1) ซึ่ง SMTP ไม่ทำงานในขณะนี้ บน.


2

เพื่อยกระดับสิ่งที่ jocull กล่าวถึงในความคิดเห็นฉันกำลังทำทุกอย่างที่กล่าวถึงในหัวข้อนี้และโดดเด่น ... หลังจากผ่านลูปครั้งแรกบางครั้งอาจล้มเหลว ทำงานในครั้งแรกผ่านลูปเสมอ

เพื่อความชัดเจน: ลูปรวมถึงการสร้าง SmtpClient แล้วทำส่งด้วยข้อมูลที่ถูกต้อง SmtpClient ถูกสร้างขึ้นภายในบล็อก try / catch เพื่อตรวจจับข้อผิดพลาดและเพื่อให้แน่ใจว่าวัตถุถูกทำลายก่อนด้านล่างของลูป

ในกรณีของฉันวิธีแก้ปัญหาคือตรวจสอบให้แน่ใจว่า SmtpClient ถูกกำจัดหลังจากทุกครั้งในลูป (ไม่ว่าจะโดยใช้คำสั่ง () หรือโดยการกำจัดด้วยตนเอง) แม้ว่าออบเจ็กต์ SmtpClient จะถูกทำลายโดยปริยายในลูป แต่ดูเหมือนว่า. NET จะทิ้งสิ่งของไว้รอบ ๆ เพื่อให้ขัดแย้งกับความพยายามครั้งต่อไป




1

ในกรณีของฉันลูกค้าลืมเพิ่มที่อยู่ IP ใหม่ในการตั้งค่า SMTP เปิด IIS 6.0 ในเซิร์ฟเวอร์ที่ตั้งค่า smtp คลิกขวาที่เซิร์ฟเวอร์เสมือน Smtp เลือกคุณสมบัติแท็บ Access คลิกการเชื่อมต่อเพิ่มที่อยู่ 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

ในกรณีที่วิธีแก้ปัญหาข้างต้นไม่ได้ผลสำหรับคุณให้ลองอัปเดตไฟล์ต่อไปนี้ไปยังเซิร์ฟเวอร์ของคุณ (โดยการเผยแพร่ฉันหมายถึงและโครงสร้างก่อนหน้านั้นจะเป็นประโยชน์)

bin-> projectname.dll 

หลังจากอัปเดตคุณจะเห็นข้อผิดพลาดนี้ ตามที่ฉันได้แก้ไขด้วยวิธีนี้


1
สิ่งนี้ใช้ได้ผลกับฉันอย่างน่าอัศจรรย์! อนุญาตให้แอปที่ไม่ปลอดภัยเปิดอยู่และพอร์ตถูกตั้งค่าเป็น 587 แล้ว
TechyGypo

ขอบคุณเพิ่งรู้ว่าฉันไม่ใช่คนเดียวที่มีปัญหานี้ ยินดีที่ได้ช่วย.
Ajay Kumar

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 ได้สูงสุด 2,000 ข้อความต่อ 24 ชั่วโมง


0

ฉันพบสิ่งนี้เมื่อใช้ smtp.office365.com โดยใช้พอร์ต 587 กับ SSL ฉันสามารถเข้าสู่ระบบบัญชีโดยใช้ portal.office.com และฉันสามารถยืนยันได้ว่าบัญชีนั้นมีใบอนุญาต แต่เมื่อฉันยิงรหัสเพื่อส่งอีเมลฉันยังคงได้รับข้อผิดพลาด net_io_connectionclosed

ฉันใช้เวลาพอสมควรในการคิดออก แต่ผู้ดูแลระบบ Exchange พบผู้กระทำผิด เรากำลังใช้ O365 แต่เซิร์ฟเวอร์ Exchange อยู่ในสภาพแวดล้อมแบบไฮบริด แม้ว่าบัญชีที่เราพยายามใช้จะซิงค์กับ Azure AD และมีสิทธิ์การใช้งาน O365 ที่ถูกต้อง แต่ด้วยเหตุผลบางประการกล่องจดหมายยังคงอยู่บนเซิร์ฟเวอร์ Exchange แบบไฮบริดไม่ใช่ Exchange แบบออนไลน์ หลังจากที่ผู้ดูแลระบบ Exchange ใช้คำสั่ง "Move-Mailbox" เพื่อย้ายกล่องจดหมายจากเซิร์ฟเวอร์แลกเปลี่ยนแบบไฮบริดไปที่ O365 เราสามารถใช้รหัสเพื่อส่งอีเมลโดยใช้ o365


-1

เตรียม: 1. HostA คือเซิร์ฟเวอร์เสมือน SMTP ที่มีพอร์ตเริ่มต้น 25 2. HostB เป็นเวิร์กสเตชันที่ฉันส่งเมลด้วย SmtpClient และจำลองเครือข่ายที่ไม่เสถียร ฉันใช้งานเงอะงะ

กรณีที่ 1 ระบุหาก HostB เป็น 2008R2 เมื่อฉันส่งอีเมล จากนั้นปัญหานี้จะเกิดขึ้น

กรณีที่ 2 ระบุหาก HostB เป็นเวอร์ชัน 2012 หรือสูงกว่าเมื่อฉันส่งอีเมล จากนั้นจดหมายก็ถูกส่งออกไป

สรุป: สาเหตุหลักนี้เกี่ยวข้องกับ Windows Server 2008R2

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.