EDM開發之二:SMTP服務器

SMTP服務器

服務器的搭建我就不作過多的敘述了,網上有不少,這裏主要講一下SMTP的工做原理和工做過程。html

SMTP一般有兩種工做模式:發送SMTP和接收SMTP。具體工做方式爲:發送SMTP在接到用戶的郵件請求後,判斷此郵件是否爲本地郵件,如果直接投送到用戶的郵箱,不然向dns查詢遠端郵件服務器的MX紀錄,並創建與遠端接收SMTP之間的一個雙向傳送通道,此後SMTP命令由發送SMTP發出,由接收SMTP接收,而應答則反方面傳送。一旦傳送通道創建,SMTP發送者發送MAIL命令指明郵件發送者。若是SMTP接收者能夠接收郵件則返回OK應答。SMTP發送者再發出RCPT命令確認郵件是否接收到。若是SMTP接收者接收,則返回OK應答;若是不能接收到,則發出拒絕接收應答(但不停止整個郵件操做),雙方將如此重複屢次。當接收者收到所有郵件後會接收到特別的序列,若是接收者成功處理了郵件,則返回OK應答便可。sql

下面是我我的對郵件在SMTP服務器文件夾中的旅行路徑,若有錯誤請指正:服務器

郵件發送分爲同步發送和異步發送:網絡

 1 /// <summary>
 2 /// 郵件設置
 3 /// </summary>
 4 /// <param name="toAddress">收件人地址</param>
 5 /// <param name="fromAddress">發件人地址</param>
 6 /// <param name="toName">收件人名字</param>
 7 /// <param name="fromName">發件人姓名</param>
 8 /// <param name="title">主題</param>
 9 /// <param name="body">正文</param>
10 /// <param name="isBodyHtml">正文是否爲html格式</param>
11 public SendEmail(string toAddress, string fromAddress, string toName, string fromName, string title, string body, bool isBodyHtml)
12 {
13     mailMessage.From = new MailAddress(fromAddress, fromName, Encoding.GetEncoding(936));
14     if (toName.Equals(""))
15         mailMessage.To.Add(toAddress);
16     else
17         mailMessage.To.Add(new MailAddress(toAddress, toName, Encoding.GetEncoding(936)));
18 
19     mailMessage.Subject = title;
20     mailMessage.SubjectEncoding = Encoding.GetEncoding(936);
21 
22     mailMessage.Body = body;
23     mailMessage.IsBodyHtml = isBodyHtml;
24     mailMessage.BodyEncoding = Encoding.GetEncoding(936);
25 }
26 /// <summary>
27 /// 設置SMTP,而且將郵件發送出去
28 /// 全部參數都設置完成後再調用該方法
29 /// </summary>
30 /// <param name="address">發件人地址(必須爲真實有效的email地址)</param>
31 /// <param name="password">發件人密碼</param>
32 /// <param name="smtpHost">SMTP服務器地址,例如:smtp.163.com</param>
33 /// <param name="smtpPort">SMTP服務器的端口,通常爲25</param>
34 /// <param name="isEnableSsl">SMTP服務器是否啓用SSL加密</param>
35 /// <param name="priority">郵件的優先級</param>
36 /// <param name="UseDefaultCredentials">設置是否須要身份驗證</param>
37 public void SetSmtp(string address, string password, string smtpHost, int smtpPort, bool isEnableSsl, MailPriority priority)
38 {
39     var smtp = new SmtpClient
40     {
41         DeliveryMethod = SmtpDeliveryMethod.Network,//電子郵件經過網絡發送到SMTP服務器
42         Credentials = new NetworkCredential(address, password),
43         Host = smtpHost,
44         Port = smtpPort,
45         UseDefaultCredentials = true,
46         EnableSsl = isEnableSsl
47     };
48     mailMessage.Priority = priority;
49     //smtp.Send(mailMessage); //同步發送郵件
50     smtp.SendAsync(mailMessage, mailMessage.To.ToString());//異步發送郵件
51 }
SendEmail

除非檢測SMTP的log日誌文件,不然咱們並不知道郵件是否發送成功,檢測SMTP日誌能夠用logparser工具,他能夠像sql那樣經過查詢語句來得到log的日誌內容:異步

net start smtpsvc /啓動smtp日誌記錄命令行/ide

 1 using LogQuery = MSUtil.LogQueryClass;
 2 using LogRecordSet = MSUtil.ILogRecordset;
 3 using TsvInputFormat = MSUtil.COMTSVInputContextClass;
 4 public class LogParser
 5 {
 6     /// <summary>      
 7     /// 計算日誌條數    
 8     /// </summary>      
 9     public double GetLogCount(string headerFile, string logName)
10     {
11         double avgLockSec = 0;
12         var oLogQuery = new LogQuery();
13         var oTsvInputFormat = new TsvInputFormat { iHeaderFile = headerFile };
14         string query = "select * from '" + logName + "'";
15         LogRecordSet oRecordSet = oLogQuery.Execute(query, oTsvInputFormat);
16         if (!oRecordSet.atEnd())
17         {
18             double item = 0;
19             if (!oRecordSet.getRecord().isNull(0))
20             {
21                 item = double.Parse(oRecordSet.getRecord().getValue(0).ToString());
22             }
23             avgLockSec = item;
24         }
25         oRecordSet.close();
26         return avgLockSec;
27     }
28 }
LogParser

根據上面圖片咱們知道,發送失敗的Email會放到Drop和BadEmail兩個文件夾中,因此只要監測兩個文件夾,有文件進來就是發送失敗的郵件:工具

 1 public static class MyFileSystemWatcher
 2 {
 3     [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
 4     public static void WatcherStrat(string path)
 5     {
 6         var watcher = new FileSystemWatcher { Path = path, Filter = "*.*" };
 7         watcher.Created += new FileSystemEventHandler(OnProcess);
 8         watcher.EnableRaisingEvents = true;
 9         watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
10         watcher.IncludeSubdirectories = true;
11     }
12     public static void OnProcess(object source, FileSystemEventArgs e)
13     {
14         switch (e.ChangeType)
15         {
16             case WatcherChangeTypes.Created:
17                 OnCreated(source, e);
18                 break;
19         }
20     }
21     public static void OnCreated(object source, FileSystemEventArgs e)
22     {
23         Console.WriteLine("文件改變事件{0}文件路徑{1}文件名{2}", e.ChangeType, e.FullPath, e.Name);
24     }
25     public static void OnChanged(object source, FileSystemEventArgs e)
26     {
27         Console.WriteLine("文件改變事件{0}文件路徑{1}文件名{2}", e.ChangeType, e.FullPath, e.Name);
28     }
29     public static void OnDeleted(object source, FileSystemEventArgs e)
30     {
31         Console.WriteLine("文件刪除事件{0}文件路徑{1}文件名{2}", e.ChangeType, e.FullPath, e.Name);
32     }
33     public static void OnRenamed(object source, RenamedEventArgs e)
34     {
35         Console.WriteLine("文件重命名事件{0}文件路徑{1}文件名{2}", e.ChangeType, e.FullPath, e.Name);
36     }
37     public static void GetFilesSystemRights(string path)
38     {
39         //給文件添加"Everyone,Users"用戶組的徹底控制權限  
40         var fi = new FileInfo(path);
41         System.Security.AccessControl.FileSecurity fileSecurity = fi.GetAccessControl();
42         fileSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow));
43         fileSecurity.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow));
44         fi.SetAccessControl(fileSecurity);
45         //給文件所在目錄添加"Everyone,Users"用戶組的徹底控制權限  
46         var di = new DirectoryInfo(path);
47         System.Security.AccessControl.DirectorySecurity dirSecurity = di.GetAccessControl();
48         dirSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow));
49         dirSecurity.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow));
50         di.SetAccessControl(dirSecurity);
51 
52     }
53 }
文件監測

在Global.asax文件中添加MyFileSystemWatcher.WatcherStrat("文件夾路徑");以便在服務啓動時就開始監測文件夾。加密

.BAD文件是郵件的實際內容;spa

.BDP是無用信息的回集;命令行

.BDR文件顯示了郵件沒有被髮送的緣由

相關文章
相關標籤/搜索