C# System.Net.Mail 类不支持465端口发送邮件
今天遇到特别恼人的bug,用System.Net.Mail 类 异步发送 邮件老是报错(我之前用python配置阿里云邮件服务,可以发送成功,而且很流畅)
看下代码
using System;
using System.ComponentModel;
using System.Net.Mail;
using System.Text;
// 邮件发送辅助静态类 异步
public static void SendMails(string MailTo, string Subject, string Body, Action errorcallback)
{
SmtpClient mailclient = new SmtpClient
{
//smtp服务器
Host = "smtpdm.aliyun.com",
// 是否加密
EnableSsl = true,
//smtp端口
Port = 465,
//发送方式
DeliveryMethod = SmtpDeliveryMethod.Network,
//用户名凭证
Credentials = new System.Net.NetworkCredential("发信账户", "password"),
};
//邮件信息
MailMessage message = new MailMessage
{
//发件人
From = new MailAddress("发信账户"),
};
//收件人
new MailAddress(MailTo, MailTo.ToString(), Encoding.UTF8);
//邮件标题编码
message.SubjectEncoding = Encoding.UTF8;
//主题
message.Subject = Subject;
//内容
message.Body = Body;
//正文编码
message.BodyEncoding = Encoding.UTF8;
//设置为HTML格式
message.IsBodyHtml = true;
//优先级
message.Priority = MailPriority.Normal;
//事件注册
mailclient.SendCompleted += (s1, e1) =>{ if (e1.Error != null){ errorcallback();}};
//异步发送
mailclient.SendAsync(message, message.To);
}
外部调用
// 外部调用
Task.Factory.StartNew(() =>
{
SendEmail.SendMails(user.Email, "半根蓝白博客注册帐号激活", sb.ToString(),
() =>
{
System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(Server.MapPath("~/data_log/"));
if (!dir.Exists)
dir.Create();
string _savefile = "~/data_log/SendEmailError_" + DateTime.Now.ToString("yyyyMMdd") + ".log";
System.IO.StreamWriter sw = new System.IO.StreamWriter(Server.MapPath(_savefile), true, Encoding.UTF8);
sw.WriteLine(sb);
sw.Close();
sw.Dispose();
});
});
因为是异步方法,所以一直看不到报错具体信息,通过断点调试,最后发现报错是 语法错误 命令不可用 服务器返回:
返回什么也看不到
经过长时间百度,谷歌
……………………………………
好像理解了,是用户名的格式问题,按照百度的说法,使用 邮件地址@符号前面(我使用的是阿里云邮件推送服务)的 我的 账户是 blog@bglb.work
所以,我把身份认证Credentials = new System.Net.NetworkCredential("发信账户", "password")
换成Credentials = new System.Net.NetworkCredential("blog", "password")
结果还是相同的语法错误 命令不可用 服务器返回:
有点恼人,经过长时间的谷歌 ,我最后决定,先把异步方法去掉,把代码换成了
using System;
using System.ComponentModel;
using System.Net.Mail;
using System.Text;
public static void SendMails(string MailTo, string Subject, string Body, Action errorcallback=null)
{
SmtpClient mailclient = new SmtpClient
{
//smtp服务器
Host = "smtpdm.aliyun.com",
// 是否加密
EnableSsl = true,
//smtp端口
Port = 465,
//发送方式
DeliveryMethod = SmtpDeliveryMethod.Network,
//用户名凭证
Credentials = new System.Net.NetworkCredential("发信账户", "password", "bglb.work"),
};
//邮件信息
MailMessage message = new MailMessage
{
//发件人
From = new MailAddress("发信账户"),
};
//收件人
new MailAddress(MailTo, MailTo.ToString(), Encoding.UTF8);
//邮件标题编码
message.SubjectEncoding = Encoding.UTF8;
//主题
message.Subject = Subject;
//内容
message.Body = Body;
//正文编码
message.BodyEncoding = Encoding.UTF8;
//设置为HTML格式
message.IsBodyHtml = true;
//优先级
message.Priority = MailPriority.Normal;
//事件注册
//mailclient.SendCompleted += (s1, e1) => { if (e1.Error != null) { errorcallback(); } };
//异步发送
//mailclient.SendAsync(message, message.To);
mailclient.Send(message);
}
外部调用代码
SendEmail.SendMails(user.Email, "半根蓝白博客注册帐号激活", sb.ToString())
经过调试,我又得到了一个离奇错误无法从传输连接中读取数据: net_io_connectionclosed。
又是一个漫长的谷歌 最后看到一篇博客说,好像不能指定多个发件人(我也没有啊) 只不过是用了一个list 但是里面确实只有一个用户啊
哎 ,再试试 修改 mailclient.Send(message);
为 mailclient.Send("blog@bglb.work", MailTo, message.Subject, message.Body);
; 满心欢喜的以为会看到 发送成功!结果 还是 相同的错误()无法从传输连接中读取数据: net_io_connectionclosed。
我就不信了,又是长时间的百度,谷歌,一篇博客中说,using System.Net.Mail;
属于System.dll v4.0.0.0 这个程序集,
System.Net.Mail 命名空间下的 SmtpClient 默认是不支持 SSL & 465 端口发送邮件的。虽然启用了 ssl 和465 端口,但是还是不能用的,啊!!!!! 炸了 一万句** 奉上 !
在给大家说一点:云服务器一般不支持25 端口 发送邮件,因为会有安全问题,都已经禁止使用了,而邮件发送的默认端口就是25,因此之后,大家都在使用 465 端口,或者587 端口,使用加密传送,启用Ssl,这也就是为什么我要使用 465 的原因
解决方法:
既然这个dll 不支持,那就换一个呗 ,C# 能发邮件的类库多了去了。
我之前使用一个废弃的类库 System.Web.Mail
这个在使用中可能会报一个错Web.Mail
已过时,但是不影响邮件的发送!,所以换一个吧。
下面给出一个简单的示例,这是我之前使用过的一个类库,没有任何问题
using MailKit.Net.Smtp;
using MimeKit;
using System;
/// <summary>
/// Mail 的摘要说明
/// </summary>
public class Mail
{
public Mail()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 使用 阿里云邮件服务获取qq邮件服务
/// </summary>
/// <param name="address"></param>
/// <param name="title"></param>
/// <param name="content"></param>
/// <returns></returns>
public static bool send(string address, string title, string content)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("发件人备注", "发信账户"));
message.To.Add(new MailboxAddress("收件人备注", address));
message.Subject = string.Format("邮件标题 ", title); //邮件标题
message.Body = new TextPart("plain")
{
Text = string.Format("{0}内容:{1} ", title, content)//邮件内容。
};
using (var client = new SmtpClient())
{
// For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
client.ServerCertificateValidationCallback = (s, c, h, e) => true;
client.Connect("smtpdm.aliyun.com", 465, true);// 取决与你发信账户的类型 一般的qq邮箱(需要开启授权码,以及smtp服务,密码也就是授权码了)使用 :"smtp.qq.com" 126邮箱类似等,类似
// Note: only needed if the SMTP server requires authentication
client.Authenticate("发信账户", "密码");
try
{
client.Send(message);//发送邮件
client.Disconnect(true);
return true;
}
catch (Exception ex)
{
return false;
throw ex;
}
}
}
}