定时发送邮件

(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;//如果沒有通過三審的訂單要發送,則返回不發送郵件
        }
        
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只调用一次,这样就不会实例化无数个定时器而占用服务器的资源 ,还有个问题是定时器的时间间隔如果精确到秒级的话是否会占用很多的内存,吃内存是肯定会的,所以要根据具体的情况设置应用程序池的回收时间和加大定时器设定的时间间隔。

你可能感兴趣的:(发送邮件)