[Mono-list] System.Web.Mail

Per Arneng pt99par@student.bth.se
Tue, 18 Feb 2003 15:33:51 +0100


--------------Boundary-00=_FSDIDFBEFLQ8SISB06MI
Content-Type: text/plain;
  charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

Hi!

Here is a some code to get SmtpMail  to work. It works
with basic mails. There is still a lot to do to get a full=20
implementation but i figured it would be nice to get it
working even if it isnt 100% finsished.

SmtpMail.cs  - The updated version of the one on the cvs to
                    use my classes

SmtpClient.cs -  A class that represents a connection to a=20
                      Smtp server.

SmtpResponse.cs - A class that represents a response from
                             an smtp server

These files works if they are put in the System.Web.Mail dir
but  SmtpClient.cs & SmtpResponse.cs should probably
be somewhere else.

Note! this is my first contrib so there is probably many things
that arent as they should .. coding standard and stuff like that..
so feel free to reply with comments on that :)=20

//Per Arneng <pt99par@student.bth.se>=20
                          =20

--------------Boundary-00=_FSDIDFBEFLQ8SISB06MI
Content-Type: text/x-c++src;
  charset="us-ascii";
  name="SmtpClient.cs"
Content-Transfer-Encoding: 7bit
Content-Description: A class for handling the comunication to a smtp server
Content-Disposition: attachment; filename="SmtpClient.cs"

// SmtpClient.cs
// author: Per Arneng <pt99par@student.bth.se>
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Sockets;

namespace System.Web.Mail {

    /// represents a connection to a smtp server
    public class SmtpClient {
	
	private string server;
	private TcpClient tcpConnection;
	private Stream stream;
	private Encoding encoding;
	
	//Initialise the variables and connect
	public SmtpClient( string server ) {
	    
	    this.server = server;
	    encoding = new ASCIIEncoding( );

	    Connect();
	}
	
	// make the actual connection
	// and HELO handshaking
	private void Connect() {
	    tcpConnection = new TcpClient( server , 25 );
	    
	    stream = tcpConnection.GetStream();
	    
	    SmtpResponse response;
	    
	    // read the server greeting
	    response = ReadResponse();
	    
	    // write the HELO command to the server
	    WriteLine( String.Format( "HELO {0}" , Dns.GetHostName() ) );
	    
	    // read the response from
	    // the HELO command
	    response  = ReadResponse();
	}
		
	// sends a message to the server
	public void Send( MailMessage msg ) {
	    
	    if( msg.Attachments.Count > 0 )
		throw new NotImplementedException( "Attachments are not " + 
						   "implemented yet.");
	    
	    if( ( msg.From == null ) || ( msg.To == null ) )
		throw new ArgumentException( "From & To properties must be set." );
	    
	    SmtpResponse response;
	    
	    // start with a reset incase old data
	    // is present at the server in this session
	    WriteLine( "RSET" );
	    response  = ReadResponse();
	    
	    WriteLine( String.Format( "MAIL FROM: {0}" , msg.From ) );
	    response  = ReadResponse();
	    
	    WriteLine( String.Format( "RCPT TO: {0}" , msg.To ) );
	    response  = ReadResponse();
	    
	    WriteLine( "DATA");
	    response  = ReadResponse();
	    
	    // send the headers
	    SendHeaders( msg );
	    
	    // send the "" delimitor between
	    // the headers and the body
	    WriteLine( "" );

	    // send the mail body
	    WriteLine( msg.Body );
	    
	    // send a "." on a single row by itself
	    // to tell the server that there is no
	    // more data
	    WriteLine( "." );
	    response  = ReadResponse();	    
	}
	
	// send the standard headers
	// and the custom in MailMessage
	// FIXME: more headers needs to be added so
	// that all properties from MailMessage are sent..
	// missing: Priority , UrlContentBase,UrlContentLocation
	private void SendHeaders( MailMessage msg ) {
	    	    
	    WriteLine( String.Format("From: {0}", msg.From ) );
	    WriteLine( String.Format("To: {0}", msg.To ) );
	    
	    if( msg.Cc != null )
		WriteLine( String.Format("Cc: {0}", msg.Cc ) );
	    
	    if( msg.Bcc != null )
		WriteLine( String.Format("Bcc: {0}", msg.Bcc ) );
	    
	    if( msg.Subject != null )
		WriteLine( String.Format("Subject: {0}", msg.Subject ) );

	    if( msg.UrlContentBase != null )
		WriteLine( String.Format("Subject: {0}", msg.Subject ) );
	    
	    // send the content type
	    string contentType = "";
	    
	    switch( msg.BodyFormat ) {
		
	    case MailFormat.Html: contentType = "text/html"; break;
	    case MailFormat.Text: contentType = "text/plain"; break;
	    
	    default: contentType = "text/plain"; break;

	    }
	    
	    WriteLine( String.Format("Content-Type: {0}", contentType ) );
	    
	    // write the custom headers
	    foreach( string key in msg.Headers.Keys ) {
		string value = (string)msg.Headers[ key ];
		WriteLine( String.Format( "{0}: {1}" , key , value ));
	    }
	}
	
	
	// closes the connection
	public void Close() {
	    
	    WriteLine( "QUIT" );
	    SmtpResponse response  = ReadResponse();
	    
	    tcpConnection.Close();
	}
	
	// writes a line to the server
	private void WriteLine( string line ) {
	    byte[] buffer = 
		encoding.GetBytes( String.Format( "{0}\r\n" , line ) );
	    
	    stream.Write( buffer , 0 , buffer.Length );
	
	    // DebugPrint( line );
	}
	
	// read a line from the server
	private SmtpResponse ReadResponse( ) {
	    string line = null;
	    
	    byte[] buffer = new byte[ 4096 ];
	    
	    int readLength = stream.Read( buffer , 0 , 
					  buffer.Length );
	    
	    if( readLength > 0 ) { 
	    
		line = encoding.GetString( buffer , 0 , readLength );
		
		line = line.TrimEnd( new Char[] { '\r' , '\n' , ' ' } );
			
	    }
	    
	    // DebugPrint( line );

	    // parse the line to a response object
	    SmtpResponse response = SmtpResponse.Parse( line );
	    
	    // FIXME:
	    // There should probably be a better 
	    // error control than this later on
	    if( ( response.StatusCode / 100 ) == 5 ) 
		throw new IOException( "Smtp error: " + response.RawResponse );
	    
	    return response;
	} 
	
	/// debug printing 
	private void DebugPrint( string line ) {
	    Console.WriteLine( "smtp: {0}" , line );
	}
	
    }

}

--------------Boundary-00=_FSDIDFBEFLQ8SISB06MI
Content-Type: text/x-c++src;
  charset="us-ascii";
  name="SmtpMail.cs"
Content-Transfer-Encoding: 7bit
Content-Description: The updated cvs version 
Content-Disposition: attachment; filename="SmtpMail.cs"

//
// System.Web.Mail.SmtpMail.cs
//
// Author(s):
//    Lawrence Pit (loz@cable.a2000.nl)
//    Per Arneng (pt99par@student.bth.se)
//

using System;
using System.Net;
using System.Reflection;

namespace System.Web.Mail
{
	/// <remarks>
	/// </remarks>
	public class SmtpMail
	{
	    
	    private static string smtpServer = "localhost";
		
		// Constructor		
		private SmtpMail ()
		{
		    /* nothing here */
		}		

		// Properties
		public static string SmtpServer {
			get { return smtpServer; } 
			set { smtpServer = value; }
		}
		
		
		public static void Send (MailMessage message) 
	        {
		    
		    SmtpClient client = new SmtpClient (smtpServer);
		    
		    client.Send (message);
		    
		    client.Close ();
		}
		
		public static void Send (string from, string to, string subject, string messageText) 
		{
			MailMessage message = new MailMessage ();
			message.From = from;
			message.To = to;
			message.Subject = subject;
			message.Body = messageText;
			Send (message);
		}
	
	}
	
} //namespace System.Web.Mail

--------------Boundary-00=_FSDIDFBEFLQ8SISB06MI
Content-Type: text/x-c++src;
  charset="us-ascii";
  name="SmtpResponse.cs"
Content-Transfer-Encoding: 7bit
Content-Description: Represents a response from an smtp server
Content-Disposition: attachment; filename="SmtpResponse.cs"

// SmtpResponse.cs
// author: Per Arneng <pt99par@student.bth.se>
using System;

namespace System.Web.Mail {

    /// this class represents the response from the smtp server
    public class SmtpResponse {
	
	private string rawResponse;
	private int statusCode;
	private string[] parts;

	/// use the Parse method to create instances
	protected SmtpResponse() {}

	/// the smtp status code FIXME: change to Enumeration?
	public int StatusCode {
	    get { return statusCode; }
	    set { statusCode = value; }
	}
	
	/// the response as it was recieved
	public string RawResponse {
	    get { return rawResponse; }
	    set { rawResponse = value; }
	}

	/// the response as parts where ; was used as delimiter
	public string[] Parts {
	    get { return parts; }
	    set { parts = value; }
	}

	/// parses a new response object from a response string
	public static SmtpResponse Parse( string line ) {
	    SmtpResponse response = new SmtpResponse();
	    
	    if( line == null )
		throw new ArgumentNullException( "Null is not allowed " + 
						 "as a response string.");

	    if( line.Length < 4 ) 
		throw new FormatException( "Response is to short " + 
					   line.Length + ".");
	    
	    if( line[ 3 ] != ' ' )
		throw new FormatException( "Response format is wrong.");
	    
	    // parse the response code
	    response.StatusCode = Int32.Parse( line.Substring( 0 , 3 ) );
	    
	    // set the rawsponse
	    response.RawResponse = line;

	    // set the response parts
	    response.Parts = line.Substring( 0 , 3 ).Split( ';' );

	    return response;
	}
    }

}

--------------Boundary-00=_FSDIDFBEFLQ8SISB06MI--