C# 邮件服务

442 阅读5分钟

一、程序来发送邮件必要信息

Smtp服务器:发送邮件的服务器,如常见的smtp.163.com、smtp.qq.com,不同的服务商,发送邮件的服务器也不相同

账号:发送邮件的邮箱账号

密码:邮箱密码或授权码(注:当你在程序中使用邮箱密码进行发邮件,发现无法发送等问题,就要考虑邮箱是否开启了SMTP权限,是不是需 要使用授权码进行发邮件,像qq、163邮箱,这些邮箱是需要先开启SMTP发送邮件的权限,当开启后,会产生一个授权码,这时第三方就可以使用邮件账号加授权码来实现发送邮件功能)

端口:25、587和465。不同的端口号用于不同的目的,因此在配置邮箱的SMTP端口号时,需要选择适合您需求的端口号。

二、不同邮件服务商的支持协议的区别

邮箱smtp服务器支持的协议(可能有遗漏)
gmailsmtp.gmail.comTLS/ STARTTLS(TLS)
qqsmtp.qq.comSSL/TLS/ STARTTLS(TLS)
foxmailsmtp.exmail.qq.comSSL/TLS/ STARTTLS(TLS)
outlooksmtp-mail.outlook.comSTARTTLS(TLS)
雅虎smtp.mail.yahoo.comTLS/STARTTLS(TLS)
网易163smtp.163.comSSL/TLS
hotmailsmtp.live.comSTARTTLS(TLS)
icloudsmtp.mail.me.comSTARTTLS(TLS)
Yandexsmtp.yandex.ruSSL/TLS/STARTTLS(SSL/TLS)
GMXsmtp.gmx.comTLS/STARTTLS
新浪smtp.sina.comSSL/TLS/STARTTLS(SSL/TLS)
aolsmtp.aol.comTLS/STARTTLS
rediffsmtp.rediffmail.comSSL/TLS/STARTTLS(SSL/TLS)

由于不同的协议,所以在选中开放的端口时要注意一般都是采用587端口作为开放端口,但是有的服务商不支持STARTTLS协议,所以就用25端口或者465端口。

三、邮件发送限制

邮件服务商发送限制收件人限制
网易企业邮箱单个用户每天最多只能发送 1000 封邮件单个邮件最多包含 500 个收件人邮箱地址
163VIP邮箱每天限制最多能发送800封邮件单个邮件最多包含 500 个收件人邮箱地址
163 、 126 、 yeah 的邮箱每天发送限额为 50 封一封邮件最多发送给 40 个收件人
尚易企业邮箱一个 IP 一分钟最多发送 400 个邮件地址一封邮件最多 200 个邮件地址(如果一封邮件包括 200 个收信人地址,一分钟最多不能超过 2 封邮件;如果一封邮件只有一个收信人地址 , 一分钟发送的邮件不能超过 6 封)
QQ邮箱(2G 的普通用户)每天最大发信量是 100 封
QQ邮箱(3G 会员、移动 QQ 、 QQ 行及 4G大肚邮)每天最大发信量是 500 封
Foxmail 免费邮箱每天发送量限制为 50 封
Gmail邮箱每天 500 封(新申请的邮箱,限制 50 封)
新浪邮箱(企业邮箱试用期)每天限制 80 封
新浪免费邮箱每天限制发送 50 封
雅虎免费邮箱每小时发送量限制为100封;每天发送量限制为 200 封
阿里企业邮箱(免费版本)每天500封信

四、邮件发送方法

1、基于System.Net.Mail.MailMessage 发送邮件

  /// <summary>
     /// 发送邮件
     /// </summary>
     /// <param name="email">收件人邮箱</param>
     /// <param name="title">标题</param>
     /// <param name="content">发送内容</param>
     /// <returns></returns>
     public static bool SendEmail(string email,string title,string content)
     {
         string _smtpServer = "smtp.163.com";   //SMTP服务器
         string _userName = "test@163.com";   //邮箱
         string _pwd = "test";   //密码或授权码
 ​
         if(_smtpServer == "" || _userName == "" || _pwd == "") {
             return false;
         }
         
         using(System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage()) {
             /*   
            * msg.To.Add("b@b.com");可以发送给多人   
            */
             msg.To.Add(email);  //设置收件人
 ​
             /*  
             * msg.CC.Add("c@c.com");   
             * msg.CC.Add("c@c.com");可以抄送给多人   
             */
 ​
             /* 3个参数分别是 发件人地址(可以随便写),发件人姓名,编码*/
             msg.From = new MailAddress(_userName,_userName,System.Text.Encoding.UTF8);
 ​
 ​
             msg.Subject = title; //邮件标题   
             msg.SubjectEncoding = System.Text.Encoding.UTF8; //邮件标题编码   
             msg.Body = content;  //邮件内容   
             msg.BodyEncoding = System.Text.Encoding.UTF8;//邮件内容编码   
             msg.IsBodyHtml = true; //是否是HTML邮件   
             msg.Priority = MailPriority.Normal; //邮件优先级
 ​
             SmtpClient client = new SmtpClient(_smtpServer,587); //邮件服务器地址及端口号
             client.EnableSsl = true; //ssl加密发送
             client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
             client.Credentials = new System.Net.NetworkCredential(_userName,_pwd); //邮箱账号  密码
             client.Timeout = 6000;  //6秒超时
 ​
             try {
                 client.Send(msg);  //发送邮件
 ​
                 client.Dispose();  //释放资源
                 return true;
             } catch(System.Net.Mail.SmtpException ex) {
                 return false;
             }
         }
     }
 ​

缺点:该方法如果采用163邮箱加密发送,会发送失败,需要设置 client.EnableSsl = false ,端口设置为25,因为System.Net.Mail只支持显式SSL(ExplicitSSL),但是不支持隐式SSL(Implicit SSL),所以会造成163邮箱发送超时的问题,可以使用下面的发送邮件函数来解决。

注:如果线上环境用的是阿里的服务器,阿里云为了反垃圾邮件,25端口是封掉的,也就是说,如果你要使用阿里服务器发送邮件,25端口是走不通的,必须使用其他端口发送邮件, 这个时候就要用到加密端口发送邮件。如果你的项目有发送邮件的功能,且在测试服务器上发邮件是正常的,部署到阿里云之后就不行了, 这个时候就要想到是不是服务器端口的问题。

2、基于System.Web.Mail 发送邮件(用于解决163邮箱加密发送超时问题,该函数微软已弃用,如果不是特殊情况,不推荐使用该函数)

     /// <summary>
     /// 发送邮件
     /// </summary>
     /// <param name="emails">收件人的邮箱</param>
     /// <param name="title">邮件标题</param>
     /// <param name="content">邮件内容(支持Html)</param>
     public static bool SendEmailBack(List<string> emails,string title,string content)
     {
         string _smtpServer = "smtp.163.com";    //发邮件smtp服务器名称              
         string _userEmail = "test@163.com"; //发送人邮箱地址               
         string _pwd = "test";               //发邮件邮箱的密码或授权码
 ​
         System.Web.Mail.MailMessage _msg = new System.Web.Mail.MailMessage();
         //邮件主题
         _msg.Subject = title;
         _msg.BodyFormat = System.Web.Mail.MailFormat.Html;
         //邮件正文
         _msg.Body = content;
         //正文编码
         _msg.BodyEncoding = Encoding.UTF8;
         //优先级
         _msg.Priority = System.Web.Mail.MailPriority.Normal;
         //发件者邮箱地址
         _msg.From = _userEmail;
         //收件人收箱地址
         string _toEmail = "";
         emails.ForEach(s => { _toEmail += s + ","; });
 ​
         //_msg.Cc = _toEmail.TrimEnd(',');   //抄送
         _msg.To = _toEmail.TrimEnd(',');   //收件人
         
         _msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate","1");
         //用户名
         _msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername",_userEmail);
         //密码
         _msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword",_pwd);
         //端口
         _msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport",465);
         //是否ssl
         _msg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl",true);
         //Smtp服务器
         System.Web.Mail.SmtpMail.SmtpServer = _smtpServer;
 ​
         try {
             System.Web.Mail.SmtpMail.Send(_msg);
             return true;
         } catch(SmtpException e) {
             return false;
         }
     }

总结

显式SSL通过25端口连接 -> StartTLS(开始加密)-> 验证 -> 发送数据

隐式SSLStartSSL(开始加密) -> 连接 -> 验证 -> 发送数据

在采用邮件发送时,需要根据邮件服务商支持的协议,开放对应的端口