asp.net定時傳送郵件總結

iDotNetSpace發表於2010-01-08
       香港那邊公司的市場部開會時要求我們這邊實現一個定時傳送郵件的功能,即在每天下午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;//如果沒有通過三審的訂單要傳送,則返回不傳送郵件
        }
        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郵箱都可以實現傳送郵件的功能,大家可否討論下他們是怎樣實現的。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-624690/,如需轉載,請註明出處,否則將追究法律責任。

相關文章