ASP.NET定时发送邮件总结

香港那边公司的市场部开会时要求我们这边实现一个定时发送邮件的功能,即在每天下午5点左右定时把今天已通过三审的订单信息发给市场部的经理,告诉他哪些订单已经通过了终审。平时只知道如何用.net发送邮件,但不知如何定时发送邮件。于是百度了一下,总结起来有以下那么三种:

(1)做一个winform 来定时发邮件。然后通过windows计划任务,设置为指定时间,每次自动运行,运行完毕后自动关闭。

(2)用sqlserver 数据库实现发邮件,用sqlserver实现发邮件的存储过程,然后制定一个作业,制定时间运行。

(3)在 Global.asax 文件里编程。事件:Application_Start。利用Time类编程。比如服务器1秒钟执行一次判断。

香港那边的公司的ERP糸统是BS模式,由于对方公司服务器环境条件的限制,我和我师傅决定用第三种方法。在编程之前,先介绍一下Global.asax文件里的几个方法。

protected void Application_Start(Object sender, EventArgs e)

{

//Application_start方法:请求 ASP.NET 应用程序中第一个资源(如页)时调用。在应用程序的生命周期期间仅调用一次

}

protected void Application_End(Object sender, EventArgs e)

{

//Application_end方法:在卸载应用程序之前对每个应用程序生命周期调用一次。

}

下面是具体的做法:

代码

protected void Application_Start(Object sender, EventArgs e)

{

Timer t = new Timer(60000);//设计时间间隔,如果一个小时执行一次就改为3600000 ,这里一分钟调用一次

t.Elapsed += new ElapsedEventHandler(t_Elapsed);

t.AutoReset = true;

t.Enabled = true;

}

private void t_Elapsed(object sender, ElapsedEventArgs e)

{

if (GetEmailContent.GetMailContent().Length == 0)

{

return;//如果没有通过三审的订单要发送,则返回不发送邮件

}

欢迎进入.NET社区论坛,与200万技术人员互动交流 >>进入
  int sendTime_Hour = Convert.ToInt32(ConfigurationManager.AppSettings["SendTime"].ToString());//假如是下午17:00分发送

int now_Hour = Convert.ToInt32(DateTime.Now.Hour.ToString());

int now_Minute = Convert.ToInt32(DateTime.Now.Minute.ToString());

int absolute = 1;//差距值,单位为分钟

if (((now_Hour == sendTime_Hour - 1) && (now_Minute >= 60 - absolute)) || ((now_Hour == sendTime_Hour) && (now_Minute <= absolute)))    //即在如果时间判断是落在16:59分至17:01分之间,那么就会调用下面的邮件发送方法

{

string subject = string.Format("CO Approve Report({0})", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));

string host = ConfigurationManager.AppSettings["MailHost"];

string from = ConfigurationManager.AppSettings["MailFrom"];

string to = ConfigurationManager.AppSettings["MailTo"];

string user = ConfigurationManager.AppSettings["MailUser"];

string password = ConfigurationManager.AppSettings["MailPassword"];

string content = GetEmailContent.GetMailContent();

try

{

OrderMail.Send(host, user, password, to, from, subject, content, null);//发送邮件的方法,改为你自己的邮件发送方法

}

catch (Exception ex)

{

throw new Exception(ex.Message);

}

}

}

如果一定要确精到分,可以设置相距时间为秒级,以及设置定时器的时间间隔为秒级,比如一秒调用一次t_Elapsed,但必须符合的一件条件是:定时器的时间间隔<2*absolute,absolute为差距值,见上面黄色背景的定义,具体多少以客户的要求为准,不满足这个条件的话不能实现在规定的时间段内调用邮件发送的方法。

好,代码编写完毕,测试没问题,下班再设置晚上9点收到邮件(理论值应是8点59至9点1分之间收到),当天发现没收到邮件,问题来了!为什么在上班的测试没问题,但下班后9点没收到邮件?网上查了一下,发觉自己还有个问题没考虑到:Application对象是有生命周期的,当网页没人访问或闲置过久,应用程序池会调用Application_End方法回收applicatioin里的对象资源,导致定时器无法工作。

解决方法:在IIS6.0以上版本设置IIS应用程序池的回收时间,默认好像是20分钟,可设置长一些,但不要太长,否则有可能出现网站假死的现象。当晚再测试,可以正式发送邮件!起码到现在已经用了两三个月,都能正常定时发送邮件。IIS5.0没有应用程序池,可以在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\ machine.config里面设置,具体设置可以参照:http://www.zhiweinet.com/jiaocheng/2008-07/1145.htm

还有,对于Applicatioin_Start方法,有很多人都会产生一个误解: Application_Start是第一个人访问网站时加载的,只会调用一次,以后都不会调用;Application_Start是第一个人访问网站时加载的,这个没错,前提是在它的生命周期内,有以下几个原因也会导致应用程序池重新启动,  即Application_Start可以再次被调用:

1)添加、修改或删除应用程序的 Bin 文件夹中的程序集。

2)添加、修改或删除 App_GlobalResources 或 App_LocalResources 文件夹中的本地化资源。

3)添加、修改或删除应用程序的 Global.asax 文件。

4)添加、修改或删除 App_Code 目录中的源代码文件。

5)添加、修改或删除配置文件配置。

6)添加、修改或删除 App_WebReferences 目录中的 Web 服务引用。

7)添加、修改或删除应用程序的 Web.config 文件。

附应用程序生命周期概述:http://www.cnblogs.com/adsiz/archive/2008/01/17/1042746.html

附.NET垃圾回收机制 :http://blog.csdn.net/lerit/archive/2009/08/16/4451287.aspx

附SqlServer发送邮件解决方法:http://www.cnblogs.com/yjmyzz/archive/2008/09/04/1284229.html

在正常情况下Application_Start只调用一次,这样就不会实例化无数个定时器而占用服务器的资源 ,还有个问题是定时器的时间间隔如果精确到秒级的话是否会占用很多的内存,吃内存是肯定会的,所以要根据具体的情况设置应用程序池的回收时间和加大定时器设定的时间间隔。

上面定时发送邮件的解决方法只是我个人的做法,可供参考,不见得是最好的方法。QQ邮箱与163邮箱都可以实现发送邮件的功能,大家可否讨论下他们是怎样实现的

posted @ 2011-03-15 10:34  爱军  阅读(1105)  评论(2编辑  收藏  举报