Как отправить электронную почту через SSL SMTP с помощью .NET Framework?
Есть ли способ с .NET Framework отправлять почту через SMTP-сервер SSL на порт 465?
Обычный способ:
System.Net.Mail.SmtpClient _SmtpServer = new System.Net.Mail.SmtpClient("tempurl.org"); _SmtpServer.Port = 465; _SmtpServer.EnableSsl = true; _SmtpServer.Credentials = new System.Net.NetworkCredential("username", "password"); _SmtpServer.Timeout = 5000; _SmtpServer.UseDefaultCredentials = false; MailMessage mail = new MailMessage(); mail.From = new MailAddress(from); mail.To.Add(to); mail.CC.Add(cc); mail.Subject = subject; mail.Body = content; mail.IsBodyHtml = useHtml; _SmtpServer.Send(mail);
время вышло:
- SSLHandshakeException: нет альтернативных имен объектов
- Обновление для Mac OS X Lion 10.7.2 прерывает SSL
- javax.net.ssl.SSLException: Ошибка чтения: ssl = 0x9524b800: ошибка ввода-вывода во время системного вызова, сброс соединения с помощью одноранговой сети
- Как загрузить файл PKCS # 12 в OpenSSL программно?
- Как я могу работать с NET: ERR_CERT_AUTHORITY_INVALID в Chrome?
System.Net Verbose: 0 : [1024] SmtpClient::.ctor(host=ssl0.ovh.net, port=465) System.Net Information: 0 : [1024] Associating SmtpClient#64923656 with SmtpTransport#44624228 System.Net Verbose: 0 : [1024] Exiting SmtpClient::.ctor() -> SmtpClient#64923656 System.Net Information: 0 : [1024] Associating MailMessage#17654054 with Message#52727599 System.Net Verbose: 0 : [1024] SmtpClient#64923656::Send(MailMessage#17654054) System.Net Information: 0 : [1024] SmtpClient#64923656::Send(DeliveryMethod=Network) System.Net Information: 0 : [1024] Associating SmtpClient#64923656 with MailMessage#17654054 System.Net Information: 0 : [1024] Associating SmtpTransport#44624228 with SmtpConnection#14347911 System.Net Information: 0 : [1024] Associating SmtpConnection#14347911 with ServicePoint#51393439 System.Net.Sockets Verbose: 0 : [1024] Socket#26756241::Socket(InterNetwork#2) System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#26756241::Socket() System.Net.Sockets Verbose: 0 : [1024] Socket#23264094::Socket(InterNetworkV6#23) System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#23264094::Socket() System.Net.Sockets Verbose: 0 : [1024] Socket#26756241::Connect(20:465#337754884) System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#26756241::Connect() System.Net.Sockets Verbose: 0 : [1024] Socket#23264094::Close() System.Net.Sockets Verbose: 0 : [1024] Socket#23264094::Dispose() System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#23264094::Close() System.Net Information: 0 : [1024] Associating SmtpConnection#14347911 with SmtpPooledStream#14303791 System.Net.Sockets Verbose: 0 : [1024] Socket#26756241::Receive() System.Net.Sockets Verbose: 0 : [2404] Socket#26756241::Dispose() System.Net.Sockets Error: 0 : [1024] Exception in the Socket#26756241::Receive - A blocking operation was interrupted by a call to WSACancelBlockingCall System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#26756241::Receive() -> 0#0 System.Net Error: 0 : [1024] Exception in the SmtpClient#64923656::Send - Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall. System.Net Error: 0 : [1024] at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.DelegatedStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.Net.BufferedReadStream.Read(Byte[] buffer, Int32 offset, Int32 count) at System.Net.Mail.SmtpReplyReaderFactory.ReadLines(SmtpReplyReader caller, Boolean oneLine) at System.Net.Mail.SmtpReplyReaderFactory.ReadLine(SmtpReplyReader caller) at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port) at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port) at System.Net.Mail.SmtpClient.GetConnection() at System.Net.Mail.SmtpClient.Send(MailMessage message) System.Net Verbose: 0 : [1024] Exiting SmtpClient#64923656::Send() System.Net Information: 0 : [1024] Associating MailMessage#49584532 with Message#19699911
Я googled вокруг и обнаружил, что System.Net.Mail поддерживает соединения на порту 587 (порт по умолчанию для явного SSL, который запускает незашифрованный, затем выдает STARTDLS, затем переключается на зашифрованное соединение: RFC 2228), но не поддерживает неявный SSL (полное соединение упакован в слой SSL) …
- html5 Websocket с SSL
- HTTPS с NSURLConnection - NSURLErrorServerCertificateUntrusted
- Как включить поддержку TLS 1.2 в Android-приложении (работает на Android 4.1 JB)
- Не удалось добавить сертификат SSL при привязке к порту
- Как мне сделать TLS с BouncyCastle?
- Подтверждения IPN PayPal IPN с использованием процедур SSL: SSL3_READ_BYTES: сбой вызова подтверждения sslv3
- Как всегда разрешать небезопасное соединение для определенного URL-адреса в хроме?
- Использование HTTPS с REST в Java
Вот пример того, как отправлять электронную почту через GMail, который также использует SSL / 465. Незначительная настройка кода ниже должна работать!
using System.Web.Mail; using System; public class MailSender { public static bool SendEmail( string pGmailEmail, string pGmailPassword, string pTo, string pSubject, string pBody, System.Web.Mail.MailFormat pFormat, string pAttachmentPath) { try { System.Web.Mail.MailMessage myMail = new System.Web.Mail.MailMessage(); myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/smtpserver", "smtp.gmail.com"); myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/smtpserverport", "465"); myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/sendusing", "2"); //sendusing: cdoSendUsingPort, value 2, for sending the message using //the network. //smtpauthenticate: Specifies the mechanism used when authenticating //to an SMTP //service over the network. Possible values are: //- cdoAnonymous, value 0. Do not authenticate. //- cdoBasic, value 1. Use basic clear-text authentication. //When using this option you have to provide the user name and password //through the sendusername and sendpassword fields. //- cdoNTLM, value 2. The current process security context is used to // authenticate with the service. myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate","1"); //Use 0 for anonymous myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/sendusername", pGmailEmail); myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/sendpassword", pGmailPassword); myMail.Fields.Add ("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true"); myMail.From = pGmailEmail; myMail.To = pTo; myMail.Subject = pSubject; myMail.BodyFormat = pFormat; myMail.Body = pBody; if (pAttachmentPath.Trim() != "") { MailAttachment MyAttachment = new MailAttachment(pAttachmentPath); myMail.Attachments.Add(MyAttachment); myMail.Priority = System.Web.Mail.MailPriority.High; } System.Web.Mail.SmtpMail.SmtpServer = "smtp.gmail.com:465"; System.Web.Mail.SmtpMail.Send(myMail); return true; } catch (Exception ex) { throw; } } }
Я опаздываю на эту вечеринку, но я предлагаю свой подход к любому прохожим, которые могут быть заинтересованы в альтернативе.
Как отмечалось в предыдущих ответах, class System.Net.Mail
SmtpClient
не поддерживает неявный SSL . Он поддерживает Явный SSL , который требует небезопасного подключения к SMTP-серверу через порт 25 для согласования безопасности транспортного уровня (TLS). Здесь я рассказывал о своих муках с этой тонкостью.
Короче говоря, SMTP через порт Implict SSL 465 требует, чтобы TLS обсуждалась до подключения к SMTP-серверу. Вместо того, чтобы писать .Net SMTPS-реализацию, я обратился к утилите Stunnel . Это небольшая услуга, которая позволит перенаправить трафик на локальный порт на удаленный порт через SSL.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Stunnel использует части библиотеки OpenSSL, которая недавно имела громкий эксплойт, опубликованный во всех основных технических новостных медиа. Я считаю, что последняя версия использует исправленный OpenSSL, но, пожалуйста, используйте на свой страх и риск.
После установки утилиты небольшое дополнение к файлу конфигурации:
; Example SSL client mode services [my-smtps] client = yes accept = 127.0.0.1:465 connect = mymailserver.com:465
… инструктирует службу Stunnel перенаправить локальные запросы на порт 465 на мой почтовый сервер на порт 465. Это происходит через TLS, который удовлетворяет SMTP-серверу на другом конце.
Используя эту утилиту, следующий код успешно передаст через порт 465:
using System; using System.Net; using System.Net.Mail; namespace RSS.SmtpTest { class Program { static void Main( string[] args ) { try { using( SmtpClient smtpClient = new SmtpClient( "localhost", 465 ) ) { // <-- note the use of localhost NetworkCredential creds = new NetworkCredential( "username", "password" ); smtpClient.Credentials = creds; MailMessage msg = new MailMessage( "[email protected]", "[email protected]", "Test", "This is a test" ); smtpClient.Send( msg ); } } catch( Exception ex ) { Console.WriteLine( ex.Message ); } } } }
Таким образом, преимущество здесь заключается в том, что вы можете использовать Implict SSL и порт 465 в качестве протокола безопасности, все еще используя методы отправки почты, встроенные в структуру. Недостатком является то, что для него требуется использование сторонней услуги, которая может быть не полезной ни для чего, кроме этой конкретной функции.
Он работает с System.Web.Mail (который отмечен как устаревший):
private const string SMTP_SERVER = "http://schemas.microsoft.com/cdo/configuration/smtpserver"; private const string SMTP_SERVER_PORT = "http://schemas.microsoft.com/cdo/configuration/smtpserverport"; private const string SEND_USING = "http://schemas.microsoft.com/cdo/configuration/sendusing"; private const string SMTP_USE_SSL = "http://schemas.microsoft.com/cdo/configuration/smtpusessl"; private const string SMTP_AUTHENTICATE = "http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"; private const string SEND_USERNAME = "http://schemas.microsoft.com/cdo/configuration/sendusername"; private const string SEND_PASSWORD = "http://schemas.microsoft.com/cdo/configuration/sendpassword"; System.Web.Mail.MailMessage mail = new System.Web.Mail.MailMessage(); mail.Fields[SMTP_SERVER] = "tempurl.org"; mail.Fields[SMTP_SERVER_PORT] = 465; mail.Fields[SEND_USING] = 2; mail.Fields[SMTP_USE_SSL] = true; mail.Fields[SMTP_AUTHENTICATE] = 1; mail.Fields[SEND_USERNAME] = "username"; mail.Fields[SEND_PASSWORD] = "password"; System.Web.Mail.SmtpMail.Send(mail);
Какова ваша точка зрения относительно использования устаревшего пространства имен?
Попробуйте проверить эту бесплатную альтернативу с открытым исходным кодом https://www.nuget.org/packages/AIM. Она бесплатна для использования и с открытым исходным кодом и использует то же самое, что и System.Net.Mail. Для отправки электронной почты на неявный ssl портов вы можете использовать следующий код
public static void SendMail() { var mailMessage = new MimeMailMessage(); mailMessage.Subject = "test mail"; mailMessage.Body = "hi dude!"; mailMessage.Sender = new MimeMailAddress("[email protected]", "your name"); mailMessage.To.Add(new MimeMailAddress("[email protected]", "your friendd's name")); // You can add CC and BCC list using the same way mailMessage.Attachments.Add(new MimeAttachment("your file address")); //Mail Sender (Smtp Client) var emailer = new SmtpSocketClient(); emailer.Host = "your mail server address"; emailer.Port = 465; emailer.SslType = SslMode.Ssl; emailer.User = "mail sever user name"; emailer.Password = "mail sever password" ; emailer.AuthenticationMode = AuthenticationType.Base64; // The authentication types depends on your server, it can be plain, base 64 or none. //if you do not need user name and password means you are using default credentials // In this case, your authentication type is none emailer.MailMessage = mailMessage; emailer.OnMailSent += new SendCompletedEventHandler(OnMailSent); emailer.SendMessageAsync(); } // A simple call back function: private void OnMailSent(object sender, AsyncCompletedEventArgs asynccompletedeventargs) { if (e.UserState!=null) Console.Out.WriteLine(e.UserState.ToString()); if (e.Error != null) { MessageBox.Show(e.Error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (!e.Cancelled) { MessageBox.Show("Send successfull!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
Если это неявный SSL, похоже, он не может быть выполнен с помощью System.Net.Mail и пока не поддерживается.
Чтобы проверить, не является ли это неявным SSL, попробуйте это.
Вы также можете подключиться через порт 465, но из-за некоторых ограничений пространства имен System.Net.Mail вам, возможно, придется изменить свой код. Это связано с тем, что пространство имен не позволяет создавать неявные SSL-соединения. Об этом говорится в http://blogs.msdn.com/b/webdav_101/archive/2008/06/02/system-net-mail-with-ssl-to-authenticate-against-port-465.aspx .
Можно сделать неявные соединения, не используя теперь устаревшее пространство имен System.Web.Mail, но вам нужно получить доступ к Microsoft CDO (Collaborative Data Object). Я привел пример использования CDO в другом обсуждении ( GMail SMTP через ошибки C # .Net на всех портах ).
Надеюсь это поможет!
В VB.NET при попытке подключиться к порту SSL Rackspace на 465 я столкнулся с той же проблемой (требуется неявный SSL). Я использовал https://www.nuget.org/packages/MailKit/ для успешного подключения.
Ниже приведен пример сообщения электронной почты HTML.
Imports MailKit.Net.Smtp Imports MailKit Imports MimeKit Sub somesub() Dim builder As New BodyBuilder() Dim mail As MimeMessage mail = New MimeMessage() mail.From.Add(New MailboxAddress("", c_MailUser)) mail.To.Add(New MailboxAddress("", c_ToUser)) mail.Subject = "Mail Subject" builder.HtmlBody = "Body Text" builder.HtmlBody += "" mail.Body = builder.ToMessageBody() Using client As New SmtpClient client.Connect(c_MailServer, 465, True) client.AuthenticationMechanisms.Remove("XOAUTH2") ' Do not use OAUTH2 client.Authenticate(c_MailUser, c_MailPassword) ' Use a username / password to authenticate. client.Send(mail) client.Disconnect(True) End Using End Sub
Я знаю, что присоединяюсь к обсуждению поздно, но я думаю, что это может быть полезно другим.
Я хотел избегать устаревших вещей, и после многих попыток я нашел простой способ отправить серверы, требующие неявного SSL: использовать NuGet и добавить пакет MailKit в проект. (Я использовал VS2017 для установки .NET 4.6.2, но он должен работать на более низких версиях .NET …)
Тогда вам нужно будет сделать что-то вроде этого:
using MailKit.Net.Smtp; using MimeKit; var client = new SmtpClient(); client.Connect("server.name", 465, true); // Note: since we don't have an OAuth2 token, disable the XOAUTH2 authentication mechanism. client.AuthenticationMechanisms.Remove ("XOAUTH2"); if (needsUserAndPwd) { // Note: only needed if the SMTP server requires authentication client.Authenticate (user, pwd); } var msg = new MimeMessage(); msg.From.Add(new MailboxAddress("[email protected]")); msg.To .Add(new MailboxAddress("[email protected]")); msg.Subject = "This is a test subject"; msg.Body = new TextPart("plain") { Text = "This is a sample message body" }; client.Send(msg); client.Disconnect(true);
Конечно, вы также можете настроить его, чтобы использовать Явный SSL или вообще не иметь транспортной безопасности.
Для gmail эти параметры работали для меня, была необходима строка ServicePointManager.SecurityProtocol. Поскольку у меня есть настройка на 2 шага, мне нужно получить пароль приложения от генератора паролей Google . SmtpClient mailer = new SmtpClient(); mailer.Host = "smtp.gmail.com"; mailer.Port = 587; mailer.EnableSsl = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
Как указано в комментарии на
с System.Net.Mail, используйте порт 25 вместо 465:
Вы должны установить SSL = true и Port = 25. Сервер отвечает на ваш запрос от незащищенного 25, а затем выдает соединение с защищенным 465.
Если у вас есть какие-либо сомнения в этом коде, задайте ваши вопросы (здесь для gmail номер порта 587)
// code to Send Mail // Add following Lines in your web.config file // // // // // // // // Add below lines in your config file inside appsetting tag // // // // Namespace Used using System.Net.Mail; public static bool SendingMail(string subject, string content) { // getting the values from config file through c# string fromEmail = ConfigurationSettings.AppSettings["emailFromAddress"]; string mailid = ConfigurationSettings.AppSettings["emailToAddress"]; bool useSSL; if (ConfigurationSettings.AppSettings["EmailSsl"] == "true") { useSSL = true; } else { useSSL = false; } SmtpClient emailClient; MailMessage message; message = new MailMessage(); message.From = new MailAddress(fromEmail); message.ReplyTo = new MailAddress(fromEmail); if (SetMailAddressCollection(message.To, mailid)) { message.Subject = subject; message.Body = content; message.IsBodyHtml = true; emailClient = new SmtpClient(); emailClient.EnableSsl = useSSL; emailClient.Send(message); } return true; } // if you are sending mail in group private static bool SetMailAddressCollection(MailAddressCollection toAddresses, string mailId) { bool successfulAddressCreation = true; toAddresses.Add(new MailAddress(mailId)); return successfulAddressCreation; }