/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Web.Mail; namespace SMTP { /// /// provides methods to send email via smtp direct to mail server /// public class SmtpDirect { /// /// Get / Set the name of the SMTP mail server /// public static string SmtpServer; private enum SMTPResponse : int { CONNECT_SUCCESS = 220, GENERIC_SUCCESS = 250, DATA_SUCCESS = 354, QUIT_SUCCESS = 221 } public static bool Send(MailMessage message) { IPHostEntry IPhst = Dns.Resolve(SmtpServer); IPEndPoint endPt = new IPEndPoint(IPhst.AddressList[0], 25); Socket s = new Socket(endPt.AddressFamily, SocketType.Stream, ProtocolType.Tcp); s.Connect(endPt); if (!Check_Response(s, SMTPResponse.CONNECT_SUCCESS)) { s.Close(); return false; } Senddata(s, string.Format("HELO {0}\r\n", Dns.GetHostName())); if (!Check_Response(s, SMTPResponse.GENERIC_SUCCESS)) { s.Close(); return false; } Senddata(s, string.Format("MAIL From: {0}\r\n", message.From)); if (!Check_Response(s, SMTPResponse.GENERIC_SUCCESS)) { s.Close(); return false; } string _To = message.To; string[] Tos = _To.Split(new char[] {';'}); foreach (string To in Tos) { Senddata(s, string.Format("RCPT TO: {0}\r\n", To)); if (!Check_Response(s, SMTPResponse.GENERIC_SUCCESS)) { s.Close(); return false; } } if (message.Cc != null) { Tos = message.Cc.Split(new char[] {';'}); foreach (string To in Tos) { Senddata(s, string.Format("RCPT TO: {0}\r\n", To)); if (!Check_Response(s, SMTPResponse.GENERIC_SUCCESS)) { s.Close(); return false; } } } StringBuilder Header = new StringBuilder(); Header.Append("From: " + message.From + "\r\n"); Tos = message.To.Split(new char[] {';'}); Header.Append("To: "); for (int i = 0; i < Tos.Length; i++) { Header.Append(i > 0 ? "," : ""); Header.Append(Tos[i]); } Header.Append("\r\n"); if (message.Cc != null) { Tos = message.Cc.Split(new char[] {';'}); Header.Append("Cc: "); for (int i = 0; i < Tos.Length; i++) { Header.Append(i > 0 ? "," : ""); Header.Append(Tos[i]); } Header.Append("\r\n"); } Header.Append("Date: "); Header.Append(DateTime.Now.ToString("ddd, d MMM yyyy H:m:s z")); Header.Append("\r\n"); Header.Append("Subject: " + message.Subject + "\r\n"); Header.Append("X-Mailer: SMTPDirect v1\r\n"); string importance = null; if (message.Priority == MailPriority.High) { importance = "high"; } else if (message.Priority == MailPriority.Low) { importance = "low"; } if (importance != null) { Header.Append("Importance: " + importance + "\r\n"); } string MsgBody = message.Body; if (!MsgBody.EndsWith("\r\n")) { MsgBody += "\r\n"; } if (message.Attachments.Count > 0 || message.BodyFormat == MailFormat.Html) { Header.Append("MIME-Version: 1.0\r\n"); Header.Append("Content-Type: multipart/mixed; boundary=unique-boundary-1\r\n"); Header.Append("\r\n"); Header.Append("This is a multi-part message in MIME format.\r\n"); StringBuilder sb = new StringBuilder(); sb.Append("--unique-boundary-1\r\n"); string type = message.BodyFormat == MailFormat.Text ? "plain" : "html"; sb.Append(string.Format("Content-Type: text/{0}\r\n", type)); sb.Append("Content-Transfer-Encoding: 7Bit\r\n"); sb.Append("\r\n"); sb.Append(MsgBody + "\r\n"); sb.Append("\r\n"); foreach (object o in message.Attachments) { MailAttachment a = o as MailAttachment; byte[] binaryData; if (a != null) { FileInfo f = new FileInfo(a.Filename); sb.Append("--unique-boundary-1\r\n"); sb.Append("Content-Type: application/octet-stream; file=" + f.Name + "\r\n"); sb.Append("Content-Transfer-Encoding: base64\r\n"); sb.Append("Content-Disposition: attachment; filename=" + f.Name + "\r\n"); sb.Append("\r\n"); FileStream fs = f.OpenRead(); binaryData = new Byte[fs.Length]; long bytesRead = fs.Read(binaryData, 0, (int) fs.Length); fs.Close(); string base64String = Convert.ToBase64String(binaryData, 0, binaryData.Length); for (int i = 0; i < base64String.Length; ) { int nextchunk = 100; if (base64String.Length - (i + nextchunk) < 0) { nextchunk = base64String.Length - i; } sb.Append(base64String.Substring(i, nextchunk)); sb.Append("\r\n"); i += nextchunk; } sb.Append("\r\n"); } } MsgBody = sb.ToString(); } Senddata(s, ("DATA\r\n")); if (!Check_Response(s, SMTPResponse.DATA_SUCCESS)) { s.Close(); return false; } Header.Append("\r\n"); Header.Append(MsgBody); Header.Append(".\r\n"); Header.Append("\r\n"); Header.Append("\r\n"); Senddata(s, Header.ToString()); if (!Check_Response(s, SMTPResponse.GENERIC_SUCCESS)) { s.Close(); return false; } Senddata(s, "QUIT\r\n"); Check_Response(s, SMTPResponse.QUIT_SUCCESS); s.Close(); return true; } private static void Senddata(Socket s, string msg) { byte[] _msg = Encoding.ASCII.GetBytes(msg); s.Send(_msg, 0, _msg.Length, SocketFlags.None); } private static bool Check_Response(Socket s, SMTPResponse response_expected) { string sResponse; int response; byte[] bytes = new byte[1024]; while (s.Available == 0) Thread.Sleep(100); s.Receive(bytes, 0, s.Available, SocketFlags.None); sResponse = Encoding.ASCII.GetString(bytes); response = Convert.ToInt32(sResponse.Substring(0, 3)); if (response != (int) response_expected) { return false; } return true; } } }