自己写个小Email发送组件玩

很多很多很多网站都需要发送邮件……

呃 其实更确切来说 有哪个网站是不需要给用户发送邮件的么?

用户激活,密码找回……呃 貌似只想到这两个 不过光是他们已经足够让很多很多很多网站需要一个发送Email的组件。奋斗


那么……怎么发呢?

作为使用.net来做私单的家伙们 这个答案貌似有点过于简单了。

System.Net.Mail名称空间就是MS已经封装好来专门给你干这个的,绝对傻瓜化大笑


参照下列简陋版本:

    /// <summary>
    /// 电子邮件的管理者对象
    /// </summary>
    public class EmailManager
    {
        /// <summary>
        /// 用默认的邮箱向指定邮箱发送email
        /// </summary>
        /// <param name="targetEmail">目标邮箱</param>
        /// <param name="nickname">目标昵称</param>
        /// <param name="title">标题</param>
        /// <param name="context">正文</param>
        public static void Send(string targetEmail, string nickname, string title, string context)
        {
            XElement e = XElement.Load(AppDomain.CurrentDomain.BaseDirectory + "/Content/Xml/email.xml");

            //设置客户端信息
            SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(e.Element("email").Value, e.Element("password").Value);
            client.EnableSsl = true;

            //创建email信息
            MailMessage message = new MailMessage(new MailAddress(e.Element("email").Value, "Magicvr")
                , new MailAddress(targetEmail, nickname));
            message.Subject = title;
            message.Body = context;

            //发送
            client.SendAsync(message, null);
        }
    }

下面是配套的XML文件:

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <email>ooxx@gmail.com</email>
  <password>ooxx</password>
</root>

是的 就这么简单 在任何想要发送邮件的地方调用静态方法Send就可以发送一封邮件 得意


听起来好像没错……

不过事情有没那么简单呢?

no

no no no安静

问题还大着呢


首先它是一个同步方法 我们知道 发送邮件是需要时间的 虽然只有几秒钟 不过 不管你在什么时候执行它 被卡个几秒的感觉总是相当囧的

还有 它的拓展性实在是太差了:只能用gmail的服务器,只能用一个固定的邮件(虽然已经使用了外部的XML,可以随时修改,但是一个终究就是一个……)


OK,所以我们需要解决的问题就三个。

第一:不能在发送邮件的时候卡住我们的主线程

第二、必须可以很方便地定义目标服务器

第三、必须可以很方便地定义邮件账户


Let's go奋斗


首先,姑且让我们无视第一个问题——我们把它留到后面去解决。

让我们看看2和3

核心只有两个字:方便

那么问题来了 怎么才能算是方便呢?

让我们来思考一下 你可能不愿意每次发邮件都打次账户和密码吧?也不愿意每次都声明一次我要用哪个哪个服务器的哪个哪个端口来发邮件对吧?

但是我们又得能用不同的账户+密码和服务器+端口啊

综上两点 答案已经很简单了:字典

——用一个简单明了的 key 来帮我们去填充复杂的 value 们


come on~

让我们给组件添加上这么两个文件:EmailAccount.xml 和 EmailClient.xml

格式分别如下:


EmailAccount.xml 

<?xml version="1.0" encoding="utf-8"?>
<root>
  <email>
    <key>test</key>
    <name>测试账户</name>
    <address>ooxx@gmail.com</address>
    <password>ooxx</password>
  </email>
</root>


EmailClient.xml

<?xml version="1.0" encoding="utf-8" ?>
<root>
  <client>
    <key>default</key>
    <host>smtp.gmail.com</host>
    <port>587</port>
  </client>
</root>

简单明了

一个用于存储我们要用的邮箱账户 一个用于存储我们要用的目标服务器的地址和端口

不过 只有它们还不够 因为……虽然说真的.net的linq to sql还真是蛮好用的 不过每次都要去直接操作那些XML节点 真想还是很坑爹哇很坑爹骂人

所以 我们需要两个对应的操作类来负责跟他们沟通


EmailAccount:

    /// <summary>
    /// 电子邮箱账户
    /// </summary>
    public class EmailAccount
    {
        #region 私有字段

        /// <summary>
        /// 数据存储对象所存储的路径
        /// </summary>
        private static string path = AppDomain.CurrentDomain.BaseDirectory + "/Content/Xml/EmailAccount.xml";

        /// <summary>
        /// 数据存储对象
        /// </summary>
        private static XElement e = XElement.Load(path);

        /// <summary>
        /// 账户列表
        /// </summary>
        private static List<Account> accounts = GetAccounts();

        #endregion

        #region 公开属性

        /// <summary>
        /// 账户列表
        /// </summary>
        public static List<Account> Accounts
        {
            get { return accounts; }
            set { accounts = value; }
        }

        #endregion

        #region 静态方法

        /// <summary>
        /// 保存对数据集的修改
        /// </summary>
        public static void Save()
        {
            e.Save(path);
        }

        /// <summary>
        /// 获取指定的账户
        /// </summary>
        /// <param name="key">账户名</param>
        /// <returns>返回指定的用户的封装</returns>
        public static Account GetAccount(string key)
        {
            return Accounts.FirstOrDefault(x => x.Key == key);
        }

        /// <summary>
        /// 添加新的Email账户
        /// </summary>
        /// <param name="key">账户名称</param>
        /// <param name="name">昵称</param>
        /// <param name="address">账户</param>
        /// <param name="password">密码</param>
        public static void SetAccount(string key, string name, string address, string password)
        {
            e.Add(new XElement("email"
                , new XElement("key", key)
                , new XElement("name", name)
                , new XElement("address", address)
                , new XElement("password", password)));
            Save();
            RefreshAccounts();
        }

        /// <summary>
        /// 删除已有的Email账户
        /// </summary>
        /// <param name="key">账户名称</param>
        public static void RemoveAccount(string key)
        {
            e.Element(key).Remove();
            Save();
            RefreshAccounts();
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 获取账户列表
        /// </summary>
        /// <returns>返回账户列表</returns>
        private static List<Account> GetAccounts()
        {
            return e.Elements("email").ToList().ConvertAll(x => new Account(x));
        }

        /// <summary>
        /// 刷新静态列表
        /// </summary>
        private static void RefreshAccounts()
        {
            accounts = GetAccounts();
        }

        #endregion

        #region 内嵌类型

        /// <summary>
        /// 账户
        /// </summary>
        public class Account
        {
            #region 私有字段

            /// <summary>
            /// 数据存储对象
            /// </summary>
            public XElement e;

            #endregion

            #region 公开属性

            /// <summary>
            /// 账户名称
            /// </summary>
            public string Key
            {
                get { return e.Element("key").Value; }
                set { e.Element("key").Value = value; }
            }

            /// <summary>
            /// 昵称
            /// </summary>
            public string Name
            {
                get { return e.Element("name").Value; }
                set { e.Element("name").Value = value; }
            }

            /// <summary>
            /// 账户
            /// </summary>
            public string Address
            {
                get { return e.Element("address").Value; }
                set { e.Element("address").Value = value; }
            }

            /// <summary>
            /// 密码
            /// </summary>
            public string Password
            {
                get { return e.Element("password").Value; }
                set { e.Element("password").Value = value; }
            }

            #endregion

            #region 构造方法

            /// <summary>
            /// 实例化一个新的账户
            /// </summary>
            /// <param name="e">数据存储对象</param>
            public Account(XElement e)
            {
                this.e = e;
            }

            #endregion
        }

        #endregion
    }

EmailClient:

    /// <summary>
    /// 电子邮件服务器
    /// </summary>
    public class EmailClient
    {
        #region 私有字段

        /// <summary>
        /// 数据存储对象所存储的路径
        /// </summary>
        private static string path = AppDomain.CurrentDomain.BaseDirectory + "/Content/Xml/EmailClient.xml";

        /// <summary>
        /// 数据存储对象
        /// </summary>
        private static XElement e = XElement.Load(path);

        /// <summary>
        /// 客户端列表
        /// </summary>
        private static List<Client> clients = GetClients();

        #endregion

        #region 公开属性

        /// <summary>
        /// 客户端列表
        /// </summary>
        public static List<Client> Clients
        {
            get { return clients; }
            set { clients = value; }
        }

        #endregion

        #region 静态方法

        /// <summary>
        /// 保存对数据集的修改
        /// </summary>
        public static void Save()
        {
            e.Save(path);
        }

        /// <summary>
        /// 获取指定的客户端
        /// </summary>
        /// <param name="key">客户端名</param>
        /// <returns>返回指定的用户的封装</returns>
        public static Client GetClient(string key)
        {
            return Clients.FirstOrDefault(x => x.Key == key);
        }

        /// <summary>
        /// 添加新的Email客户端
        /// </summary>
        /// <param name="key">客户端名称</param>
        /// <param name="host">目标主机的地址</param>
        /// <param name="port">目标主机的端口</param>
        public static void SetClient(string key, string host, int port)
        {
            e.Add(new XElement("email"
                , new XElement("key", key)
                , new XElement("host", host)
                , new XElement("port", port)));
            Save();
            RefreshClients();
        }

        /// <summary>
        /// 删除已有的Email客户端
        /// </summary>
        /// <param name="key">客户端名称</param>
        public static void RemoveClient(string key)
        {
            e.Element(key).Remove();
            Save();
            RefreshClients();
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 获取客户端列表
        /// </summary>
        /// <returns>返回客户端列表</returns>
        private static List<Client> GetClients()
        {
            return e.Elements("client").ToList().ConvertAll(x => new Client(x));
        }

        /// <summary>
        /// 刷新静态列表
        /// </summary>
        private static void RefreshClients()
        {
            clients = GetClients();
        }

        #endregion

        #region 内嵌类型

        /// <summary>
        /// 客户端
        /// </summary>
        public class Client
        {
            #region 私有字段

            /// <summary>
            /// 数据存储对象
            /// </summary>
            public XElement e;

            #endregion

            #region 公开属性

            /// <summary>
            /// 客户端名称
            /// </summary>
            public string Key
            {
                get { return e.Element("key").Value; }
                set { e.Element("key").Value = value; }
            }

            /// <summary>
            /// 目标主机的地址
            /// </summary>
            public string Host
            {
                get { return e.Element("host").Value; }
                set { e.Element("host").Value = value; }
            }

            /// <summary>
            /// 目标主机的端口
            /// </summary>
            public int Port
            {
                get { return Convert.ToInt32(e.Element("port").Value); }
                set { e.Element("port").Value = value.ToString(); }
            }

            #endregion

            #region 构造方法

            /// <summary>
            /// 实例化一个新的客户端
            /// </summary>
            /// <param name="e">数据存储对象</param>
            public Client(XElement e)
            {
                this.e = e;
            }

            #endregion
        }

        #endregion
    }

关于这两个类基本上就没什么需要的了 只不过是一些对于linq to xml的包装而已

如果懒的话甚至可以不用看 直接拷回去用……当然 记得把私有字段 path 改成你自己存储xml文件的位置


有了这个两个类 我们就可以很方便的用我们预先设定在XML文件里面的key来获取我们所想要的信息


然后,我们可以来处理一些核心的问题了。

首先,明确一点 我们并不想在处理其他一些事情的同时去同步地发送邮件(也没有这个必要)

第二,可有可能以后我们会想要在发邮件的同时做点什么(比如统计一些什么数据,附加一个审核模块,把发送成功的不成功的邮件在数据库分门别类地备份,等等)


如果只需要满足第一点 其实很简单

我们只需要一个委托:

        /// <summary>
        /// 发送动作的委托
        /// </summary>
        public delegate void SendHandler(IMessage message);

然后这样:

SendHandler sendHandler = new SendHandler(Send);
sendHandler.BeginInvoke(message, (result) => { }, null);

标准而简洁的异步编程 对吧?

不过为了系统的健壮和良好的拓展性 我们需要更麻烦一点的做法


我的思路是 开设一个临时的队列 主线程所有想要发送的邮件全部先寄存在它那里

然后Email组件的线程再来处理它们


首先是核心部分 它包括三个部分

1、接口 IMessage

2、类 Message

3、静态方法Send


接口 IMessage用于定义我们所要用来发送邮件的外部输入的信息应该是什么样子的

        /// <summary>
        /// 定义用于发送Email的信息的封装
        /// </summary>
        public interface IMessage
        {
            #region 实例方法

            /// <summary>
            /// 获取客户端信息
            /// </summary>
            /// <returns>返回客户端信息的实例</returns>
            SmtpClient GetClient();

            /// <summary>
            /// 获取Email信息
            /// </summary>
            /// <returns>返回Email信息的实例</returns>
            MailMessage GetMessage();

            #endregion
        }

它非常非常的简单:因为我们发邮件本身就只需要知道目标服务器和Email的内容就可以了 对吧

看看Send方法就足够直观了:

        /// <summary>
        /// 发送新邮件
        /// </summary>
        /// <param name="message">所要发送的信息</param>
        public static void Send(IMessage message)
        {
            //获取实例化对象
            SmtpClient client = message.GetClient();
            MailMessage _message = message.GetMessage();

            //发送
            client.Send(_message);
        }

获得目标服务器信息 => 获得邮件内容信息 => 发送(多简单 对吧~ 大笑


不过他们只是站着说话不腰疼的“领导” 事实还得我们自己去做

来吧 我们害得实现那个看起来很简单的接口……

        /// <summary>
        /// 用于发送Email的信息
        /// </summary>
        public class Message : IMessage
        {
            #region 私有字段

            /// <summary>
            /// 邮箱客户端
            /// </summary>
            private EmailClient.Client client = GetDefaultClient();

            /// <summary>
            /// 邮箱账户
            /// </summary>
            private EmailAccount.Account account = GetDefaultAccount();

            #endregion

            #region 公开属性

            /// <summary>
            /// 目标用户的邮箱地址
            /// </summary>
            public string Address { get; set; }

            /// <summary>
            /// 目标用户的昵称
            /// </summary>
            public string Nickname { get; set; }

            /// <summary>
            /// Email标题
            /// </summary>
            public string Title { get; set; }

            /// <summary>
            /// Email正文
            /// </summary>
            public string Context { get; set; }

            /// <summary>
            /// 邮箱客户端
            /// </summary>
            public EmailClient.Client Client
            {
                get { return client; }
                set { client = value; }
            }

            /// <summary>
            /// 邮箱账户
            /// </summary>
            public EmailAccount.Account Account
            {
                get { return account; }
                set { account = value; }
            }

            #endregion

            #region 构造方法

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            public Message()
            {
            }

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            /// <param name="address">目标用户的邮箱地址</param>
            /// <param name="nickname">目标用户的昵称</param>
            /// <param name="title">Email标题</param>
            /// <param name="context">Email正文</param>
            public Message(string address, string nickname, string title, string context)
            {
                this.Address = address;
                this.Nickname = nickname;
                this.Title = title;
                this.Context = context;
            }

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            /// <param name="address">目标用户的邮箱地址</param>
            /// <param name="nickname">目标用户的昵称</param>
            /// <param name="title">Email标题</param>
            /// <param name="context">Email正文</param>
            /// <param name="account">邮箱账户</param>
            public Message(string address, string nickname, string title, string context, string account)
            {
                this.Address = address;
                this.Nickname = nickname;
                this.Title = title;
                this.Context = context;

                EmailAccount.Account _account = EmailAccount.GetAccount(account);
                if (_account != null)
                {
                    this.Account = _account;
                }
            }

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            /// <param name="address">目标用户的邮箱地址</param>
            /// <param name="nickname">目标用户的昵称</param>
            /// <param name="title">Email标题</param>
            /// <param name="context">Email正文</param>
            /// <param name="client">客户端</param>
            /// <param name="account">邮箱账户</param>
            public Message(string address, string nickname, string title, string context, string client, string account)
            {
                this.Address = address;
                this.Nickname = nickname;
                this.Title = title;
                this.Context = context;

                EmailClient.Client _client = EmailClient.GetClient(client);
                if (_client != null)
                {
                    this.Client = _client;
                }
                EmailAccount.Account _account = EmailAccount.GetAccount(account);
                if (_account != null)
                {
                    this.Account = _account;
                }
            }

            #endregion

            #region 实例方法

            /// <summary>
            /// 获取客户端信息
            /// </summary>
            /// <returns>返回客户端信息的实例</returns>
            public SmtpClient GetClient()
            {
                SmtpClient client = new SmtpClient(this.Client.Host, this.Client.Port);
                client.UseDefaultCredentials = false;
                client.Credentials = new NetworkCredential(this.Account.Address, this.Account.Password);
                client.EnableSsl = true;

                return client;
            }

            /// <summary>
            /// 获取Email信息
            /// </summary>
            /// <returns>返回Email信息的实例</returns>
            public MailMessage GetMessage()
            {
                MailAddress To = new MailAddress(this.Address, this.Nickname);
                MailAddress From = new MailAddress(this.Account.Address, this.Account.Name);
                MailMessage message = new MailMessage(From, To);
                message.Subject = this.Title;
                message.Body = this.Context;

                return message;
            }

            #endregion

            #region 私有方法

            /// <summary>
            /// 获取默认的Email账户
            /// </summary>
            /// <returns>返回默认的Email账户的实例</returns>
            private static EmailAccount.Account GetDefaultAccount()
            {
                EmailAccount.Account account = EmailAccount.GetAccount("main");
                if (account == null) { account = EmailAccount.GetAccount("test"); }

                return account;
            }

            /// <summary>
            /// 获取默认的Email客户端
            /// </summary>
            /// <returns>返回默认的Email客户端的实例</returns>
            private static EmailClient.Client GetDefaultClient()
            {
                return EmailClient.GetClient("default");
            }

            #endregion
        }

所有所有的目的就在于获取足够的信息区实现接口所定义的两个GetXX方法

而且设计的重点就在于默认值和构造方法的重载来为我们实现“方便地切换不同账户和服务器对象”的要求


上述三者便是发送邮件的核心代码

接下来我们需要的就是邮件的队列和处理队列的一系列方法


首先当然是……队列吐舌头

        /// <summary>
        /// 用于临时存储新邮件的队列
        /// </summary>
        private static Queue<IMessage> messages = new Queue<IMessage>();

因为是非实时性的处理 所以先进先出还是客观必要的 大笑


然后我们当然还需要一个方法 用于在主线程中把消息扔进来

        /// <summary>
        /// 向发送队列交付待发送的新邮件
        /// </summary>
        /// <param name="message">所要发送的信息</param>
        public static void Call(IMessage message)
        {
            messages.Enqueue(message);
        }

但是 光是丢进来时不行的 我们得定时去处理它们

而定时处理又会产生一个问题 比如我们定时5秒处理一次 而某一次邮件比较多 5秒发不完 第二次执行又来了 那肯定会出问题

所以我们需要一个标记 告诉后来的家伙:hi 伙计 我在做着呢 你一边玩去~

        /// <summary>
        /// 标识发送程序是否正在运行
        /// </summary>
        private static bool IsProcessing = false;

处理的原则很简单:  假如没有“前贤”在处理的话 => 声明“我正在处理” => 发送队列中排在最前面的邮件 => 重复上一步动作 => 直到队列为空 => 声明“我已经处理完了” 

        /// <summary>
        /// 循环发送等待队列中的新邮件
        /// </summary>
        private static void Send()
        {
            if (!IsProcessing)
            {
                IsProcessing = true;

                while (messages.Count > 0)
                {
                    try
                    {
                        IMessage message = messages.Dequeue();
                        SendHandler sendHandler = new SendHandler(Send);
                        sendHandler.BeginInvoke(message, CallBack, null);
                    }
                    catch (Exception)
                    {
                        //写入系统log
                    }
                }

                IsProcessing = false;
            }
        }

以下是配套的委托和回调函数:

        /// <summary>
        /// 发送动作的委托
        /// </summary>
        public delegate void SendHandler(IMessage message);

        /// <summary>
        /// 发送邮件动作的异步回调方法
        /// </summary>
        /// <param name="result">异步返回的方法参数</param>
        private static void CallBack(IAsyncResult result)
        {
            //发送邮件成功后你想也要做的
        }

(关于异步编程不在本文的讨论范围之内 想要了解这个范畴的请自行google 大笑


然后,我们还需要给处理方法配上一个计时器(不然人家怎么直到什么时候应该工作呢?)

这个就不要太简单了:

        /// <summary>
        /// 处理等待队列中的邮件
        /// </summary>
        private static void Process()
        {
            double interval = 5 * 1000;
            Timer timer = new Timer(interval);

            timer.Elapsed += ((sender, e) =>
            {
                Send();
            });

            timer.Start();
        }

再再再然后 我们给整个组件配上一个单独的线程(为什么捏?因为……这样比较好 偷笑

        /// <summary>
        /// 向系统注册邮件处理进程
        /// </summary>
        public static void Wait()
        {
            //创建新线程
            System.Threading.Thread newThread = new System.Threading.Thread(() =>
            {
                Process();
            });

            //启动线程
            newThread.Start();
        }


好吧 以上是废话 单独的线程主要是我们设计上就是把它当做一个独立的“组件”看待的 它不应该跟其他东西搅和在一起

至于更多的东西 我们留待以后再说大笑


以下是完整的类代码:

    /// <summary>
    /// 电子邮件的帮助者对象
    /// </summary>
    public class EmailHelper
    {
        #region 私有字段

        /// <summary>
        /// 用于临时存储新邮件的队列
        /// </summary>
        private static Queue<IMessage> messages = new Queue<IMessage>();

        /// <summary>
        /// 标识发送程序是否正在运行
        /// </summary>
        private static bool IsProcessing = false;

        #endregion

        #region 静态方法

        /// <summary>
        /// 发送新邮件
        /// </summary>
        /// <param name="message">所要发送的信息</param>
        public static void Send(IMessage message)
        {
            //获取实例化对象
            SmtpClient client = message.GetClient();
            MailMessage _message = message.GetMessage();

            //发送
            client.Send(_message);
        }

        /// <summary>
        /// 向发送队列交付待发送的新邮件
        /// </summary>
        /// <param name="message">所要发送的信息</param>
        public static void Call(IMessage message)
        {
            messages.Enqueue(message);
        }

        /// <summary>
        /// 向系统注册邮件处理进程
        /// </summary>
        public static void Wait()
        {
            //创建新线程
            System.Threading.Thread newThread = new System.Threading.Thread(() =>
            {
                Process();
            });

            //启动线程
            newThread.Start();
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 循环发送等待队列中的新邮件
        /// </summary>
        private static void Send()
        {
            if (!IsProcessing)
            {
                IsProcessing = true;

                while (messages.Count > 0)
                {
                    try
                    {
                        IMessage message = messages.Dequeue();
                        SendHandler sendHandler = new SendHandler(Send);
                        sendHandler.BeginInvoke(message, CallBack, null);
                    }
                    catch (Exception)
                    {
                        //写入系统log
                    }
                }

                IsProcessing = false;
            }
        }

        /// <summary>
        /// 发送邮件动作的异步回调方法
        /// </summary>
        /// <param name="result">异步返回的方法参数</param>
        private static void CallBack(IAsyncResult result)
        {
            //什么也不做
        }

        /// <summary>
        /// 处理等待队列中的邮件
        /// </summary>
        private static void Process()
        {
            double interval = 5 * 1000;
            Timer timer = new Timer(interval);

            timer.Elapsed += ((sender, e) =>
            {
                Send();
            });

            timer.Start();
        }

        #endregion

        #region 内嵌接口

        /// <summary>
        /// 定义用于发送Email的信息的封装
        /// </summary>
        public interface IMessage
        {
            #region 实例方法

            /// <summary>
            /// 获取客户端信息
            /// </summary>
            /// <returns>返回客户端信息的实例</returns>
            SmtpClient GetClient();

            /// <summary>
            /// 获取Email信息
            /// </summary>
            /// <returns>返回Email信息的实例</returns>
            MailMessage GetMessage();

            #endregion
        }

        #endregion

        #region 内嵌类型

        /// <summary>
        /// 用于发送Email的信息
        /// </summary>
        public class Message : IMessage
        {
            #region 私有字段

            /// <summary>
            /// 邮箱客户端
            /// </summary>
            private EmailClient.Client client = GetDefaultClient();

            /// <summary>
            /// 邮箱账户
            /// </summary>
            private EmailAccount.Account account = GetDefaultAccount();

            #endregion

            #region 公开属性

            /// <summary>
            /// 目标用户的邮箱地址
            /// </summary>
            public string Address { get; set; }

            /// <summary>
            /// 目标用户的昵称
            /// </summary>
            public string Nickname { get; set; }

            /// <summary>
            /// Email标题
            /// </summary>
            public string Title { get; set; }

            /// <summary>
            /// Email正文
            /// </summary>
            public string Context { get; set; }

            /// <summary>
            /// 邮箱客户端
            /// </summary>
            public EmailClient.Client Client
            {
                get { return client; }
                set { client = value; }
            }

            /// <summary>
            /// 邮箱账户
            /// </summary>
            public EmailAccount.Account Account
            {
                get { return account; }
                set { account = value; }
            }

            #endregion

            #region 构造方法

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            public Message()
            {
            }

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            /// <param name="address">目标用户的邮箱地址</param>
            /// <param name="nickname">目标用户的昵称</param>
            /// <param name="title">Email标题</param>
            /// <param name="context">Email正文</param>
            public Message(string address, string nickname, string title, string context)
            {
                this.Address = address;
                this.Nickname = nickname;
                this.Title = title;
                this.Context = context;
            }

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            /// <param name="address">目标用户的邮箱地址</param>
            /// <param name="nickname">目标用户的昵称</param>
            /// <param name="title">Email标题</param>
            /// <param name="context">Email正文</param>
            /// <param name="account">邮箱账户</param>
            public Message(string address, string nickname, string title, string context, string account)
            {
                this.Address = address;
                this.Nickname = nickname;
                this.Title = title;
                this.Context = context;

                EmailAccount.Account _account = EmailAccount.GetAccount(account);
                if (_account != null)
                {
                    this.Account = _account;
                }
            }

            /// <summary>
            /// 实例化一个新的用于发送Email的信息
            /// </summary>
            /// <param name="address">目标用户的邮箱地址</param>
            /// <param name="nickname">目标用户的昵称</param>
            /// <param name="title">Email标题</param>
            /// <param name="context">Email正文</param>
            /// <param name="client">客户端</param>
            /// <param name="account">邮箱账户</param>
            public Message(string address, string nickname, string title, string context, string client, string account)
            {
                this.Address = address;
                this.Nickname = nickname;
                this.Title = title;
                this.Context = context;

                EmailClient.Client _client = EmailClient.GetClient(client);
                if (_client != null)
                {
                    this.Client = _client;
                }
                EmailAccount.Account _account = EmailAccount.GetAccount(account);
                if (_account != null)
                {
                    this.Account = _account;
                }
            }

            #endregion

            #region 实例方法

            /// <summary>
            /// 获取客户端信息
            /// </summary>
            /// <returns>返回客户端信息的实例</returns>
            public SmtpClient GetClient()
            {
                SmtpClient client = new SmtpClient(this.Client.Host, this.Client.Port);
                client.UseDefaultCredentials = false;
                client.Credentials = new NetworkCredential(this.Account.Address, this.Account.Password);
                client.EnableSsl = true;

                return client;
            }

            /// <summary>
            /// 获取Email信息
            /// </summary>
            /// <returns>返回Email信息的实例</returns>
            public MailMessage GetMessage()
            {
                MailAddress To = new MailAddress(this.Address, this.Nickname);
                MailAddress From = new MailAddress(this.Account.Address, this.Account.Name);
                MailMessage message = new MailMessage(From, To);
                message.Subject = this.Title;
                message.Body = this.Context;

                return message;
            }

            #endregion

            #region 私有方法

            /// <summary>
            /// 获取默认的Email账户
            /// </summary>
            /// <returns>返回默认的Email账户的实例</returns>
            private static EmailAccount.Account GetDefaultAccount()
            {
                EmailAccount.Account account = EmailAccount.GetAccount("main");
                if (account == null) { account = EmailAccount.GetAccount("test"); }

                return account;
            }

            /// <summary>
            /// 获取默认的Email客户端
            /// </summary>
            /// <returns>返回默认的Email客户端的实例</returns>
            private static EmailClient.Client GetDefaultClient()
            {
                return EmailClient.GetClient("default");
            }

            #endregion
        }

        #endregion

        #region 内嵌委托

        /// <summary>
        /// 发送动作的委托
        /// </summary>
        public delegate void SendHandler(IMessage message);

        #endregion
    }

在实际的项目中使用的时候需要在全局启动器中声明以下

——在web项目中就是项目的根目录下面的Global.asax文件里面的 Application_Start 方法


在方法中加上这样一句就可以了(选中的那行~):



在项目中需要发邮件的时候 只需要实例化一个Message的实例 然后执行Call方法就好

例如这样:



OK 

至此 一个小小的Email发送组件开发完成~

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值