Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 23 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
23
Dung lượng
695,58 KB
Nội dung
Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 Mỗi lần học được điều mới sẽ cố gắng chia sẻ mọi người ^^ Hồi lâu nghiên cứu về cái SMTP cuối cùng cũng ngộ ra được 1 số thứ Giới thiệu qua chút về SMTP: SMTP là một giao thức dùng nền văn bản và tương đối đơn giản. Trước khi một thông điệp đư ợc gửi, người ta có thể định vị một hoặc nhiều địa chỉ nhận cho thông điệp - những địa chỉ này thường được kiểm tra về sự tồn tại trung thực của chúng) . Việc kiểm t hử một trình chủ SMTP là một việc tương đối dễ dàng, dùng chương trình ứng dụng "telnet" (xem dưới đây). SMTP dùng cổng 25 của giao thức TCP. Để xác định trình chủ SMTP của một tên miền nào đấy (domain name), người ta dùng một mẫu tin MX (Mail eXchange - Trao đổi thư) của DNS (Domain Name System - Hệ thống tên miền). Các bạn nên đọc thêm tư liệu về SMTP Code: http://tools.ietf.org/html/rfc1123 http://vi.wikipedia.org/wiki/SMTP Một ví dụ truy nhập trực tiếp vào mail server bằng telnet qua port 25: Code: S: 220 www.example.com ESMTP Postfix C: HELO mydomain.com S: 250 Hello mydomain.com C: MAIL FROM:<sender@mydomain.com> S: 250 Ok C: RCPT TO:<friend@example.com> S: 250 Ok C: DATA S: 354 End data with <CR><LF>.<CR><LF> C: Subject: test message C: From: sender@mydomain.com C: To: friend@example.com C: C: Hello, C: This is a test. C: Goodbye. C: . S: 250 Ok: queued as 12345 C: QUIT S: 221 Bye Trích từ wikipedia Tiếng Việt: http://vi.wikipedia.org/wiki/SMTP Mình có làm một cái video bên HCE về cái này Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 Code: http://hcegroup.net/hceteam/showthread.php?t=2497 OK ! Xem thử mô hình nha Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 Mô hình và cách thức như vậy ^^. Giờ ta tạo Class MySMTP để xử lý quy trình: Những thứ cần khởi tạo là gì? Dựa trên cái mô hình ở trên ta có những thứ sau private string Server; private string SenderName; private string SenderAddress; private string RCPName; private string RCPAddress; private string Subject; private string Body; private int TimeOut; private int Port; TcpClient SMTPTCPClient; NetworkStream SMTPNetworkStream; StreamReader SMTPStreamReader; StreamWriter SMTPStreamWriter; DateTime TimeOutCheck; Chú ý: + Để tạo một connection ta cần sử dụng: TcpClient + Để tạo một stream cho Network sử dụng NetworkStream + Xử lý NetworkStream qua 2 cái Base trước đó: StreamReader và StreamWriter. + DateTime: để quản lý connection , trường hợp bị TimeOut + Có các thành phần rồi giờ đơn giản thì ta tạo các Properties trước đi /* * PROPERTIES */ // Property: Server public string SMTPServer { get { return Server; } set { Server = value; } } // Property: SenderName public string SMTPSenderName { get { return SenderName; } set { SenderName = value; } } // Property: SenderAddress public string SMTPSenderAddress { get { return SenderAddress; } set { SenderAddress = value; } } // Property: RCPName public string SMTPRCPName { get { return RCPName; } Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 set { RCPName = value; } } // Property: RCPAddress public string SMTPRCPAddress { get { return RCPAddress; } set { RCPAddress = value; } } // Property: Subject public string SMTPSubject { get { return Subject; } set { Subject = value; } } // Property: Body public string SMTPBody { get { return Body; } set { Body = value; } } // Property: TimeOut public int SMTPTimeOut { get { return TimeOut; } set { TimeOut = value; } } // Property: Port public int SMTPPort { get { return Port; } set { Port = value; } } + Với xử lý việc gửi mail thì có thể chỉ cần sử dụng 1 phương thức: a. Gửi Email đi : OnSendEmail() là đủ Nhưng khi send Email ta cần kiểm tra connection time out vì thế phải xác nhận response từ server thì mới có thể request và biết nên đóng connection cho hợp lý. Vì vậy thêm 1 phương thức nữa xử lý TimeOut b. Xử lý Connection TimeOut: WaitForResponse() + Xử lý gửi thông điệp đi thực sự rất đơn giản và không phức tạp. Dựa vào mô hình ở trên ta thấy vòng lặp quá trình xử lý được làm như sau: 1. Khởi tạo kết nối, thất bại thì đóng 2. Khởi tạo thành công, thu nhận thông điệp vào các stream 3. Chào server, code = 220; đóng nếu thật bại 4. Xử lý sender address: đóng nếu thất bại . code =250 5. Xử lý người nhận : đóng nếu thất bại. code = 250 6. Xử lý data: Thông tin Data của thông điệp gửi đi có 2 phần chính: Header Info From: To: Subject: Message Info Body: Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 Ngoài ra còn một số thông tin khác bổ sung cho Header như DateTime, Reply-To 7. Gửi thông điệp , đóng nếu thất bại. Code = 354 8. Kiểm tra thông điệp nếu được gửi thành công: code = 250. Đóng nếu thất bại Chú ý: việc xử lý các bước đều thông qua viẹc xử lý connection time out. Vì xử lý thông điệp tới server có 2 kết quả, thành công hoặc thất bại nên 2 phương thức t a viết ở sử dụng kiểu Boolean (bool) Từ bản nháp giấy trên ta tiến hành vào code thực dụng cho 2 phương thức: + public void OnSendEmail() + private void WaitForResponse(string Code) ( sử dụng private vì public thì ai dùng , có mỗi thằng OnSendEmail nó xài. Thêm vào đó Response code thì dùng kiểu String chứ không dùng Int vì tránh phải convert khi kiểm tra và so sánh từ stream. Thông điệp từ stream luôn là kiểu String). Đây là Class được xây dựng hoàn chỉnh: using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; namespace Network { public class MySMTP { // Mail Properties private string Server; private string SenderName; private string SenderAddress; private string RCPName; private string RCPAddress; private string Subject; private string Body; private int TimeOut; private int Port; // Network Connector Properties TcpClient SMTPTCPClient; NetworkStream SMTPNetworkStream; StreamReader SMTPStreamReader; StreamWriter SMTPStreamWriter; DateTime TimeOutCheck; // Constructor public MySMTP() { TimeOut = 60; // Set Connection Time Out around 1 minute Port = 25; // which is accessed through Telnet } /* Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 * PROPERTIES */ // Property: Server public string SMTPServer { get { return Server; } set { Server = value; } } // Property: SenderName public string SMTPSenderName { get { return SenderName; } set { SenderName = value; } } // Property: SenderAddress public string SMTPSenderAddress { get { return SenderAddress; } set { SenderAddress = value; } } // Property: RCPName public string SMTPRCPName { get { return RCPName; } set { RCPName = value; } } // Property: RCPAddress public string SMTPRCPAddress { get { return RCPAddress; } set { RCPAddress = value; } } // Property: Subject public string SMTPSubject { get { return Subject; } set { Subject = value; } } // Property: Body public string SMTPBody { get { return Body; } set { Body = value; } } // Property: TimeOut public int SMTPTimeOut { get { return TimeOut; } set { TimeOut = value; } } // Property: Port public int SMTPPort { get { return Port; } set { Port = value; } } Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 /* * METHOD */ // Send message through telnet connection public bool OnSendEmail() { // Initialization SMTPTCPClient = new TcpClient(); // Set up the connection try { SMTPTCPClient.Connect(Server, Port); } catch (Exception ex) { // if fail to connect to mail server Console.WriteLine("Error: " + ex.Message); return false; } // If succeed creating the connection // init all the streams SMTPNetworkStream = SMTPTCPClient.GetStream(); SMTPStreamReader = new StreamReader(SMTPNetworkStream); SMTPStreamWriter = new StreamWriter(SMTPNetworkStream); // Need for server's response if (WaitForResponse("220")) { // Greet mail server SMTPStreamWriter.WriteLine("HELO: " + Server); // Clear the rest/garbage SMTPStreamWriter.Flush(); } else // if no response from server { // connection fails SMTPTCPClient.Close(); return false; } // The next response for input sender address if (WaitForResponse("250")) { // write down the sender address SMTPStreamWriter.WriteLine("Mail From:" + SenderAddress); SMTPStreamWriter.Flush(); } else { // connection close otherwise SMTPTCPClient.Close(); return false; } // Response for input RCP Address if (WaitForResponse("250")) Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 { // write down the RCP address SMTPStreamWriter.WriteLine("RCPT TO:" + RCPAddress); SMTPStreamWriter.Flush(); } else { // close the connection otherwise SMTPTCPClient.Close(); return false; } // Response for data / body if (WaitForResponse("250")) { // request data SMTPStreamWriter.WriteLine("Data"); SMTPStreamWriter.Flush(); } else { // close connection otherwise SMTPTCPClient.Close(); return false; } // Send the message if (WaitForResponse("354")) { // Get all message // NOTE: Each section should be ended up with a newline seperately string szData = ""; szData = "From:" + SenderName + Environment.NewLine; szData += "To:" + RCPName + Environment.NewLine; szData += "Subject:" + Subject + Environment.NewLine; szData += Body + Environment.NewLine + "." + Environment.NewLine; // Send the message to network stream through stream writer SMTPStreamWriter.Write(szData); // clear the rest SMTPStreamWriter.Flush(); } else { // close the connection if fails SMTPTCPClient.Close(); return false; } // Wait for the last success if (WaitForResponse("250")) { // close the connection safely SMTPTCPClient.Close(); return true; } else Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 { // close the connection otherwise SMTPTCPClient.Close(); return false; } } // WaitForResponse method manipulates the connection response. private bool WaitForResponse(string Code) { // Get the time at connecting moment TimeOutCheck = DateTime.Now; // Span the timer TimeSpan TimeSpanner = DateTime.Now - TimeOutCheck; // Loop until timeout exceeds while (TimeSpanner.Seconds < TimeOut) { if (SMTPNetworkStream.DataAvailable) { // If catch the incoming data, get it by lines string DataIn = SMTPStreamReader.ReadLine(); // Check for the sufficient response code if (DataIn.Substring(0, Code.Length).Equals(Code)) return true; } // Recalculate timeout TimeSpanner = DateTime.Now - TimeOutCheck; } // Return false if it fails return false; } } public class Network { public static void Main() { // Create a SMTP Object MySMTP smtp = new MySMTP(); smtp.SMTPServer = "gsmtp163.google.com"; smtp.SMTPPort = 25; smtp.SMTPTimeOut = 60; smtp.SMTPSenderName = "Pete Houston"; smtp.SMTPSenderAddress = "xcross87@gmail.com"; smtp.SMTPRCPName = "Pete Houston"; smtp.SMTPRCPAddress = "pete.houston.17187@gmail.com"; smtp.SMTPSubject = "Testing for SMTP Class"; smtp.SMTPBody = "Hello Pete ! Message Sent Successfully !"; Console.WriteLine("Sending \n"); // Try to send email if (smtp.OnSendEmail()) { Console.WriteLine("OK !"); } else { Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 Console.WriteLine("Failed !"); } } } } // Ghi chú: có tham khảo và chỉnh sửa từ c-sharpcorner.com Tuy nhiên .NET Framework đã có library hỗ trợ xử lý với các Mail Server thông qua Code: using System.Net.Mail; public class SmtpClient; Để sử dụng ta đơn thuần tạo một Email Object từ class MailMessage trong cùng namespace System.Net.Mail; xử lý 4 properties chính của một Email Message: Code: From To Subject Body Một ví dụ send email qua SMTP như sau using System; using System.Net; using System.Net.Mail; class EmailWithSMTP { // the EP public static void Main() { // server info string szServer = "Dien server vao day"; int iPort = 25; // set up a connection SmtpClient client = new SmtpClient(szServer,iPort); // If you access to a account on mail server to send email // use this: // client.Credentials = new NetworkCredential("user@addr.com","password"); // create message using (MailMessage message = new MailMessage()) { // make up message message.From = new MailAddress("sender@somewhere.com"); message.To.Add("receiver@someplace.com"); [...]... message; } } public class SMTPTest { public static void Main(string[] args) { try { Smtp smtp = new Smtp( ); smtp. From = "xcross87@cviet.com"; smtp. Subject = "Greet to Pete"; smtp. BodyText = "How's your work going?"; smtp. To.Add("pete.houston.17187@gmail.com"); smtp. Send(); Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 } catch (SmtpException e) { System.Console.WriteLine("{0}", e.What()); } } } } rất đơn... gsmtp183.google.com internet address = 64.233.183.27 > exit Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 C:UsersXcross87> như vậy là có thể thấy Gmail sử dụng các Email Exchange Server để lưu trữ và gửi mail đi Tại sao lại sử dụng nhiều server mail như thế? Đơn giản là trong quá trình gửi mail đi nếu có trục trặc bị lỗi ở server này không gửi đi được thì mail sẽ được chuyển tới server khác để gửi. .. exchanger = alt1.gmail -smtp- in.l.google = 10, mail exchanger = alt2.gmail -smtp- in.l.google = 50, mail exchanger = gsmtp163.google.com = 50, mail exchanger = gsmtp183.google.com = 5, mail exchanger = gmail -smtp- in.l.google.com gmail.com nameserver = ns4.google.com gmail.com nameserver = ns1.google.com gmail.com nameserver = ns2.google.com gmail.com nameserver = ns3.google.com gsmtp163.google.com internet... "250") { throw new SmtpException(response); } /* * 9 Quit * Code = 221 */ message = "QUIT\r\n"; Write(message); response = Response(); if (response.IndexOf("221") == -1) { throw new SmtpException(response); } } #endregion } public class SmtpException : Exception { string message; public SmtpException(string str) { message = str; } public string What() { return message; } } public class SMTPTest { public... thiết kế class Smtp Ta cài đặt với các properties như sau : private string _server = null; private int _port = 0; private string _from = null; private ArrayList _to; private ArrayList _cc; private ArrayList _bcc; private string _subject = null; private string _bodyHtml = null; private string _bodyText = null; /// /// Constructor /// public Smtp( ) { // Init server connection info _server = "gsmtp163.google.com";... check email pete.houston.17187@gmail.com sẽ thấy một mail mới nhận Các bạn thử thực hành quy trình trên bằng tay xem Trong quá trình send email đi ta chia nhỏ ra một chút Ta sẽ chia ra phần gửi thông điệp tới server và sẽ kiểm tra response, nếu không hợp lệ thì sẽ throw vào lớp exception Lý thuyết là thế, giờ bắt tay vào xây dựng cho hợp lý Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 đầu tiên với. .. public class SmtpException : System.Exception { private string message; public SmtpException(string str) { message = str; } public string What() { return message; } } Ta tạo một namespace Gmail và tạo các class bên trong using using using using using System; System.Collections; System.Net.Sockets; System.Net.Mail; System.Text; namespace Gmail { public class Smtp : TcpClient public class SmtpException... tập: thienthanit@yahoo.com Nguồn: Xcross87 if (response.Substring(0, 3) != "250") { throw new SmtpException(response); } } catch (SmtpException e) { System.Console.WriteLine("{ 0}", e.What()); } } /* * 6 Input list of bcc * Code = 250 việc cuôi cùng là test lại class cho hoàn chỉnh đây là bộ class hoàn chỉnh Smtp cho Gmail có cả 1 class con để test luôn using using using using using using System; System.Collections;... Response(); if (response.Substring(0, 3) != "250") { throw new SmtpException(response); } /* * 4 Input list of receivers * Code = 250 */ foreach (string address in _to) { try { message = "RCPT TO:\r\n"; Write(message); response = Response(); if (response.Substring(0, 3) != "250") { throw new SmtpException(response); } } catch (SmtpException e) { System.Console.WriteLine("{0}", e.What());... "250") { throw new SmtpException(response); } } catch (SmtpException e) { System.Console.WriteLine("{ 0}", e.What()); Biên tập: thienthanit@yahoo.com Nguồn: Xcross87 } } /* * 6 Input list of bcc * Code = 250 */ foreach (string address in _bcc) { try { message = "RCPT TO:\r\n"; Write(message); response = Response(); if (response.Substring(0, 3) != "250") { throw new SmtpException(response); . Main() { // Create a SMTP Object MySMTP smtp = new MySMTP(); smtp. SMTPServer = "gsmtp163.google.com"; smtp. SMTPPort = 25; smtp. SMTPTimeOut = 60; smtp. SMTPSenderName = "Pete. Houston"; smtp. SMTPSenderAddress = "xcross87@gmail.com"; smtp. SMTPRCPName = "Pete Houston"; smtp. SMTPRCPAddress = "pete.houston.17187@gmail.com"; smtp. SMTPSubject. SMTPPort { get { return Port; } set { Port = value; } } + Với xử lý việc gửi mail thì có thể chỉ cần sử dụng 1 phương thức: a. Gửi Email đi : OnSendEmail() là đủ Nhưng khi send Email