Как отправить электронную почту через 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);
время ожидания:
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), но не поддерживает Implicit SSL (полное соединение завернуто в слой SSL)...
Ответы
Ответ 1
Вот пример того, как отправлять электронную почту через 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;
}
}
}
Ответ 2
Я опаздываю на эту вечеринку, но я предлагаю свой подход к любому прохожим, которые могут быть заинтересованы в альтернативе.
Как отмечено в предыдущих ответах, класс 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 в качестве протокола безопасности, все еще используя методы отправки почты, встроенные в фреймворк. Недостатком является то, что для этого требуется использование сторонней службы, которая может быть не полезной ни для чего, кроме этой конкретной функции.
Ответ 3
Он работает с 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);
Какова ваша точка зрения относительно использования устаревшего пространства имен?
Ответ 4
Попробуйте проверить эту бесплатную альтернативу с открытым исходным кодом
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 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);
}
}
Ответ 5
Если это неявный SSL, похоже, что он не может быть выполнен с помощью System.Net.Mail и пока не поддерживается.
http://blogs.msdn.com/webdav_101/archive/2008/06/02/system-net-mail-with-ssl-to-authenticate-against-port-465.aspx
Чтобы проверить, не является ли он неявным SSL, попробуйте this.
Ответ 6
Вы также можете подключиться через порт 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 через ошибки С#.Net во всех портах).
Надеюсь, это поможет!
Ответ 7
В 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 = "<html><body>Body Text"
builder.HtmlBody += "</body></html>"
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
Ответ 8
Для gmail эти параметры работали для меня, была необходима строка ServicePointManager.SecurityProtocol. Поскольку у меня есть настройка на 2 шага, мне нужен пароль для приложения из генератор паролей Google. SmtpClient mailer = new SmtpClient();
mailer.Host = "smtp.gmail.com";
mailer.Port = 587;
mailer.EnableSsl = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
Ответ 9
Я знаю, что присоединяюсь к обсуждению поздно, но я думаю, что это может быть полезно для других.
Я хотел избежать устаревших вещей, и после многих попыток я нашел простой способ отправить серверы, требующие неявного 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 или вообще никакой транспортной безопасности.
Ответ 10
Если у вас есть сомнения в этом коде, задайте ваши вопросы (здесь для номера порта Gmail 587)
// code to Send Mail
// Add following Lines in your web.config file
// <system.net>
// <mailSettings>
// <smtp>
// <network host="smtp.gmail.com" port="587" userName="[email protected]" password="yyy" defaultCredentials="false"/>
// </smtp>
// </mailSettings>
// </system.net>
// Add below lines in your config file inside appsetting tag <appsetting></appsetting>
// <add key="emailFromAddress" value="[email protected]"/>
// <add key="emailToAddress" value="[email protected]"/>
// <add key="EmailSsl" value="true"/>
// 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;
}