⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smtp.cs

📁 用C#开发实现SMTP相关技术,能接收到带附件的邮件服务功能.
💻 CS
字号:
namespace OpenSmtp.Mail 
{

/******************************************************************************
	Copyright 2001-2004 Ian Stallings
	OpenSmtp.Net is free software; you can redistribute it and/or modify
	it under the terms of the Lesser GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	OpenSmtp.Net is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	Lesser GNU General Public License for more details.

	You should have received a copy of the Lesser GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
/*******************************************************************************/


using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections;

	/// <summary>
	/// This Type sends a MailMessage using SMTP
	/// <seealso cref="EmailAddress"/>
	/// <seealso cref="MailMessage"/>
	/// <seealso cref="SmtpConfig"/>
	/// </summary>
	/// <example>
	/// <code>
	///		from = new EmailAddress("support@OpenSmtp.com", "Support");
	///		to = new EmailAddress("recipient@OpenSmtp.com", "Joe Smith");
	///
	///		msg = new MailMessage(from, to);
	///		msg.Subject = "Testing OpenSmtp .Net SMTP component";
	///		msg.Body = "Hello Joe Smith.";
	/// 
	///		Smtp smtp = new Smtp("localhost", 25);
	///		smtp.SendMail(msg);
	/// </code>
	/// </example>
	public class Smtp
	{
		internal TcpClient 	tcpc;
		internal string 	host;
		internal int 		port = 25;
		internal string 	username;
		internal string 	password;

		internal int 		sendTimeout = 50000;
		internal int 		recieveTimeout = 50000;
		internal int 		receiveBufferSize = 1024;
		internal int 		sendBufferSize = 1024;
		
		/// <summary>Default constructor</summary>
		/// <example>
		/// <code>
		/// 	Smtp smtp = new Smtp();
		/// 	smtp.Host = "mail.OpenSmtp.com";
		/// 	smtp.Port = 25;
		/// </code>
		/// </example>
		public Smtp()
		{}
		

		/// <summary>Constructor specifying a host and port</summary>
		/// <example>
		/// <code>
		/// 	Smtp smtp = new Smtp("mail.OpenSmtp.com", 25);
		/// </code>
		/// </example>
		public Smtp(string host, int port) 
		{
			this.host = host;
			this.port = port;
		}

		/// <summary>Constructor specifying a host, username and password</summary>
		/// <example>
		/// <code>
		/// 	Smtp smtp = new Smtp("mail.OpenSmtp.com", "login", "pwd");
		/// </code>
		/// </example>
		public Smtp(string host, string username, string password)
		{
			this.Host = host;
			this.Port = port;
			this.Username = username;
			this.Password = password;
		}

		/// <summary>Constructor specifying a host, username, password and port</summary>
		/// <example>
		/// <code>
		/// 	Smtp smtp = new Smtp("mail.OpenSmtp.com", "login", "pwd", 25);
		/// </code>
		/// </example>
		public Smtp(string host, string username, string password, int port)
		{
			this.Host = host;
			this.Port = port;
			this.Username = username;
			this.Password = password;
		}

		//========================================================================
		// PROPERTIES
		//========================================================================

		/// <value>Stores the Host address SMTP server. The default value is "localhost"</value>
		/// <example>"mail.OpenSmtp.com"</example>
		public string Host
		{
			get { return(this.host); }
			set { this.host = value; }
		}		

		/// <value>Stores the Port of the host SMTP server. The default value is port 25</value>
		public int Port
		{
			get { return(this.port); }
			set { this.port = value; }
		}
		
		/// <value>Stores send timeout for the connection to the SMTP server in milliseconds.
		/// The default value is 10000 milliseconds.</value>
		public int SendTimeout
		{
			get { return this.sendTimeout; }
			set { sendTimeout = value; }
		}

		/// <value>Stores send timeout for the connection to the SMTP server in milliseconds.
		/// The default value is 10000 milliseconds.</value>
		public int RecieveTimeout
		{
			get { return this.recieveTimeout; }
			set { recieveTimeout = value; }
		}

		/// <value>Stores the username used to authenticate on the SMTP server.
		/// If no authentication is needed leave this value blank.</value>
		public string Username
		{
			get { return this.username; }
			set { username = value; }
		}

		/// <value>Stores the password used to authenticate on the SMTP server.
		/// If no authentication is needed leave this value blank.</value>
		public string Password
		{
			get { return this.password; }
			set { password = value; }
		}

		//========================================================================
		// EVENTS
		//========================================================================
		
		/// <value>Event that fires when connected with target SMTP server.</value>
		public event EventHandler Connected;
		
		/// <value>Event that fires when dicconnected with target SMTP server.</value>
		public event EventHandler Disconnected;
		
		/// <value>Event that fires when authentication is successful.</value>
		public event EventHandler Authenticated;
		
		/// <value>Event that fires when message transfer has begun.</value>
		public event EventHandler StartedMessageTransfer;
		
		/// <value>Event that fires when message transfer has ended.</value>
		public event EventHandler EndedMessageTransfer;
		
		internal void OnConnect(EventArgs e)
		{
			if (Connected != null)
				Connected(this, e);
		}

		internal void OnDisconnect(EventArgs e)
		{
			if (Disconnected != null)
				Disconnected(this, e);
		}
				
		internal void OnAuthenticated(EventArgs e)
		{
			if (Authenticated != null)
				Authenticated(this, e);
		}

		internal void OnStartedMessageTransfer(EventArgs e)
		{
			if (StartedMessageTransfer != null)
				StartedMessageTransfer(this, e);
		}
		
		internal void OnEndedMessageTransfer(EventArgs e)
		{
			if (EndedMessageTransfer != null)
				EndedMessageTransfer(this, e);
		}

		//========================================================================
		// METHODS
		//========================================================================
		
		/// <summary>Sends a mail message using supplied MailMessage properties as string params</summary>
		/// <param name="from">RFC 822 formatted email sender address</param>
		/// <param name="to">RFC 822 formatted email recipient address</param>
		/// <param name="subject">Subject of the email message</param>
		/// <param name="body">Text body of the email message</param>
		/// <example>
		/// <code>
		/// 	Smtp smtp = new Smtp("mail.OpenSmtp.com", 25);
		///		smtp.SendMail("support@OpenSmtp.com", "recipient@OpenSmtp.com", "Hi", "Hello Joe Smith");
		/// </code>
		/// </example>
		public void SendMail(string from, string to, string subject, string body)
		{
			MailMessage msg = new MailMessage(from, to); 
			msg.subject = subject;
			msg.body = body;
			
			SendMail(msg);
		}
		
		/// <summary>Sends a mail message using supplied MailMessage and Smtp properties</summary>
		/// <param name="msg">MailMessage instance</param>
		/// <param name="host">SMTP host address</param>
		/// <param name="port">Port used to connect to host</param>
		/// <example>
		/// <code>
		///		MailMessage msg = new MailMessage("support@OpenSmtp.com", "recipient@OpenSmtp.com");
		///		msg.Subject = "Hi";
		///		msg.Body = "Hello Joe Smith."
		/// 	Smtp smtp = new Smtp();
		///		smtp.SendMail(msg, "mail.OpenSmtp.com", 25);
		/// </code>
		/// </example>
		public void SendMail(MailMessage msg, string host, int port)
		{
			this.host = host;
			this.port = port;
			SendMail(msg);
		}
		

		/// <summary>Sends a mail message using supplied MailMessage</summary>
		/// <param name="msg">MailMessage instance</param>
		/// <example>
		/// <code>
		///		MailMessage msg = new MailMessage("support@OpenSmtp.com", "recipient@OpenSmtp.com");
		///		msg.Subject = "Hi";
		///		msg.Body = "Hello Joe Smith."
		/// 	Smtp smtp = new Smtp("mail.OpenSmtp.com", 25);
		///		smtp.SendMail(msg);
		/// </code>
		/// </example>
		public void SendMail(MailMessage msg)
		{

			NetworkStream nwstream = GetConnection();

			CheckForError(ReadFromStream(ref nwstream), ReplyConstants.HELO_REPLY);

			if (this.username != null && this.username.Length > 0 && this.password != null && this.password.Length > 0)
			{
				WriteToStream(ref nwstream, "EHLO " + host + "\r\n");
			}
			else
				WriteToStream(ref nwstream, "HELO " + host + "\r\n");

			CheckForError(ReadFromStream(ref nwstream), ReplyConstants.OK);

			// Authentication is used if the u/p are supplied
			AuthLogin(ref nwstream);

			WriteToStream(ref nwstream, "MAIL FROM: <" + msg.from.address + ">\r\n");
			CheckForError(ReadFromStream(ref nwstream), ReplyConstants.OK);

			SendRecipientList(ref nwstream, msg.recipientList);
			SendRecipientList(ref nwstream, msg.ccList);
			SendRecipientList(ref nwstream, msg.bccList);

			WriteToStream(ref nwstream, "DATA\r\n");
			CheckForError(ReadFromStream(ref nwstream), ReplyConstants.START_INPUT);


			OnStartedMessageTransfer(EventArgs.Empty);
			WriteToStream(ref nwstream, msg.ToString() + "\r\n.\r\n");
			CheckForError(ReadFromStream(ref nwstream), ReplyConstants.OK);
			OnEndedMessageTransfer(EventArgs.Empty);

			WriteToStream(ref nwstream, "QUIT\r\n");
			CheckForError(ReadFromStream(ref nwstream), ReplyConstants.QUIT);

			CloseConnection();

		}
		
		
		/// <summary>Resets the Smtp instance to it's defaut values; set in the SmtpConfig class</summary>
		/// <example>
		/// <code>
		/// 	Smtp smtp = new Smtp("mail.OpenSmtp.com", 25);
		///		smtp.Reset();
		/// </code>
		/// </example>
		public void Reset()
		{
			host 	 = null;
			port	 = 25;
			username = null;
			password = null;
			
			CloseConnection();
		}
		
		
		// --------------- Helper methods ------------------------------------

		private NetworkStream GetConnection()
		{
			try
			{
				if (host == null)
				{ host = SmtpConfig.SmtpHost; }

				if (port == 0)
				{ port = SmtpConfig.SmtpPort; }

				if (host != null && port != 0)
				{
					tcpc = new TcpClient(host, port);
					
					LogMessage("connecting to:" + host + ":" + port, ""); 
					tcpc.ReceiveTimeout= recieveTimeout;
					tcpc.SendTimeout = sendTimeout;
					tcpc.ReceiveBufferSize = receiveBufferSize;
					tcpc.SendBufferSize = sendBufferSize;

					LingerOption lingerOption = new LingerOption(true, 10);
					tcpc.LingerState = lingerOption;
					
				}
				else
				{
					throw new SmtpException("Cannot use SendMail() method without specifying target host and port");
				}
			}
			catch(SocketException e)
			{
				throw new SmtpException("Cannot connect to specified smtp host(" + host + ":" + port + ").", e);
			}

			OnConnect(EventArgs.Empty);
			return tcpc.GetStream(); 
		}
		
		private void CloseConnection()
		{
			// add delimeter to log file
			LogMessage("------------------------------------------------------\r\n", "");
			
			// fire disconnect event
			OnDisconnect(EventArgs.Empty);
			
			// destroy tcp connection if it hasn't already closed
			if (tcpc!=null)			
			{ tcpc.Close(); }
		}


		private bool AuthLogin(ref NetworkStream nwstream)
		{
			if (this.username != null && this.username.Length > 0 && this.password != null && this.password.Length > 0)
			{
				WriteToStream(ref nwstream, "AUTH LOGIN\r\n");
				if (AuthImplemented(ReadFromStream(ref nwstream)))
				{
					WriteToStream(ref nwstream, Convert.ToBase64String(Encoding.ASCII.GetBytes(this.username.ToCharArray())) + "\r\n");

					CheckForError(ReadFromStream(ref nwstream), ReplyConstants.SERVER_CHALLENGE);

					WriteToStream(ref nwstream, Convert.ToBase64String(Encoding.ASCII.GetBytes(this.password.ToCharArray())) + "\r\n");
					CheckForError(ReadFromStream(ref nwstream), ReplyConstants.AUTH_SUCCESSFUL);
					
					OnAuthenticated(EventArgs.Empty);
					return true;
				}
			}

			return false;
		}
				
		private void SendRecipientList(ref NetworkStream nwstream, ArrayList recipients)
		{
			//	Iterate through all addresses and send them:
			for (IEnumerator i = recipients.GetEnumerator();i.MoveNext();)
			{
				EmailAddress recipient = (EmailAddress)i.Current;
				WriteToStream(ref nwstream, "RCPT TO: <" + recipient.address + ">\r\n");

				// potential 501 error (not valid sender, bad email address) below:
				CheckForError(ReadFromStream(ref nwstream), ReplyConstants.OK);
			}	
		}

		private bool CheckMailMessage(MailMessage message)
		{
			string returnMessage = "Mail Message is missing ";
		
			if (message.To == null || message.To.Count <= 0)
			{	
				throw new SmtpException(returnMessage + "'To:' field");
			}
			else
			{ return true; }
		}

		/**
		 * NetworkStream Helper methods
		 */
		private void WriteToStream(ref NetworkStream nw, string line)
		{
			try
			{
				byte[] arrToSend = Encoding.ASCII.GetBytes(line);
				nw.Write(arrToSend, 0, arrToSend.Length);
				//Console.WriteLine("[client]:" + line);
				LogMessage(line, "[client]: ");
			}
			catch(System.Exception)
			{
				throw new SmtpException("Write to Stream threw an System.Exception");
			}
		}

		private string ReadFromStream(ref NetworkStream nw)
		{
			try
			{
			
				byte[] readBuffer = new byte[4096];
			
				int length = nw.Read(readBuffer, 0, readBuffer.Length);
				string returnMsg = Encoding.ASCII.GetString(readBuffer, 0, length);

				LogMessage(returnMsg, "[server]: ");
				return returnMsg;
			}
			catch(System.Exception e)
			{
				throw new SmtpException("Read from Stream threw an System.Exception: " + e.ToString());
			}
		}

		private void LogMessage(string msg, string src)
		{
			Log log = new Log();
			if (SmtpConfig.LogToText)	{ log.logToTextFile(SmtpConfig.LogPath, msg, src); }
		}
		
		/**
		 *
		 * Checks stream returned from SMTP server for success code
		 * If the success code is not present it will throw an error.		
		 *
		 */
		private void CheckForError(string s, string successCode)
		{
			if (s.IndexOf(successCode) == -1)
				throw new SmtpException("ERROR - Expecting: " + successCode + ". Recieved: " + s);
		}

		/// Check to see if the command sent returns a Unknown Command Error
		private bool IsUnknownCommand(string s)
		{
			if (s.IndexOf(ReplyConstants.UNKNOWN) != -1) { return true; }
			else { return false; }
		}

		/// Check to see if AUTH command returns valid challenge. 
		/// A valid AUTH string must be passed into this method.
		private bool AuthImplemented(string s)
		{
			if (s.IndexOf(ReplyConstants.SERVER_CHALLENGE) != -1)
			{ return true; }
			
			return false;
		}
	}
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -