SmtpException: Không thể đọc dữ liệu từ kết nối truyền tải: net_io_connectionclosed


102

Tôi đang sử dụng SmtpClientthư viện để gửi email bằng cách sau:

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

Mã hoạt động tốt trong môi trường thử nghiệm của tôi, nhưng khi tôi sử dụng máy chủ SMTP sản xuất, mã không thành công với thông báo SmtpException"Không gửi được thư". với nội dung IOException"Không thể đọc dữ liệu từ kết nối truyền tải: net_io_connectionclosed".

Tôi đã xác nhận rằng tường lửa không phải là một vấn đề. Cổng chỉ mở tốt giữa máy khách và máy chủ. Tôi không chắc điều gì khác có thể gây ra lỗi này.

Câu trả lời:


189

CHỈNH SỬA: Phiên bản Super Redux

Hãy thử cổng 587 thay vì 465. Về mặt kỹ thuật, cổng 465 không được dùng nữa.


Sau một loạt các gói tin, tôi đã tìm ra. Đầu tiên, đây là câu trả lời ngắn gọn:

.NET SmtpClient chỉ hỗ trợ mã hóa qua STARTTLS. Nếu EnableSslcờ được đặt, máy chủ phải phản hồi với EHLO bằng STARTTLS, nếu không nó sẽ đưa ra một ngoại lệ. Xem tài liệu MSDN để biết thêm chi tiết.

Thứ hai, một bài học lịch sử SMTP nhanh chóng cho những ai gặp phải vấn đề này trong tương lai:

Ngày trước, khi các dịch vụ muốn cung cấp mã hóa, chúng được gán một số cổng khác và trên số cổng đó, chúng ngay lập tức bắt đầu kết nối SSL. Thời gian trôi qua, họ nhận ra thật ngớ ngẩn khi lãng phí hai số cổng cho một dịch vụ và họ đã nghĩ ra cách để các dịch vụ cho phép bản rõ và mã hóa trên cùng một cổng bằng cách sử dụng STARTTLS. Giao tiếp sẽ bắt đầu sử dụng văn bản rõ, sau đó sử dụng lệnh STARTTLS để nâng cấp lên kết nối được mã hóa. STARTTLS đã trở thành tiêu chuẩn cho mã hóa SMTP. Thật không may, nó luôn xảy ra khi một tiêu chuẩn mới được triển khai, có một sự thiếu sót về khả năng tương thích với tất cả các máy khách và máy chủ ngoài đó.

Trong trường hợp của tôi, người dùng của tôi đang cố gắng kết nối phần mềm với máy chủ đang buộc kết nối SSL ngay lập tức, đây là phương pháp kế thừa không được Microsoft hỗ trợ trong .NET.


Làm cách nào để biết Máy chủ mà tôi đang kết nối có vấn đề tương tự hay không? Tôi đang cố gắng sử dụng SmtpClient với yahoo và / hoặc gmail và gặp lỗi được mô tả. Khi tôi thử với một máy chủ trao đổi năm 2013, mã của tôi hoạt động tốt.
raider33

11
Cách đơn giản nhất để kiểm tra là thử sử dụng cổng 587 chứ không phải 465. Trong khi một số máy chủ SMTP hỗ trợ TLS trên 465 (và đôi khi thậm chí là 25), chỉ cần cổng 587 để hỗ trợ TLS. Ngoài ra, việc sử dụng cổng 465 đã không còn được chấp nhận từ năm 1998 ( en.wikipedia.org/wiki/SMTPS ), mặc dù trên thực tế, nhiều máy chủ đã kích hoạt nó cho các máy khách cũ.
Jake C

1
Có, thay đổi thành 587 đã làm một mẹo nhỏ. Cám ơn đã chỉ tôi hướng đi đúng.
raider33

2
587 hoạt động mặc dù smtp.att.yahaoo.com nói rằng sử dụng 465. Cảm ơn anh bạn.
Sam

1
Để biết giải pháp thực tế, hãy xem stackoverflow.com/a/1014876/247702 về cách sử dụng System.Web.Mail (không được dùng nữa), hỗ trợ SSL ngầm định.
user247702

20

Thay đổi cổng từ 465 thành 587 và nó sẽ hoạt động.


3
Tôi không chắc điều gì đã xảy ra nhưng điều này hoạt động với tôi khi sử dụng smtp gmail. bạn có thể giải thích tại sao điều này hoạt động?
Crismogram

20

Đối với bất kỳ ai tình cờ xem được bài đăng này đang tìm kiếm giải pháp và bạn đã thiết lập SMTP sendgrid qua Azure.

Tên người dùng không phải là tên người dùng bạn đã thiết lập khi tạo đối tượng sendgrid trong azure. Để tìm tên người dùng của bạn;

  • Nhấp vào đối tượng sendgrid của bạn trong màu xanh và nhấp vào quản lý. Bạn sẽ được chuyển hướng đến trang SendGrid.
  • Xác nhận email của bạn và sau đó sao chép tên người dùng được hiển thị ở đó .. đó là tên người dùng được tạo tự động.
  • Thêm tên người dùng từ SendGrid vào cài đặt SMTP của bạn trong tệp web.config.

Hi vọng điêu nay co ich!


2
Điều này có vẻ ngớ ngẩn nhưng một điều khác mà bạn có thể muốn kiểm tra là mật khẩu có đúng cho thiết lập SMTP SendGrid hay không. Thiết lập của chúng tôi ban đầu hoạt động và sau đó một ngày chúng tôi bắt đầu nhận được thông báo ngoại lệ của OP. Các tìm kiếm trên WWW chủ yếu hướng đến việc xem xét các cấu hình Máy chủ SMTP khác nhưng cuối cùng thì mật khẩu không chính xác. Ai đó trong nhóm đã thay đổi mật khẩu trong tệp cấu hình thành một biến thể trong đó chữ cái đầu tiên không được viết hoa.
methon.dagger

1
Trong trường hợp của tôi, tên người dùng không chính xác và có lỗi đánh máy. Tuy nhiên, mật khẩu sai cũng có thể gây ra lỗi "Không thể đọc dữ liệu từ kết nối truyền tải: net_io_connectionclosed." lỗi. Vì vậy, hãy kiểm tra cả tên người dùng và mật khẩu. Và đối với người dùng Azure, tên người dùng có dạng "azure_guid-withoutdashes@azure.com" (ví dụ: azure_e9e062db4bfd491296bec77bcff49ed9@azure.com)
Raj Rao

10

Bạn cũng có thể phải thay đổi cài đặt "ứng dụng kém an toàn" trên tài khoản Gmail của mình. EnableSsl, sử dụng cổng 587 và bật "ứng dụng kém an toàn". Nếu bạn google phần ứng dụng kém an toàn hơn, có các trang trợ giúp của google sẽ liên kết bạn đến ngay trang dành cho tài khoản của bạn. Đó là vấn đề của tôi nhưng mọi thứ hiện đang hoạt động nhờ tất cả các câu trả lời ở trên.


Cảm ơn Bill. Điều này vẫn hoạt động với tài khoản gmail tiêu chuẩn của tôi. Nếu không sử dụng cài đặt "ứng dụng kém an toàn", bạn phải sử dụng xác thực 2 phần OAuth2. Điều này không thực tế khi bạn chỉ muốn gửi email xác nhận từ một trang web.
Dan Randolph

1
"Ứng dụng kém an toàn" đang ở đâu. Tôi đang ở trong tài khoản gmail của mình để tìm kiếm nó.
Sam

1
Tôi đã tìm thấy cài đặt "Ứng dụng kém an toàn hơn" - cài đặt này không nằm trong Cài đặt Gmail, mà trong Cài đặt tài khoản Google: Tài khoản của tôi> Đăng nhập và bảo mật myaccount.google.com/…
HFloyd 14/03/18

9

Tôi đã thử tất cả các câu trả lời ở trên nhưng vẫn gặp lỗi này với tài khoản Office 365. Mã dường như hoạt động tốt với tài khoản Google và smtp.gmail.com khi cho phép các ứng dụng kém an toàn hơn.

Bất kỳ đề xuất nào khác mà tôi có thể thử?

Đây là mã mà tôi đang sử dụng

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

CẬP NHẬT VÀ CÁCH TÔI GIẢI QUYẾT NÓ:

Đã giải quyết vấn đề bằng cách thay đổi Smtp Client thành Mailkit. Máy khách System.Net.Mail Smtp hiện không được Microsoft khuyến nghị sử dụng vì các vấn đề bảo mật và thay vào đó bạn nên sử dụng MailKit. Việc sử dụng Mailkit đã cung cấp cho tôi các thông báo lỗi rõ ràng hơn mà tôi có thể hiểu để tìm ra nguyên nhân gốc rễ của vấn đề (vấn đề giấy phép). Bạn có thể tải Mailkit bằng cách tải xuống dưới dạng Gói Nuget .

Đọc tài liệu về Smtp Client để biết thêm thông tin: https://docs.microsoft.com/es-es/dotnet/api/system.net.mail.smtpclient?redinticfrom=MSDN&view=netframework-4.7.2

Đây là cách tôi triển khai SmtpClient với 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

Thư viện SMTP của bạn có hỗ trợ kết nối được mã hóa không? Máy chủ thư có thể đang mong đợi kết nối TLS an toàn và do đó đóng kết nối mà không có bắt tay TLS


Nó chỉ là SmtpClientthư viện .NET mặc định , nó hỗ trợ mã hóa, máy chủ yêu cầu mã hóa và tôi đã thiết lập client.EnableSssl = true;. Mặc dù tôi nghĩ rằng tôi sẽ tiếp tục điều này xa hơn một chút với Wireshark.
Jake C

3

Nếu bạn đang sử dụng máy chủ SMTP trên cùng một hộp và SMTP của bạn được liên kết với địa chỉ IP thay vì "Bất kỳ được chỉ định", nó có thể không thành công vì nó đang cố sử dụng địa chỉ IP (như 127.0.0.1) mà SMTP hiện không hoạt động trên.


2

Để nâng cao những gì jocull được đề cập trong một nhận xét, tôi đã làm mọi thứ đề cập trong chủ đề này và nhấn mạnh ... bởi vì tôi đang ở trong một vòng lặp phải chạy đi chạy lại; sau lần đầu tiên thông qua vòng lặp, đôi khi nó sẽ không thành công. Luôn luôn làm việc lần đầu tiên thông qua vòng lặp.

Nói rõ hơn: vòng lặp bao gồm việc tạo SmtpClient và sau đó thực hiện .Send với đúng dữ liệu. SmtpClient được tạo bên trong một khối try / catch, để bắt lỗi và đảm bảo đối tượng đã bị phá hủy trước phần cuối của vòng lặp.

Trong trường hợp của tôi, giải pháp là đảm bảo rằng SmtpClient được xử lý sau mỗi lần trong vòng lặp (thông qua câu lệnh using () hoặc bằng cách xử lý thủ công). Ngay cả khi đối tượng SmtpClient đang bị phá hủy ngầm trong vòng lặp, .NET dường như vẫn để lại những thứ nằm xung quanh để xung đột với lần thử tiếp theo.



2

loại bỏ

client.UseDefaultCredentials = false; 

dường như giải quyết nó cho tôi.


1

Trong trường hợp nếu tất cả các giải pháp trên không hiệu quả với bạn thì hãy thử cập nhật tệp sau vào máy chủ của bạn (ý tôi là bằng cách xuất bản và một bản dựng trước đó sẽ hữu ích).

bin-> projectname.dll 

Sau khi cập nhật bạn sẽ thấy lỗi này. như tôi đã giải quyết bằng giải pháp này.


1
Thật ngạc nhiên là điều này đã làm việc cho tôi! Cho phép các ứng dụng không an toàn đã được bật và cổng đã được đặt thành 587.
TechyGypo 14/09/17

Cảm ơn, chỉ cần nhận ra tôi không phải là người duy nhất với vấn đề này. vui vẻ giúp đỡ.
Ajay Kumar

1

Trong trường hợp của tôi, khách hàng đã quên thêm địa chỉ IP mới trong cài đặt SMTP của họ. Mở IIS 6.0 trong máy chủ thiết lập smtp, nhấp chuột phải vào máy chủ ảo Smtp, chọn Thuộc tính, tab Access, nhấp vào Kết nối, thêm địa chỉ IP của máy chủ mới. Sau đó bấm Relay, cũng thêm địa chỉ IP của máy chủ mới. Điều này đã giải quyết vấn đề của tôi.


0

Hãy thử điều này: Đây là mã mà tôi đang sử dụng để gửi email cho nhiều người dùng.

 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
SmtpClientcũng là dùng một lần, vì vậy nó nên được bọc trong một usingkhối
jocull

0

Đối với triển vọng, hãy sử dụng cài đặt sau đây không gây ra lỗi cho tôi

Tên máy chủ SMTP smtp-mail.outlook.com

Cổng SMTP 587


0

Lỗi này rất chung chung, có thể do nhiều nguyên nhân như Máy chủ thư không chính xác. Một số công ty lưu trữ sử dụng định dạng mail.domainname. Nếu bạn chỉ sử dụng tên miền, nó sẽ không hoạt động. kiểm tra thông tin đăng nhập tên máy chủ tên người dùng mật khẩu nếu cần Kiểm tra với công ty lưu trữ.

<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

Trong trường hợp của tôi, IP máy chủ web đã bị chặn trên máy chủ thư, nó cần được công ty lưu trữ của bạn bỏ chặn và đưa nó vào danh sách trắng. Ngoài ra, sử dụng cổng cổng 587.


0

Nếu máy chủ thư của bạn là Gmail (smtp.google.com), bạn sẽ gặp lỗi này khi đạt đến giới hạn thư. Gmail chỉ cho phép gửi qua SMTP tối đa 2000 thư mỗi 24 giờ.


0

Tôi gặp sự cố này khi sử dụng smtp.office365.com, sử dụng cổng 587 với SSL. Tôi đã có thể đăng nhập vào tài khoản bằng portal.office.com và tôi có thể xác nhận tài khoản đã có giấy phép. Nhưng khi tôi kích hoạt mã để gửi email, tôi vẫn gặp lỗi net_io_connectionclosed.

Tôi đã mất một thời gian để tìm ra nó, nhưng quản trị viên Exchange đã tìm ra thủ phạm. Chúng tôi đang sử dụng O365 nhưng máy chủ Exchange ở trong một môi trường kết hợp. Mặc dù tài khoản chúng tôi đang cố gắng sử dụng đã được đồng bộ hóa với Azure AD và có giấy phép O365 hợp lệ, vì một số lý do mà hộp thư vẫn nằm trên máy chủ Exchange hỗn hợp - không phải Exchange trực tuyến. Sau khi quản trị viên trao đổi sử dụng lệnh "Move-Mailbox" để di chuyển hộp thư từ máy chủ trao đổi hỗn hợp sang O365, chúng tôi có thể sử dụng mã để gửi email bằng o365.


-1

Chuẩn bị: 1. HostA là máy chủ ảo SMTP với cổng mặc định 25 2. HostB là máy trạm mà tôi gửi mail bằng SmtpClient và mô phỏng mạng không ổn định mà tôi sử dụng vụng về

Trường hợp 1 Được đưa ra Nếu HostB là 2008R2 Khi tôi gửi email. Sau đó, vấn đề này xảy ra.

Trường hợp 2 Đưa ra Nếu HostB là phiên bản 2012 trở lên Khi tôi gửi email. Sau đó, thư đã được gửi đi.

Kết luận: Nguyên nhân gốc rễ này liên quan đến Windows Server 2008R2.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.