README.md

December 4, 2022 ยท View on GitHub

SMTP without CDO

Description

The System.Web.Mail namespace works on servers without CDO installed, this is a complete SMTP client, that supports MIME attachments.

More Info

Use the System.Web.Mail.MailMessage as the input to the Send function.

Use this class as you would use the System.Web.Mail.SmtpMail class it called System.Web.Mail.SmtpMail_NOCDO.

Make sure you set the System.Web.Mail.SmtpMail_NOCDO.SmtpServer

to the name of a valid stmp server.

true is send ok!

This version dosn't support BCC

Submitted On
ByPeter Hughes
LevelIntermediate
User Rating5.0 (15 globes from 3 users)
CompatibilityC#
CategoryControls/ Forms/ Dialogs/ Menus
World.Net (C#, VB.net)
Archive File

Source Code

using System;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Net;
namespace System.Web.Mail
{
	/// <summary>
	/// provides methids to send email via smtp, with out CDO SYS installed
	/// </summary>
	public class SmtpMail_NOCDO
	{
		/// <summary>
		/// Get or Set the name of the SMTP relay mail server
		/// </summary>
		public static string SmtpServer;
		private enum SMTP_Responses: int
		{
			CONNECT_SUCCESS = 220,
			GENERIC_SUCCESS = 250,
			DATA_SUCCESS	= 354,
			QUIT_SUCCESS	= 221
		}
		public static bool Send(MailMessage message)
		{
			IPHostEntry lipa = Dns.Resolve(SmtpServer);
			IPEndPoint target = new IPEndPoint(lipa.AddressList[0], 25);
			Socket s= new Socket(target.AddressFamily, SocketType.Stream,ProtocolType.Tcp);
			s.Connect(target);
			#region connect
			if(!Check_Response(s, SMTP_Responses.CONNECT_SUCCESS))
			{
				Console.WriteLine("Server didn't respond.");
				s.Close();
				return false;
			}
			#endregion
			#region send helo
			Senddata(s, string.Format("HELO {0}\r\n", Dns.GetHostName() ));
			if(!Check_Response(s, SMTP_Responses.GENERIC_SUCCESS))
			{
				Console.WriteLine("Helo Failed!.");
				s.Close();
				return false;
			}
			#endregion
			#region Send the MAIL command
			Senddata(s, string.Format("MAIL From: {0}\r\n", message.From ));
			if(!Check_Response(s, SMTP_Responses.GENERIC_SUCCESS))
			{
				Console.WriteLine("Mail command Failed!.");
				s.Close();
				return false;
			}
			#endregion
			#region Send RCPT commands (one for each recipient)
			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, SMTP_Responses.GENERIC_SUCCESS))
				{
					Console.WriteLine("RCPT command Failed ({0})!.", To);
					s.Close();
					return false;
				}
			}
			#endregion
			#region Send RCPT commands (one for each recipient) - CC
			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, SMTP_Responses.GENERIC_SUCCESS))
					{
						Console.WriteLine("RCPT command Failed ({0})!.", To);
						s.Close();
						return false;
					}
				}
			}
			#endregion
			#region Send the DATA command
			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 M y H:m:s z" ));
			Header.Append("\r\n");
			Header.Append("Subject: " + message.Subject+ "\r\n");
			Header.Append( "X-Mailer: Narayan EMail v2\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)
				{
					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 = 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, SMTP_Responses.DATA_SUCCESS))
			{
				Console.WriteLine("Data command Failed!.");
				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, SMTP_Responses.GENERIC_SUCCESS ))
			{
				Console.WriteLine("Data command Failed!.");
				s.Close();
				return false;
			}
			#endregion
			#region quit
			Senddata(s, "QUIT\r\n");
			Check_Response(s, SMTP_Responses.QUIT_SUCCESS );
			s.Close();
			#endregion
			return true;
		}
		private static void Senddata(Socket s, string msg)
		{
//			StreamWriter sw= new FileInfo("send.txt").AppendText();
//			sw.WriteLine(msg);
//			sw.Close();
//			sw=null;
//			GC.Collect();
			byte[] _msg = Encoding.ASCII.GetBytes(msg);
			s.Send(_msg , 0, _msg .Length, SocketFlags.None);
		}
		private static bool Check_Response(Socket s, SMTP_Responses response_expected )
		{
			string sResponse;
			int response;
			byte[] bytes = new byte[1024];
//			Console.WriteLine("Waiting for {0}", response_expected);
			while (s.Available==0)
			{
				System.Threading.Thread.Sleep(100);
			}
			s.Receive(bytes, 0, s.Available, SocketFlags.None);
			sResponse = Encoding.ASCII.GetString(bytes);
			//Console.WriteLine(sResponse);
			response = Convert.ToInt32(sResponse.Substring(0,3));
			if(response != (int)response_expected)
				return false;
			return true;
		}
	}
}