ASP.NET自動傳送郵件功能的實現
有時我們需要在網站中加入傳送郵件的功能,例如一個網上投稿系統,當稿件被採用的時候傳送郵件通知作者。下面就以這個功能為例說明如何實現自動傳送郵件。
實現傳送郵件功能
首先說一下在.Net下如何傳送郵件。.Net已經為我們準備好了與傳送郵件相關的類,只要直接呼叫即可,非常方便。下面是我自己寫的一個郵件通知類:
///
/// 郵件通知服務類。
///
public class EmailNotificationService {
///
/// 構造一個郵件通知服務類的例項。
///
/// SMTP伺服器的IP地址
/// 是否使用SSL連線SMTP伺服器器
/// SMTP伺服器埠
/// 用於登入SMTP伺服器的使用者名稱
/// 登入密碼
public EmailNotificationService(
string smtpService,
bool enableSSL,
int port,
string loginName,
string password) {
this.m_smtpService = smtpService;
this.m_loginName = loginName;
this.m_password = password;
this.m_enableSSL = enableSSL;
this.m_port = port;
}
private readonly string m_smtpService;
private readonly string m_loginName;
private readonly string m_password;
private readonly bool m_enableSSL;
private readonly int m_port;
///
/// 傳送郵件通知到指定的EMAIL地址。
///
/// 顯示在“發件人”一欄上的名稱
/// 目的EMAIL地址
/// 郵件標題
/// 郵件內容
public void SendTo(string senderName, string address, string title, string content) {
MailMessage mail = new MailMessage();
mail.To.Add(address);
mail.From = new MailAddress(this.m_loginName, senderName, Encoding.UTF8);
mail.Subject = title;
mail.Body = content;
mail.BodyEncoding = Encoding.UTF8;
mail.IsBodyHtml = false;
mail.Priority = MailPriority.Normal;
SmtpClient smtp = new SmtpClient();
smtp.Credentials = new NetworkCredential(this.m_loginName, this.m_password);
smtp.Host = this.m_smtpService;
smtp.EnableSsl = this.m_enableSSL;
smtp.Port = this.m_port;
smtp.Send(mail);
}
}
在使用時,首先構造一個EmailNotificationService類,再呼叫SendTo方法即可。例如:
EmailNotificationService mailNotificationService = new EmailNotificationService("smtp.gmail.com", true, 587, "LoginName@gmail.com", "LoginPassword");
mailNotificationService.SendTo("SenderName", "TargetAddress@qq.com", "Title", "Content");
傳送郵件實現方案
上面建立好了一個負責傳送郵件的類,接下來的問題是應該在什麼時候呼叫這個類。傳送電子郵件需要進行網路通訊,耗時比較多,而且SmtpClient的Send方法是會阻塞呼叫執行緒的,一旦呼叫了該方法,就要等到郵件傳送完畢或出錯才能結束方法呼叫,所以不能將對EmailNotificationService的呼叫放在ASP.NET頁面的程式碼中。如果這麼做,客戶端就要等待很長時間才能獲得響應,使用者體驗是比較差的。
SmtpClient還有一個SendAsync方法,該方法與Send方法的區別是,SendAsync是非同步的,呼叫該方法之後會產生一個新的執行緒來負責傳送郵件,之後呼叫執行緒立即返回,不會再等待郵件傳送結束。那麼我們是不是可以用SendAsync代替Send,並在頁面程式碼中呼叫呢?答案是否定的,雖然客戶端可以很快獲得相應,但郵件根本沒有傳送出去。這是由ASP.NET頁面生命週期的特性決定的,客戶端向伺服器的每一次請求,頁面都會經歷一個由產生到銷燬的過程,當頁面銷燬的時候,負責傳送郵件的執行緒還沒有完成傳送郵件的工作就被強制結束了。
由於ASP.NET頁面生命週期的特性,我們不能將呼叫程式碼放在頁面的程式碼中。我們需要一個與頁面無關的執行緒,一個在網站執行時始終存在的執行緒。我的方案是使用一個全域性物件來管理一個髮送郵件執行緒,同時維護一個待傳送郵件連結串列。當全域性物件建立的時候,連結串列中沒有任何內容,傳送郵件執行緒處於掛起狀態。當某個頁面中的處理需要傳送電子郵件時,就將與傳送郵件相關的資訊新增到待傳送郵件連結串列中。此時連結串列不為空,傳送郵件執行緒開始工作,逐個取出連結串列中的郵件資訊併傳送,一直到連結串列為空,再次進入掛起狀態。如此迴圈反覆。
實現傳送郵件功能
基本的構思已經確定好了,接下來就是寫程式碼實現了。首先定義一個類來封裝待傳送郵件的相關資訊,本文開頭已經說過要以一個網上投稿系統作為例子,所以這裡所用的資訊與該應用有關。
///
/// 封裝傳送郵件時所需資訊的類。
///
public class MailNotifyInfo {
///
/// 獲取或設定稿件的標題。
///
public string Title {
get;
set;
}
///
/// 獲取或設定稿件的作者名稱。
///
public string Author {
get;
set;
}
///
/// 獲取或設定作者的電子郵件地址。
///
public string EmailAddress {
get;
set;
}
///
/// 獲取或設定稿件的狀態。
///
public ArticleStatus ArticleStatus {
get;
set;
}
}
然後是全域性物件類的定義,我使用了單件模式來實現其全域性性。
///
/// 處理郵件傳送功能的類。
///
public class NotificationHandler {
///
/// 該類的靜態例項。
///
private static readonly NotificationHandler g_instance = new NotificationHandler();
///
/// 獲取該類的唯一例項。
///
public static NotificationHandler Instance {
get {
return g_instance;
}
}
///
/// 預設構造方法。
///
private NotificationHandler() {
this.m_lockObject = new object();
this.m_mailNotifyInfos = new LinkedList
this.m_threadEvent = new ManualResetEvent(false);
this.m_workThread = new Thread(this.ThreadStart);
this.m_workThread.Start();
}
private readonly LinkedList
private readonly Thread m_workThread;
private readonly ManualResetEvent m_threadEvent;
private readonly Object m_lockObject;
///
/// 新增待傳送郵件的相關資訊。
///
public void AppendNotification(MailNotifyInfo mailNotifyInfo) {
lock (this.m_lockObject) {
this.m_mailNotifyInfos.AddLast(mailNotifyInfo);
if (this.m_mailNotifyInfos.Count != 0) {
this.m_threadEvent.Set();
}
}
}
///
/// 傳送郵件執行緒的執行方法。
///
private void ThreadStart() {
while (true) {
this.m_threadEvent.WaitOne();
MailNotifyInfo mailNotifyInfo = this.m_mailNotifyInfos.First.Value;
EmailNotificationService mailNotificationService = new EmailNotificationService("smtp.gmail.com", true, 587, "LoginName@gmail.com", "LoginPassword");
mailNotificationService.SendTo("稿件中心",
mailNotifyInfo.EmailAddress,
"稿件狀態變更通知",
String.Format("{0}你的稿件{1}狀態已變更為{2}", mailNotifyInfo.Author, mailNotifyInfo.Title, mailNotifyInfo.ArticleStatus));
lock (this.m_lockObject) {
this.m_mailNotifyInfos.Remove(mailNotifyInfo);
if (this.m_mailNotifyInfos.Count == 0) {
this.m_threadEvent.Reset();
}
}
}
}
該類比較簡單,首先在建構函式中初始化成員變數,然後啟動傳送郵件執行緒,此時該執行緒是掛起的。
當外部呼叫AppendNotification方法時,會在連結串列中新增一個MailNotifyInfo物件,然後喚醒傳送郵件執行緒。由於在生產環境下可能會出現同時呼叫AppendNotification方法的情形,所以這裡要進行同步。
傳送郵件執行緒喚醒後進入一個死迴圈,等待事件物件觸發。當事件物件出發之後就開始傳送郵件了。郵件傳送完畢後從連結串列中刪除已傳送的郵件,然後檢查連結串列是否為空,如果是則重置事件物件,重新進入掛起狀態。同樣地,在對連結串列進行操作時也要進行同步。
至此,傳送郵件的功能實現完畢。需要傳送郵件的時候只要像這樣呼叫即可:
MailNotifyInfo mailNotifyInfo = new MailNotifyInfo();
.....
NotificationHandler.Instance.AppendNotification(mailNotifyInfo);
這只是一個很粗陋的框架,而且還不完善。例如,這裡假設網站是不間斷執行的系統,沒有考慮當網站關閉時傳送郵件執行緒的處理。大家可以在這個基礎上添磚加瓦,使其更加完善。另外,自動傳送郵件也是常見的功能,例如定時檢查某個條件,如果成立則傳送郵件。要實現自動傳送郵件的話,只要對本文的方案稍加修改即可:在NotificationHandler中新增一個Timer,定時執行某個方法,在這個方法中進行條件檢查並觸發事件即可。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-664115/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Django實現傳送郵件功能Django
- Python 實現郵件傳送功能(進階)Python
- Python 實現郵件傳送功能(初級)Python
- Python3實現自動傳送MySql查詢併傳送郵件PythonMySql
- py整合寶塔,flask已加入模組,無法實現自動傳送郵件功能Flask
- Springboot 自動傳送郵件Spring Boot
- python實現郵件的傳送Python
- Jenkins實現自動化郵件傳送踩坑記錄Jenkins
- ASP.NET之郵件傳送ASP.NET
- asp.net傳送郵件程式ASP.NET
- Redmine釋出新聞,自動傳送郵件功能失效恢復
- oracle 傳送郵件 實現方法Oracle
- 用Perl實現郵件傳送
- python實現傳送郵件Python
- Java實現QQ郵件傳送郵件工具類Java
- asp.net 郵件傳送提醒功能(接收方包括QQ郵箱等)ASP.NET
- ASP.net傳送郵件的例項ASP.NET
- 用phpmailer實現網頁表單提交傳送郵件功能PHPAI網頁
- linux下設定郵件自動傳送Linux
- python實現自動監控網站併傳送郵件告警薦Python網站
- 郵件的傳送
- 傳送郵件的小功能(.net core 版)
- Spring Boot實現傳送QQ郵件Spring Boot
- 『居善地』介面測試 — 9、介面自動化框架的傳送郵件實現框架
- spring-boot-route(二十二)實現郵件傳送功能Springboot
- 郵件傳送
- 傳送郵件
- 【Python】傳送郵件功能淺析Python
- Gitlab伺服器郵箱配置,實現自動為使用者傳送郵件(註冊傳送驗證連結)Gitlab伺服器
- 功能較全的oracle傳送郵件過程Oracle
- Ubuntu的郵件傳送Ubuntu
- asp.net定時傳送郵件總結ASP.NET
- 求助:J2ME實現檔案操作 和郵件傳送功能
- 傳送郵件出現問題
- SpringBoot實現傳送電子郵件Spring Boot
- python實現基於smtp傳送郵件Python
- Springboot+Javamail實現郵件傳送Spring BootJavaAI
- 使用多執行緒實現郵件傳送執行緒