本文讨论的不是发送邮件采用的技术,而是通过公司的一个项目()实践说说邮件引擎的架构,有不足和改进之处,欢迎同行批评指正. 
我们以前发送邮件的时候采用的方法就是,在页面里面触发进行发送,比如注册了会员,点了提交按钮之后,将会员数据插入到数据库,然后进行发送.这种方法虽然简单方便,但是有一个弱点,如果邮件发送失败,就不能重发了.因此,在我们项目中采用的方法是,将需要发送的邮件统一插入到一个邮件队列,然后由引擎来处理这个队列.具体的做法是,数据库设计: 
Win_EmailQueue(邮件队列表) 
QueueId    int   自动编号,主键Id 
ToEmail    nvarchar(100)  收件人 
Title      nvarchar(100)  邮件标题 
Content    ntext          邮件内容 
AddDate    datetime       添加时间 
TryTimes   int            错误重试次数 
LastSendTime datetime     最后一次发送的时间 
Status     int            状态:0 未发送 1 已经发送 
需要发送邮件的时候,如注册会员成功后,将邮件的内容插入到表中. 
邮件引擎可以用一个系统服务来完成,安装在Web服务器同一台服务器上面,也可以根据负载实际情况安装在另外一台服务器上面,减轻Web服务器负担.邮件引擎的任务是间隔一个时间(比如5秒),查询邮件队列,根据时间顺序发送邮件,为了降低引擎的负担,可以设置每次发送15封,当然这个数字要根据实际情况来配置. 
以下是处理队列和发送邮件的一些代码. 
 ///  
        /// 发送Email队列,来自   
        ///  
        public static void SendEmailQueue() 
        { 
            //取最新的15条未成功的进行发送。 
            string sql = "select top 15 * from Win_EmailQueue where Status=0 and ToEmail<>'' order by AddDate desc"; 
            DataTable dt = DbHelperSQL.Query(sql).Tables[0]; 
            for (int i = 0; i < dt.Rows.Count; i++) 
            { 
                string title = dt.Rows[i]["Title"].ToString(); 
                string content = dt.Rows[i]["Content"].ToString(); 
                string to = dt.Rows[i]["ToEmail"].ToString(); 
                string CreateTime = dt.Rows[i]["AddDate"].ToString(); 
                string QueueID = dt.Rows[i]["QueueID"].ToString(); 
                bool flag = EmailUtil.Send(title, to, content); 
                if (flag) 
                { 
      //发送成功,将Status设置为1 
                    sql = "update  Win_EmailQueue set Status=1 where QueueID=" + QueueID + ""; 
                } 
                else 
                { 
      //发送失败,将失败次数增加1 
                    sql = "update   Win_EmailQueue set TryTimes=TryTimes+1,LastSendTime='" + DateTime.Now.ToString() + "' where QueueID=" + QueueID + ""; 
                } 
                DbHelperSQL.ExecuteSql(sql); 
            } 
            dt.Dispose(); 
            //超过10次未成功的邮件,将不再发送 
            sql = "update  Win_EmailQueue set Status=1  where TryTimes>10"; 
            DbHelperSQL.ExecuteSql(sql); 
        } 
 ///  
        /// 执行发送操作,来自   
        ///  
        ///  
        public static bool Send(string title, string to, string content) 
        { 
            //来自配置项 
            string fromemail = System.Configuration.ConfigurationManager.AppSettings["SMTPUserName"]; 
            string smtpserver = System.Configuration.ConfigurationManager.AppSettings["SMTPServer"]; 
            string frompwd = System.Configuration.ConfigurationManager.AppSettings["SMTPPass"]; 
            string fromaddress = System.Configuration.ConfigurationManager.AppSettings["SMTPNickName"]; 
            MailMessage mail = new MailMessage(); 
            mail.From = new MailAddress(fromemail, fromaddress, Encoding.GetEncoding("gb2312"));//发件人的邮箱 
            mail.To.Add(new MailAddress(to));//收件人 
            mail.Subject = title;//主题 
            mail.Body = content;//内容 
            mail.IsBodyHtml = true; 
            mail.SubjectEncoding = Encoding.GetEncoding("gb2312"); 
            mail.BodyEncoding = Encoding.GetEncoding("gb2312"); 
            mail.IsBodyHtml = true; 
            mail.Priority = MailPriority.Normal; 
            SmtpClient sc = new SmtpClient(smtpserver);//发邮件的服务器  
            NetworkCredential nc = new NetworkCredential(fromemail, frompwd);//申请的帐户信息 
            sc.Credentials = nc; 
            bool successflag; 
            try 
            { 
                sc.Send(mail); 
                successflag = true; 
            } 
            catch 
            { 
                successflag = false; 
            } 
            return successflag; 
        } 
在虚拟主机中,也可以采用首页加载一个script页面,这个页面来充当邮件引擎.代码如下: 
ajax/ajaxm.aspx 
protected void Page_Load(object sender, EventArgs e) 
{ 
    try 
    { 
 Email.SendEmailQueue();  //发送邮件 
    } 
    catch (Exception ex) 
    { 
 Log.SaveException(ex);  //保存错误日志 
    } 
    Response.Write(" "); 
    Response.End(); 
} 
然后在首页或者内页,插入代码及可. 
                                         |