/// <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; } }
/// <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; } }
/// <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; } }
/// <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; } }
/// <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; } }
/// <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; } }
/// <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; } }