/// <summary>
 /// Handle the RCPT TO:&lt;address&gt; command.
 /// </summary>
 private void Rcpt( SMTPContext context, string argument )
 {
     if( context.LastCommand == COMMAND_MAIL || context.LastCommand == COMMAND_RCPT )
     {				
         string address = ParseAddress( argument );
         if( address != null )
         {
             try
             {
                 EmailAddress emailAddress = new EmailAddress( address );
                 
                 // Check to make sure we want to accept this message.
                 //if( recipientFilter.AcceptRecipient( context, emailAddress ) )
                 //{						
                     context.Message.AddToAddress( emailAddress );
                     context.LastCommand = COMMAND_RCPT;							
                     context.WriteLine( MESSAGE_OK );
                     //if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: RcptTo address: {1} accepted.", context.ConnectionId, address ) );
                 //}
                 //else
                 //{
                 //    context.WriteLine(MESSAGE_UNKNOWN_USER);
                     //if (log.IsDebugEnabled) log.Debug(String.Format("Connection {0}: RcptTo address: {1} rejected.  Did not pass Address Filter.", context.ConnectionId, address));
                 //}
             }
             catch( InvalidEmailAddressException )
             {
                 //if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: RcptTo argument: {1} rejected.  Should be from:<*****@*****.**>", context.ConnectionId, argument ) );
                 context.WriteLine( MESSAGE_INVALID_ADDRESS );
             }
         }
         else
         {
             //if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: RcptTo argument: {1} rejected.  Should be from:<*****@*****.**>", context.ConnectionId, argument ) );
             context.WriteLine( MESSAGE_INVALID_ADDRESS );
         }
     }
     else
     {
         context.WriteLine( MESSAGE_INVALID_COMMAND_ORDER );
     }
 }
        private void Data( SMTPContext context )
        {
            context.WriteLine( MESSAGE_START_DATA );
            
            SMTPMessage message = context.Message;
            IPEndPoint clientEndPoint = (IPEndPoint) context.Socket.RemoteEndPoint;
            StringBuilder header = new StringBuilder();
            header.Append( String.Format( "Received: from {0} ({0} [{1}])", context.ClientDomain, clientEndPoint.Address ) );
            header.Append( "\r\n" );
            header.Append( String.Format( "     by {0} (Sitefinity's Mail Server)", domain ) );
            header.Append( "\r\n" );
            header.Append( "     " + System.DateTime.Now );
            header.Append( "\r\n" );
            
            message.AddData( header.ToString() );
            
            String line = context.ReadLine();
            while( !line.Equals( "." ) )
            {
                message.AddData( line );
                message.AddData( "\r\n" );
                line = context.ReadLine();
            }
            
            // Spool the message
            messageSpool.SpoolMessage( message );
            context.WriteLine( MESSAGE_OK );


            OnMessageReceived(new MessageEventArgs(message));
            
            // Reset the connection.
            context.Reset();
        }
 /// <summary>
 /// Reset the connection state.
 /// </summary>
 private void Rset( SMTPContext context )
 {
     if( context.LastCommand != -1 )
     {
         // Dump the message and reset the context.
         context.Reset();
         context.WriteLine( MESSAGE_OK );
     }
     else
     {
         context.WriteLine( MESSAGE_INVALID_COMMAND_ORDER );
     }
 }
 /// <summary>
 /// Handle the MAIL FROM:&lt;address&gt; command.
 /// </summary>
 private void Mail( SMTPContext context, string argument )
 {
     bool addressValid = false;
     if( context.LastCommand == COMMAND_HELO )
     {
         string address = ParseAddress( argument );
         if( address != null )
         {
             try
             {
                 EmailAddress emailAddress = new EmailAddress( address );
                 context.Message.FromAddress = emailAddress;
                 context.LastCommand = COMMAND_MAIL;
                 addressValid = true;
                 context.WriteLine( MESSAGE_OK );
                 //if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: MailFrom address: {1} accepted.", context.ConnectionId, address ) );
             }
             catch( InvalidEmailAddressException )
             {
                 // This is fine, just fall through.
             }
         }
         
         // If the address is invalid, inform the client.
         if( !addressValid )
         {
             //if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: MailFrom argument: {1} rejected.  Should be from:<*****@*****.**>", context.ConnectionId, argument ) );
             context.WriteLine( MESSAGE_INVALID_ADDRESS );
         }
     }
     else
     {
         context.WriteLine( MESSAGE_INVALID_COMMAND_ORDER );
     }
 }
 /// <summary>
 /// Handles the HELO command.
 /// </summary>
 private void Helo( SMTPContext context, String[] inputs )
 {
     if( context.LastCommand == -1 )
     {
         if( inputs.Length == 2 )
         {
             context.ClientDomain = inputs[1];
             context.LastCommand = COMMAND_HELO;
             context.WriteLine( HeloResponse );				
         }
         else
         {
             context.WriteLine( MESSAGE_INVALID_ARGUMENT_COUNT );
         }
     }
     else
     {
         context.WriteLine( MESSAGE_INVALID_COMMAND_ORDER );
     }
 }
        /// <summary>
        /// Handles the command input from the client.  This
        /// message returns when the client issues the quit command.
        /// </summary>
        private void ProcessCommands( SMTPContext context )
        {
            bool isRunning = true;
            String inputLine;
            
            // Loop until the client quits.
            while( isRunning )
            {
                try
                {
                    inputLine = context.ReadLine();
                    if( inputLine == null )
                    {
                        isRunning = false;
                        context.Close();
                        continue;
                    }

                    //log.Debug( "ProcessCommands Read: " + inputLine );
                    String[] inputs = inputLine.Split( " ".ToCharArray() );
                    
                    switch( inputs[0].ToLower() )
                    {
                        case "helo":
                        case "ehlo":
                            Helo( context, inputs );
                            break;
                        case "rset":
                            Rset( context );
                            break;
                        case "noop":
                            context.WriteLine( MESSAGE_OK );
                            break;
                        case "quit":
                            isRunning = false;
                            context.WriteLine( MESSAGE_GOODBYE );
                            context.Close();
                            break;
                        case "mail":
                            if( inputs[1].ToLower().StartsWith( "from" ) )
                            {
                                Mail( context, inputLine.Substring( inputLine.IndexOf( " " ) ) );
                                break;
                            }
                            context.WriteLine( MESSAGE_UNKNOWN_COMMAND );
                            break;
                        case "rcpt":
                            if( inputs[1].ToLower().StartsWith( "to" ) ) 							
                            {
                                Rcpt( context, inputLine.Substring( inputLine.IndexOf( " " ) ) );
                                break;
                            }
                            context.WriteLine( MESSAGE_UNKNOWN_COMMAND );
                            break;
                        case "data":
                            Data( context );
                            break;
                        default:
                            context.WriteLine( MESSAGE_UNKNOWN_COMMAND );
                            break;
                    }				
                }
                catch( Exception exception )
                {
                    //log.Error( String.Format( "Connection {0}: Exception occured while processing commands: {1}", context.ConnectionId, exception ), exception );
                    context.WriteLine( MESSAGE_SYSTEM_ERROR );
                }
            }
        }
 /// <summary>
 /// Sends the welcome greeting to the client.
 /// </summary>
 private void SendWelcomeMessage( SMTPContext context )
 {
     context.WriteLine( WelcomeMessage );
 }
 /// <summary>
 /// ProcessConnection handles a connected TCP Client
 /// and performs all necessary interaction with this
 /// client to comply with RFC821.  This method is thread 
 /// safe.
 /// </summary>
 public void ProcessConnection( Socket socket )
 {
     long currentConnectionId = 0;
     // Really only need to lock on the long, but that is not
     // allowed.  Is there a better way to do this?
     lock( this )
     {
         currentConnectionId = connectionId++;
     }
     
     SMTPContext context = new SMTPContext( currentConnectionId, socket );
     
     try 
     {
         SendWelcomeMessage( context );
         
         ProcessCommands( context );
     }
     catch( Exception exception )
     {
         //log.Error( String.Format( "Connection {0}: Error: {1}", context.ConnectionId, exception ), exception );
     }
 }
 /// <summary>
 /// Accepts only local email.
 /// </summary>
 /// <param name='context'>The SMTPContext</param>
 /// <param name='recipient'>TODO - add parameter description</param>
 public virtual bool AcceptRecipient( SMTPContext context, EmailAddress recipient )
 {
     return domain.Equals( recipient.Domain );
 }