Reputation: 61
Note: The code below is not originally my idea. It is just a modification of the code of Peter Bromberg in his article.
This code works on me but a little bit slow in sending emails(even only one is sent) and I'm not sure why. Also, I am trying to send HTML Body but it always sends TEXT Body. Please help.
Thank you in advance!
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Net.Mail;
namespace SMTP
{
/// <summary>
/// provides methods to send email via smtp direct to mail server
/// </summary>
public static class SmtpDirect
{
public static System.Threading.ManualResetEvent GetHostEntryFinished =
new System.Threading.ManualResetEvent(false);
public class ResolveState
{
string hostName;
System.Net.IPHostEntry resolvedIPs;
public ResolveState(string host)
{
hostName = host;
}
public IPHostEntry IPs
{
get { return resolvedIPs; }
set { resolvedIPs = value; }
}
public string host
{
get { return hostName; }
set { hostName = value; }
}
}
/// <summary>
/// Get / Set the name of the SMTP mail server
/// </summary>
public static string SmtpServer { get; set; }
// Record the IPs in the state object for later use.
public static void GetHostEntryCallback(IAsyncResult ar)
{
ResolveState ioContext = (ResolveState)ar.AsyncState;
ioContext.IPs = Dns.EndGetHostEntry(ar);
GetHostEntryFinished.Set();
}
private enum SMTPResponse : int
{
CONNECT_SUCCESS = 220,
GENERIC_SUCCESS = 250,
DATA_SUCCESS = 354,
QUIT_SUCCESS = 221
}
/// <summary>
/// Send Email
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public static bool Send(MailMessage message)
{
try
{
GetHostEntryFinished.Reset();
ResolveState ioContext = new ResolveState(SmtpServer);
Dns.BeginGetHostEntry(ioContext.host,
new AsyncCallback(GetHostEntryCallback), ioContext);
// Wait here until the resolve completes (the callback
// calls .Set())
GetHostEntryFinished.WaitOne();
IPEndPoint endPt = new IPEndPoint(ioContext.IPs.AddressList[0], 25);
Socket s = new Socket(endPt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
bool conn = false;
foreach (IPAddress ip in ioContext.IPs.AddressList)
{
endPt = new IPEndPoint(ioContext.IPs.AddressList[0], 25);
s = new Socket(endPt.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
s.Connect(endPt);
if (Check_Response(s, SMTPResponse.CONNECT_SUCCESS))
{
conn = true;
}
}
if (!conn)
{
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[0].ToString();
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.ToString().Split(new char[] { ';' });
foreach (string To in Tos)
{
Console.WriteLine("RCPT To");
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.ToString().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.ToString().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 M y H:m:s z"));
Header.Append("\r\n");
Header.Append("Subject: " + message.Subject + "\r\n");
Header.Append("X-Mailer: SMTPDirect v1\r\n");
string MsgBody = message.Body;
if (!MsgBody.EndsWith("\r\n"))
MsgBody += "\r\n";
if (message.Attachments.Count > 0)
{
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");
sb.Append("Content-Type: text/plain\r\n");
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)
{
Attachment a = o as Attachment;
byte[] binaryData;
if (a != null)
{
FileInfo f = new FileInfo(a.Name);
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 = System.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;
}
catch (Exception ex)
{
return false;
}
}
private static void Senddata(Socket s, string msg)
{
try
{
byte[] _msg = Encoding.ASCII.GetBytes(msg);
s.Send(_msg, 0, _msg.Length, SocketFlags.None);
}
catch (Exception ex)
{
Console.WriteLine("SendData Error: " + ex.Message);
}
}
private static bool Check_Response(Socket s, SMTPResponse response_expected)
{
string sResponse;
int response;
byte[] bytes = new byte[1024];
while (s.Available == 0)
{
System.Threading.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;
}
}
}
To test the code above I use this
SMTP.SmtpDirect.SmtpServer = "myhost.loc";
MailMessage msg = new MailMessage();
msg.Body = "TEST";
msg.From = new MailAddress("[email protected]");
msg.To.Add("[email protected]");
msg.Subject = "TEST SUBJECT";
//msg.Headers.Add("Reply-to", "");
if (SMTP.SmtpDirect.Send(msg))
{
Console.WriteLine("Sent OK");
}
else
{
Console.WriteLine("Something BAD Happened!");
}
Upvotes: 0
Views: 187
Reputation: 2607
For sending html body from mail. use
msg.BodyFormat = MailFormat.Html;
if you are using System.Web.Mail namespace in current class.(Please do not use this namespace since MailFormat is obsolete in higher .net framework)
Otherwise use
msg.IsBodyHtml = true;
if you are using System.Net.Mail namespace.
If nothing works then try to add this code snippet.:
AlternateView htmlView =
AlternateView.CreateAlternateViewFromString(yourbody, Encoding.UTF8, "text/html");
msg.AlternateViews.Add(htmlView);
msg.Body = yourbody;
msg.IsBodyHtml = true;
Upvotes: 0
Reputation: 5117
You can send multiple emmails at the same time. But be careful with the number of concurrent mail send operations. Adjust the number of concurrent mail send operations by several tests. This aproach may help you
Upvotes: 1