SMTPContext.cs :  » Email » SharpWebMail » EricDaugherty » CSES » SmtpServer » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Email » SharpWebMail 
SharpWebMail » EricDaugherty » CSES » SmtpServer » SMTPContext.cs
namespace EricDaugherty.CSES.SmtpServer{
  using System;
  using System.Net.Sockets;
  using System.Text;
  using log4net;
  
  /// <summary>
  /// Maintains the current state for a SMTP client connection.
  /// </summary>
  /// <remarks>
  /// This class is similar to a HTTP Session.  It is used to maintain all
  /// the state information about the current connection.
  /// </remarks>
  public class SMTPContext : object
  {
    #region Constants
    
    private const string EOL = "\r\n";
    
    #endregion
    
    #region Variables
    
    /// <summary>The unique ID assigned to this connection</summary>
    private long connectionId;
    
    /// <summary>The socket to the client.</summary>
    private Socket socket;
    
    /// <summary>Last successful command received.</summary>
    private int lastCommand;
    
    /// <summary>The client domain, as specified by the helo command.</summary>
    private string clientDomain;
    
    /// <summary>The incoming message.</summary>
    private SMTPMessage message;
    
    /// <summary>Encoding to use to send/receive data from the socket.</summary>
    private Encoding encoding;
    
    /// <summary>
    /// It is possible that more than one line will be in
    /// the queue at any one time, so we need to store any input
    /// that has been read from the socket but not requested by the
    /// ReadLine command yet.
    /// </summary>
    private StringBuilder inputBuffer;
    
    /// <summary>Default Logger</summary>
    private static ILog log = LogManager.GetLogger( typeof( SMTPContext ) );
    
    /// <summary>Logs all IO.  Seperate from normal Logger.</summary>
    private static ILog ioLog = LogManager.GetLogger( "IO." + typeof( SMTPContext ) );
        
    #endregion
    
    #region Constructors
    
    /// <summary>
    /// Initialize this context for a given socket connection.
    /// </summary>
    public SMTPContext( long connectionId, Socket socket )
    {
      if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: New connection from client {1}", connectionId, socket.RemoteEndPoint ) );
      
      this.connectionId = connectionId;
      this.lastCommand = -1;
      this.socket = socket;
      message = new SMTPMessage();
      
      // Set the encoding to ASCII.  
      encoding = Encoding.ASCII;
      
      // Initialize the input buffer
      inputBuffer = new StringBuilder();
    }
    
    #endregion
    
    #region Properties
    
    /// <summary>
    /// The unique connection id.
    /// </summary>
    public long ConnectionId
    {
      get
      {
        return connectionId;
      }
    }
    
    /// <summary>
    /// Last successful command received.
    /// </summary>
    public int LastCommand
    {
      get
      {
        return lastCommand;
      }
      set
      {
        lastCommand = value;
      }
    }
    
    /// <summary>
    /// The client domain, as specified by the helo command.
    /// </summary>
    public string ClientDomain
    {
      get
      {
        return clientDomain;
      }
      set
      {
        clientDomain = value;
      }
    }
    
    /// <summary>
    /// The Socket that is connected to the client.
    /// </summary>
    public Socket Socket
    {
      get
      {
        return socket;
      }
    }
    
    /// <summary>
    /// The SMTPMessage that is currently being received.
    /// </summary>
    public SMTPMessage Message
    {
      get
      {
        return message;
      }
      set
      {
        message = value;
      }
    }
    
    #endregion
    
    #region Public Methods
    
    /// <summary>
    /// Writes the string to the socket as an entire line.  This
    /// method will append the end of line characters, so the data
    /// parameter should not contain them.
    /// </summary>
    /// <param name="data">The data to write the the client.</param>
    public void WriteLine( string data )
    {
      if( ioLog.IsDebugEnabled ) ioLog.Debug( String.Format( "Connection {0}: Wrote Line: {1}", connectionId, data ) );
      socket.Send( encoding.GetBytes( data + EOL ) );
    }
    
    /// <summary>
    /// Reads an entire line from the socket.  This method
    /// will block until an entire line has been read.
    /// </summary>
    public String ReadLine()
    {
      // If we already buffered another line, just return
      // from the buffer.      
      string output = ReadBuffer();
      if( output != null )
      {
        return output;
      }
            
      // Otherwise, read more input.
      byte[] byteBuffer = new byte[80];
      int count;
      
      // Read from the socket until an entire line has been read.      
      do
      {
        // Read the input data.
        count = socket.Receive( byteBuffer );
        
        if( count == 0 )
        {
          log.Debug( "Socket closed before end of line received." );
          return null;
        }

        inputBuffer.Append( encoding.GetString( byteBuffer, 0, count ) );        
        if( ioLog.IsDebugEnabled ) ioLog.Debug( String.Format( "Connection {0}: Read: {1}", connectionId, inputBuffer ) );
      }
      while( (output = ReadBuffer()) == null );
      
      // IO Log statement is in ReadBuffer...
      
      return output;
    }
    
    /// <summary>
    /// Resets this context for a new message
    /// </summary>
    public void Reset()
    {
      if( log.IsDebugEnabled ) log.Debug( String.Format( "Connection {0}: Reset" , connectionId ) );
      message = new SMTPMessage();
      lastCommand = SMTPProcessor.COMMAND_HELO;
    }
    
    /// <summary>
    /// Closes the socket connection to the client and performs any cleanup.
    /// </summary>
    public void Close()
    {
      socket.Close();
    }
    
    #endregion
    
    #region Private Methods
    
    /// <summary>
    /// Helper method that returns the first full line in
    /// the input buffer, or null if there is no line in the buffer.
    /// If a line is found, it will also be removed from the buffer.
    /// </summary>
    private string ReadBuffer()
    {
      // If the buffer has data, check for a full line.
      if( inputBuffer.Length > 0 )        
      {
        string buffer = inputBuffer.ToString();
        int eolIndex = buffer.IndexOf( EOL );
        if( eolIndex != -1 )
        {
          string output = buffer.Substring( 0, eolIndex );
          inputBuffer = new StringBuilder( buffer.Substring( eolIndex + 2 ) );
          if( ioLog.IsDebugEnabled ) ioLog.Debug( String.Format( "Connection {0}: Read Line: {1}", connectionId, output ) );
          return output;
        }        
      }
      return null;
    }
    
    #endregion
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.