我怎样才能通过SSL与SMTP发送电子邮件?
有没有一种方法使用.NET Framework通过端口465上的SSL SMTP服务器发送电子邮件?
通常的方式:
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
我search了一下,发现System.Net.Mail支持端口587上的连接(显式SSL的默认端口启动未encryption,然后发出STARTDLS,然后切换到encryption连接:RFC 2228),但不支持隐式SSL(整个连接被包裹在一个SSL层)…
这里是一个如何通过也使用SSL / 465的GMail发送电子邮件的例子。 小调整下面的代码应该工作!
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; } } }
我迟到了这个派对,但是我会为任何可能对另一个select感兴趣的路人提供我的方法。
正如在以前的答案中指出的, System.Net.Mail
SmtpClient
类不支持隐式SSL 。 它支持显式SSL ,它需要通过端口25与SMTP服务器build立不安全的连接,以协商传输级别安全性(TLS)。 我在这里用这个微妙的东西来描述我的辛劳。
简而言之,通过Implict SSL端口465的SMTP需要在连接到SMTP服务器之前协商TLS。 而不是写一个.Net SMTPS实现,而是转向一个名为Stunnel的工具。 这是一项小型服务,可让您通过SSL将本地端口上的stream量redirect到远程端口。
免责声明:Stunnel使用OpenSSL库的一部分,最近在所有主要的科技新闻媒体上都有一个高调的漏洞利用。 我相信最新的版本使用补丁OpenSSL,但请使用您自担风险。
一旦该实用程序被安装了一小部分的configuration文件:
; 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( "joe@schmoe.com", "jane@schmoe.com", "Test", "This is a test" ); smtpClient.Send( msg ); } } catch( Exception ex ) { Console.WriteLine( ex.Message ); } } } }
所以这里的好处是你可以使用Implict SSL和端口465作为安全协议,同时仍然使用框架内置的发送邮件方法。 缺点是它需要使用第三方服务,除了这个特定的function外,其他的服务可能都没用。
它与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("you@gmail.com", "your name"); mailMessage.To.Add(new MimeMailAddress("yourfriend@gmail.com", "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命名空间就可以build立隐式连接,但必须访问Microsoft CDO(协作数据对象)。 我提供了一个如何在另一个讨论中使用CDO的示例( 通过所有端口上的C#.Net错误的GMail SMTP )。
希望这可以帮助!
在VB.NET中,当试图连接到465上的Rackspace的SSL端口时,我遇到了同样的问题(需要隐式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
对于gmail来说,这些设置适用于我,ServicePointManager.SecurityProtocol行是必要的。 因为我已经设置了两步validation,所以我需要从Google应用密码生成器获取应用密码 。 SmtpClient mailer = new SmtpClient(); mailer.Host = "smtp.gmail.com"; mailer.Port = 587; mailer.EnableSsl = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
我知道我join讨论的时间太晚,但我认为这对其他人可能有用。
我想避免弃用的东西,经过大量的摆弄,我发现一个简单的方法发送到服务器需要隐式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("sender@ema.il")); msg.To .Add(new MailboxAddress("target@ema.il")); 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端口号是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="xxx@gmail.com" password="yyy" defaultCredentials="false"/> // </smtp> // </mailSettings> // </system.net> // Add below lines in your config file inside appsetting tag <appsetting></appsetting> // <add key="emailFromAddress" value="xxxx@gmail.com"/> // <add key="emailToAddress" value="xxxxxxx@gmail.com"/> // <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; }