Beispiel #1
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 5321 4.1.1.9.
                        noop = "NOOP" [ SP String ] CRLF
                    */

                    byte[] buffer = Encoding.UTF8.GetBytes("NOOP\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,"NOOP");

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.NoopCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Beispiel #2
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 3207 4.
                        The format for the STARTTLS command is:

                        STARTTLS

                        with no parameters.

                        After the client gives the STARTTLS command, the server responds with
                        one of the following reply codes:

                        220 Ready to start TLS
                        501 Syntax error (no parameters allowed)
                        454 TLS not available due to temporary reason
                    */

                    byte[] buffer = Encoding.UTF8.GetBytes("STARTTLS\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,"STARTTLS");

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.StartTlsCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Beispiel #3
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    // NOTE: At frist we try EHLO command, if it fails we fallback to HELO.

                    /* RFC 5321 4.1.1.1.
                        ehlo        = "EHLO" SP ( Domain / address-literal ) CRLF  
                     
                        ehlo-ok-rsp = ( "250" SP Domain [ SP ehlo-greet ] CRLF )
                                    / ( "250-" Domain [ SP ehlo-greet ] CRLF
                                     *( "250-" ehlo-line CRLF )
                                        "250" SP ehlo-line CRLF )
                    */

                    byte[] buffer = Encoding.UTF8.GetBytes("EHLO " + m_HostName + "\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,"EHLO " + m_HostName);

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.EhloCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + m_pException.Message,m_pException);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Beispiel #4
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    // See if BDAT supported.
                    bool bdatSupported = false;
                    foreach(string feature in m_pSmtpClient.EsmtpFeatures){
                        if(feature.ToUpper() == SMTP_ServiceExtensions.CHUNKING){
                            bdatSupported = true;

                            break;
                        }
                    }
            
                    // BDAT.
                    if(bdatSupported && m_UseBdat){
                        /* RFC 3030 2.
                            bdat-cmd   ::= "BDAT" SP chunk-size [ SP end-marker ] CR LF
                            chunk-size ::= 1*DIGIT
                            end-marker ::= "LAST"
                        */

                        m_pBdatBuffer    = new byte[64000];
                        m_BdatSendBuffer = new byte[64100]; // 100 bytes for "BDAT xxxxxx...CRLF"

                        // Start reading message data-block.
                        m_pStream.BeginRead(m_pBdatBuffer,0,m_pBdatBuffer.Length,this.BdatChunkReadingCompleted,null);
                    }
                    // DATA.
                    else{
                        /* RFC 5321 4.1.1.4.
                            The mail data are terminated by a line containing only a period, that
                            is, the character sequence "<CRLF>.<CRLF>", where the first <CRLF> is
                            actually the terminator of the previous line.
                          
                            Examples:
			 		            C: DATA<CRLF>
			 		            S: 354 Start sending message, end with <crlf>.<crlf>.<CRLF>
			 		            C: send_message
			 		            C: .<CRLF>
                                S: 250 Ok<CRLF>
                        */

                        byte[] buffer = Encoding.UTF8.GetBytes("DATA\r\n");

                        // Log
                        m_pSmtpClient.LogAddWrite(buffer.Length,"DATA");

                        // Start command sending.
                        m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.DataCommandSendingCompleted,null);
                    }                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + m_pException.Message,m_pException);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Beispiel #5
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 5321 4.1.1.3. RCPT.
                        rcpt = "RCPT TO:" ( "<Postmaster@" Domain ">" / "<Postmaster>" / Forward-path ) [SP Rcpt-parameters] CRLF

			            Examples:
			 		        RCPT TO:<*****@*****.**>
             
                        RFC 3461 adds NOTIFY and ORCPT parameters.
			        */

                    // Build command.
                    StringBuilder cmd = new StringBuilder();
                    cmd.Append("RCPT TO:<" + m_To + ">");            
                    if(m_DsnNotify == SMTP_DSN_Notify.NotSpecified){
                    }
                    else if(m_DsnNotify == SMTP_DSN_Notify.Never){
                        cmd.Append(" NOTIFY=NEVER");
                    }
                    else{
                        bool first = true;                
                        if((m_DsnNotify & SMTP_DSN_Notify.Delay) != 0){
                            cmd.Append(" NOTIFY=DELAY");
                            first = false;
                        }
                        if((m_DsnNotify & SMTP_DSN_Notify.Failure) != 0){
                            if(first){
                                cmd.Append(" NOTIFY=FAILURE");   
                            }
                            else{
                                cmd.Append(",FAILURE");
                            }
                            first = false;
                        }
                        if((m_DsnNotify & SMTP_DSN_Notify.Success) != 0){
                            if(first){
                                cmd.Append(" NOTIFY=SUCCESS");   
                            }
                            else{
                                cmd.Append(",SUCCESS");
                            }
                            first = false;
                        }
                    }
                    if(!string.IsNullOrEmpty(m_ORcpt)){
                        cmd.Append(" ORCPT=" + m_ORcpt);
                    }

                    byte[] buffer = Encoding.UTF8.GetBytes(cmd.ToString() + "\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,cmd.ToString());

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.RcptCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    if(m_pSmtpClient != null){
                        m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    }
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Beispiel #6
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 5321 4.1.1.2. MAIL
			            mail         = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF
                        Reverse-path = Path / "<>"
                        Path         = "<" [ A-d-l ":" ] Mailbox ">"

			  
			           RFC 1870 adds optional SIZE keyword support.
			                SIZE keyword may only be used if it's reported in EHLO command response.
			 	        Examples:
			 		        MAIL FROM:<*****@*****.**> SIZE=1000
             
                       RFC 3461 adds RET and ENVID paramters.
			        */

                    bool isSizeSupported = false;
                    foreach(string feature in m_pSmtpClient.EsmtpFeatures){
                        if(feature.ToLower().StartsWith("size ")){
                            isSizeSupported = true;

                            break;
                        }
                    }

                    // Build command.
                    StringBuilder cmd = new StringBuilder();
                    cmd.Append("MAIL FROM:<" + m_MailFrom + ">");
                    if(isSizeSupported && m_MessageSize > 0){
                        cmd.Append(" SIZE=" + m_MessageSize.ToString());
                    }
                    if(m_DsnRet == SMTP_DSN_Ret.FullMessage){
                        cmd.Append(" RET=FULL");
                    }
                    else if(m_DsnRet == SMTP_DSN_Ret.Headers){
                        cmd.Append(" RET=HDRS");
                    }
                    if(!string.IsNullOrEmpty(m_EnvID)){
                        cmd.Append(" ENVID=" + m_EnvID);
                    }

                    byte[] buffer = Encoding.UTF8.GetBytes(cmd.ToString() + "\r\n");

                    // Log
                    m_pSmtpClient.LogAddWrite(buffer.Length,cmd.ToString());

                    // Start command sending.
                    m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.MailCommandSendingCompleted,null);                    
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }
Beispiel #7
0
            /// <summary>
            /// Starts operation processing.
            /// </summary>
            /// <param name="owner">Owner SMTP client.</param>
            /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns>
            /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception>
            internal bool Start(SMTP_Client owner)
            {
                if(owner == null){
                    throw new ArgumentNullException("owner");
                }

                m_pSmtpClient = owner;

                SetState(AsyncOP_State.Active);

                try{
                    /* RFC 4954 4. The AUTH Command.

                        AUTH mechanism [initial-response]

                        Arguments:
                            mechanism: A string identifying a [SASL] authentication mechanism.

                            initial-response: An optional initial client response.  If
                            present, this response MUST be encoded as described in Section
                            4 of [BASE64] or contain a single character "=".
                    */

                    if(m_pSASL.SupportsInitialResponse){
                        byte[] buffer = Encoding.UTF8.GetBytes("AUTH " + m_pSASL.Name + " " + Convert.ToBase64String(m_pSASL.Continue(null)) + "\r\n");

                        // Log
                        m_pSmtpClient.LogAddWrite(buffer.Length,Encoding.UTF8.GetString(buffer).TrimEnd());

                        // Start command sending.
                        m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.AuthCommandSendingCompleted,null);
                    }
                    else{
                        byte[] buffer = Encoding.UTF8.GetBytes("AUTH " + m_pSASL.Name + "\r\n");

                        // Log
                        m_pSmtpClient.LogAddWrite(buffer.Length,"AUTH " + m_pSASL.Name);

                        // Start command sending.
                        m_pSmtpClient.TcpStream.BeginWrite(buffer,0,buffer.Length,this.AuthCommandSendingCompleted,null);
                    }
                }
                catch(Exception x){
                    m_pException = x;
                    m_pSmtpClient.LogAddException("Exception: " + x.Message,x);
                    SetState(AsyncOP_State.Completed);
                }

                // Set flag rise CompletedAsync event flag. The event is raised when async op completes.
                // If already completed sync, that flag has no effect.
                lock(m_pLock){
                    m_RiseCompleted = true;

                    return m_State == AsyncOP_State.Active;
                }
            }