自己封装的一个支持回调和独立线程的异步发送邮件的类

经常看到有很多朋友在网上找发送邮件的代码,也经常有很多朋友问各种邮件发送中出的问题,

因此把自己写的一个邮件发送类整理了一下,贴出来,给大家参考借鉴。虽然这个代码不算完整,

但贵在简练实用,便于阅读和修改扩展,里面还包含了写日志的简练方法,非常实用。


特色:

 代码简洁短小,逻辑清晰,便于大家拓展修改。

支持群发,一封邮件指定多名接收人。

使用独立线程,不影响主程序运行。采用异步发送,最大程度降低系统消耗。

使用队列,对意外发送不成功邮件,可以重复发送,提高成功率。

支持回调,可以了解发送失败的详细错误信息,便于调试和修正。

支持错误日志,实时记录各种异常状况。


 
/*** 王海斌 2016-05-22 qq:443053303  版权所有,请勿传播 ***
 *
 * 邮件发送类
 *
 * 特色:
 * 1:独立线程,不影响主程序运行
 * 2:使用队列,对意外发送不成功邮件,可以重复发送,提高成功率
 * 3:支持回调,可以了解发送失败的详细错误信息,便于调试和修正
 * 4:错误日志,实时记录各种异常状况
 * 5:支持群发
 * 6:代码简洁,逻辑清晰,便于大家拓展修改
 *
 * 注意:
 * 1:该代码从项目中删减而来,一些安全、校验、特别处理等等业务代码,都过滤了,大家自己添加
 * 2:邮件回调方法里,可以探视多种发送邮件服务返回的消息,这里没写那么多,大家自己完善
 * 3:只开放日志方法、添加待发送邮件、发送邮件三个方法。
 * 4:日志方法和邮件发送方法,都可以独立使用
 * 5:邮件队列采用List<>模拟,简洁实用,发邮件足够
 * 6:该代码删减后未做测试,如有错漏,请与我联系
 *
 *** 王海斌 2016-05-22 qq:443053303  版权所有,请勿传播 ***/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Web;
using System.Linq;
using System.Threading;
namespace Common
{
    public class MyEmail
    {
        public string Subject { get; set; }
        public string Body    { get; set; }
        public string Tos     { get; set; }
        public string From    { get; set; }
        public int id         { get; set; }
        public int Status     { get; set; }//0:未发送,1:发送中,2:已发送,3:发送失败
        public int SendCnt    { get; set; }
        public MyEmail()
        {
            Status = 0;
            SendCnt = 0;
        }
    }
    public static class EMailHelper
    {
        #region 邮件静态属性
        private static string SmtpServer = "outlook.office365.com";      //邮件服务器
        private static string From = "testSend@hotmail.com";             //默认发件箱
        private static string Name = "Hotmail Tester";                   //默认发件箱名字
        private static string Password = "Test123";                      //默认发件箱密码
        private static int SmtpServerPort = 587;                         //邮件服务器端口
        private static int Timeout = 60000;                              //超时时间
        private static List<MyEmail> Mails = new List<MyEmail>();        //待发邮件列表
        private static bool IsRun = false;                               //发邮件线程是否启动
        #endregion
        #region 日志方法
        private static object LockObj = new object();
        private static string logPath = ConfigurationManager.AppSettings["LogPath"];
        public static bool WriteLog(string str)
        {
            lock (LockObj)
            {
                string fileName = System.DateTime.Now.ToLongDateString() + ".log";
                try
                {
                    if (!Directory.Exists(logPath))
                    {
                        Directory.CreateDirectory(logPath);
                    }
                    string nowTime = System.DateTime.Now.ToString();
                    StreamWriter sw = new StreamWriter(logPath + fileName, true);
                    sw.Write("【" + nowTime + "】" + str + "
");
                    sw.Flush();
                    sw.Close();
                    return true;
                }
                catch
                {
                    return false;
                }
            }
        }
        #endregion
        public static void Add(VivaEmail mail)
        {
            mail.id = Mails.Count < 1 ? 1 : Mails.Max(p => p.id) + 1;
            Mails.Add(mail);
            if (!IsRun)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(StartSend));
                IsRun = true;
            }
        }
        public static string Send(email)
        {
            var errMsg = "";
            try
            {
                var client = new SmtpClient(SmtpServer, SmtpServerPort);
                client.UseDefaultCredentials = true;
                client.Credentials = new NetworkCredential(From, Password);
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                client.EnableSsl = true;
                client.Timeout = Timeout;

                var mailMessage = new MailMessage();
                mailMessage.From = new MailAddress(From, Name, Encoding.UTF8);
                foreach (var to in email.tos)//抄送和密送人写法类似,如有需要,自己添加
                {
                     if (!string.IsNullOrWhiteSpace(to))
                     {
                         mailMessage.To.Add(to);
                     }
                }
                mailMessage.Subject = email.Subject;
                mailMessage.SubjectEncoding = Encoding.UTF8;
                mailMessage.Body = email.Body;
                mailMessage.IsBodyHtml = true;
                mailMessage.BodyEncoding = Encoding.UTF8;
                mailMessage.IsBodyHtml = true;
                mailMessage.Priority = MailPriority.High;

                object userState = mailMessage;
                client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
                client.SendAsync(mailMessage, email);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return errMsg;
        }

        private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
        {
            var mail = e.UserState as MyEmail;
            if (e.Error != null)
            {
                Log.WriteLog("邮件【" + mail.To + ":" + mail.Subject + "】发送失败!" + "
" + e.Error.Message);
                mail.Status = 3;
            }
            else
            {
                Mails.Remove(mail);
            }
        }
        private static void StartSend(object obj)
        {
            while (true)
            {
                var mail = Mails.FirstOrDefault(p => p.Status == 0 && p.SendCnt < 3);
                if (mail != null)
                {
                    if (!string.IsNullOrWhiteSpace(mail.Tos))
                    {
                        Send(mail);
                        mail.SendCnt += 1;
                        mail.Status = 1;
                    }
                    else
                    {
                        mail.Status = 3;
                    }
                }
                Thread.Sleep(500);
            }
        }
    } 
}

原文地址:https://www.cnblogs.com/foren/p/6009081.html