站长  发布于 2024-12-01 22:48:10  阅读(948)  点赞(2)  评论(0)

    最近准备给网站接入邮件通知功能,用的是阿里云的企业邮箱,本以为很快就能实现,但是最终花了将近两天的时间,遇到了各种坑和雷,特此记录,希望能帮助到有需要的朋友。

    一、邮件发送的各种端口:

    25端口:为SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)服务所开放的,是用于发送邮件,邮件内容不加密,安全性低;

    465端口:为SMTPS(SMTP-over-SSL)协议服务开放的,这是SMTP协议基于SSL安全协议之上的一种变种协议,它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。SMTPS和SMTP协议一样,也是用来发送邮件的,只是更安全些,防止邮件被黑客截取泄露,还可实现邮件发送者抗抵赖功能。防止发送者发送之后删除已发邮件,拒不承认发送过这样一份邮件;

   587端口:是STARTTLS协议的 属于TLS通讯协议 只是他是在STARTTLS命令执行后才对之后的原文进行保护的;

   二、阿里云企业邮箱及国内云服务器对25、465、587端口的支持:

   25端口:国内云服务器默认封禁,以阿里云服务器为例,如果你想开通,须要额外申请,解封参照帮助文档(https://help.aliyun.com/document_detail/56130.html);

   587端口:国内云服务可telnet smtp.qiye.aliyun.com 587通,但是国外及香港云服务器怎么都telnet不通;不知被哪里限制了实在不能理解,刚好我这用到了香港云服务器,被坑了一把;

   image.png

   465端口:国内、国外、香港云服务器都可以telnet smtp.qiye.aliyun.com 465通。

   综上避坑点1:25要申请解封,申请了还不一定能给你解封;587香港和国外服务器连接不通;最好用465端口;

   三、465端口的雷和坑

   一开始使用.net的System.Net.Mail来发送邮件,也选用的是465端口,EnableSsl设置为true,但是结果却是死活连不上服务器发送不了,最后一查发现System.Net.Mail不支持?你说坑不坑,.net自己的发邮件的库居然不支持?

    原因为:NET Framework的System.Net.Mail组件默认不支持Implicit SSL,而465端口通常使用Implicit SSL进行加密。因此,直接使用.NET Framework发送邮件时,可能会遇到不支持465端口的问题‌。阿里云企业邮箱推荐使用465端口进行加密传输。然而.NET Framework的SmtpClient类不支持Implicit SSL,导致无法通过465端口发送邮件‌。

   而.net官方还建议大家考虑使用如MailKit、MimeKit等第三方库代System.Net.Mail来发邮件,真的无语。

   最后没办法,我既不想云申请25端口解封和客服扯皮,提交了工单让他们处理香港服务器587端口不通的问题也半天没回复,只能用465端口,最后只能换成用MailKit来发了。

   四、发送邮件时的验证密码并不是邮箱密码

   发送邮件时验证密码不是邮箱密码,这个事我是知道的,因为以前用QQ邮箱等有经验,不过最终还是被坑了一把,真的是要吐槽一把阿里云企业邮箱的这个交互功能。验证密码申请的方式如下:

    1、使用账号密码登录阿里云企业邮箱后台:https://qiye.aliyun.com;

    2、进入设置->账户安全 找到三方客户端安全密码;    image.png

    3、点击生成新密码,输入账号密码后他就给你弹出了个新密码,还让你复制,如果你直接复制关闭窗口就懵逼了,那个密码复制出来根本没用,因为他这里还要你输个设置名再保存后才是真正的有效密码。我就在这被坑了一次。

    image.png

   最后分享一个发送邮件的帮助类:

using MailKit.Security;
using MimeKit;
using System.Net;
using MailKit.Net.Smtp;
using System.Net.Mail;

namespace CBC.Utility
{
    public class EmailHelper
    {
        /// <summary>
        /// 是否初始化
        /// </summary>
        private bool isInit=false;

        /// <summary>
        /// 邮箱对象
        /// </summary>
        private static EmailHelper self {get; set;}

        /// <summary>
        /// smtp
        /// </summary>
        private string smtp { get; set; }

        /// <summary>
        /// email
        /// </summary>
        private string email { get; set; }

        /// <summary>
        /// password
        /// </summary>
        private string password { get; set; }

        /// <summary>
        /// senderName
        /// </summary>
        private string senderName { get; set; }

        /// <summary>
        /// port
        /// </summary>
        private int port { get; set; }

        private EmailHelper()
        {
            smtp = "";
            email = "";
            password = "";
            senderName = "";
            port = 25;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        static EmailHelper()
        {
            self=new EmailHelper();
        }

        /// <summary>
        /// 初始华函数
        /// </summary>
        /// <param name="smtp"></param>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="senderName"></param>
        /// <param name="port"></param>
        public static void Init(string smtp, string email, string password, string senderName,int port)
        {
            self.isInit = true;
            if (!string.IsNullOrEmpty(smtp) && !string.IsNullOrEmpty(email) && !string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(senderName))
            {
                self.smtp = smtp;
                self.email = email;
                self.password = password;
                self.senderName = senderName;
                self.port = port;
            }
        }

        #region 发送邮件

        /// <summary>
        /// 简单发送邮件功能(支持25、587端口)
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="content">内容</param>
        /// <param name="toEmail">收件人</param>
        /// <returns></returns>
        public static Result<bool> SendMail(string title, string content,string toEmail)
        {
            Result<bool> ret = new Result<bool>();
            if (self.isInit)
            {
                if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(content))
                {
                    ret.Obj = false;
                    ret.Msg = "参数错误!";
                }
                try
                {
                    System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
                    client.Host = self.smtp;
                    client.UseDefaultCredentials = false;
                    client.Credentials = new System.Net.NetworkCredential(self.email, self.password);
                    //星号改成自己邮箱的密码
                    client.DeliveryMethod = SmtpDeliveryMethod.Network;
                    client.EnableSsl = true;
                    client.Port=self.port;
                    System.Net.Mail.MailMessage message = new MailMessage();
                    //填充发送者邮箱
                    string from = self.email;
                    MailAddress ad_from = new MailAddress(from, self.senderName);//发送人
                    message.From = ad_from;
                    message.To.Add(toEmail);
                    message.Subject = title;
                    message.Body = content;
                    message.BodyEncoding = System.Text.Encoding.UTF8;
                    message.IsBodyHtml = true;
                    client.Send(message);
                    ret.Obj = true;
                    ret.Msg = "发送成功!";
                    return ret;
                }
                catch (Exception ex)
                {
                    ret.Obj = false;
                    ret.Msg = "发送失败!" + ex.Message;
                }
            }
            else
            {
                ret.Obj = false;
                ret.Msg = "发送失败!请先初始化发件邮箱配置";
            }
            return ret;
        }

        /// <summary>
        /// MailKit 发送邮件功能 支持25、587、465端口
        /// </summary>
        /// <param name="title"></param>
        /// <param name="content"></param>
        /// <param name="toEmail"></param>
        /// <returns></returns>
        public static Result<bool> SendMailKit(string title, string content, string toEmail)
        {

            Result<bool> ret = new Result<bool>();
            if (self.isInit)
            {
                if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(content))
                {
                    ret.Obj = false;
                    ret.Msg = "参数错误!";
                    return ret;
                }
                MimeMessage message = new MimeMessage();
                message.From.Add(new MailboxAddress(self.senderName, self.email));
                message.To.Add(new MailboxAddress(toEmail, toEmail));
                message.Subject = title;
                BodyBuilder bodyBuilder = new BodyBuilder
                {
                    HtmlBody = content
                };
                message.Body = bodyBuilder.ToMessageBody();
                using (var client = new MailKit.Net.Smtp.SmtpClient())
                {
                    try
                    {
                        client.Connect(self.smtp, self.port, SecureSocketOptions.Auto);
                        client.Authenticate(self.email, self.password);
                        string result = client.Send(message);
                        ret.Obj = true;
                        ret.Msg = "发送成功!";
                    }
                    catch (Exception ex)
                    {
                        ret.Obj = false;
                        ret.Msg = "发送失败!" + ex.Message;
                    }
                    finally
                    {
                        client.Disconnect(true);
                    }
                }
                return ret;
            }
            else
            {
                ret.Obj = false;
                ret.Msg = "发送失败!请先初始化发件邮箱配置";
            }
            return ret;
        }

        #endregion
    }
}

    用法:

    1、在配置文件中加入以下配置

    "Smtp": "smtp.qiye.aliyun.com",

    "SmtpPort": 465,

    "Email": "邮箱地址",

    "EmailPassword": "邮箱密码",

    "SenderName": "发件人"

    2、使用前调用init方法初始化邮件信息,.net core 可以放在Program.cs当中:

//初始化邮件配置
string smtp= builder.Configuration.GetValue<string>("appSettings:Smtp");
string email= builder.Configuration.GetValue<string>("appSettings:Email");
string password= builder.Configuration.GetValue<string>("appSettings:EmailPassword");
string senderName = builder.Configuration.GetValue<string>("appSettings:SenderName");
int smtpPort = builder.Configuration.GetValue<int>("appSettings:SmtpPort");
EmailHelper.Init(smtp, email, password, senderName, smtpPort);

    3、最后在发送邮件的地方调用EmailHelper.SendMailKit(string title, string content,string toEmail)方法。

评论列表
发表评论
请填写昵称