/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="from">MAIL FROM: value.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b>, <b>from</b> or <b>reply</b> is null reference.</exception> public SMTP_e_MailFrom(SMTP_Session session, SMTP_MailFrom from, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (from == null) { throw new ArgumentNullException("from"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_pMailFrom = from; m_pReply = reply; }
private void MAIL(string cmdText) { // RFC 5321 3.1. if (m_SessionRejected) { WriteLine("503 bad sequence of commands: Session rejected."); return; } // RFC 5321 4.1.4. if (string.IsNullOrEmpty(m_EhloHost)) { WriteLine("503 Bad sequence of commands: send EHLO/HELO first."); return; } // RFC 5321 4.1.4. if (m_pFrom != null) { WriteLine("503 Bad sequence of commands: nested MAIL command."); return; } // RFC 3030 BDAT. if (m_pMessageStream != null) { WriteLine("503 Bad sequence of commands: BDAT command is pending."); return; } if (Server.MaxTransactions != 0 && m_Transactions >= Server.MaxTransactions) { WriteLine("503 Bad sequence of commands: Maximum allowed mail transactions exceeded."); return; } /* RFC 5321 4.1.1.2. mail = "MAIL FROM:" Reverse-path [SP Mail-parameters] CRLF Mail-parameters = esmtp-param *(SP esmtp-param) esmtp-param = esmtp-keyword ["=" esmtp-value] esmtp-keyword = (ALPHA / DIGIT) *(ALPHA / DIGIT / "-") esmtp-value = 1*(%d33-60 / %d62-126) ; any CHAR excluding "=", SP, and control ; characters. If this string is an email address, ; i.e., a Mailbox, then the "xtext" syntax [32] SHOULD be used. Reverse-path = Path / "<>" Path = "<" [ A-d-l ":" ] Mailbox ">" 4.1.1.11. If the server SMTP does not recognize or cannot implement one or more of the parameters associated with a particular MAIL FROM or RCPT TO command, it will return code 555. */ if (cmdText.ToUpper().StartsWith("FROM:")) { // Remove FROM: from command text. cmdText = cmdText.Substring(5).Trim(); } else { WriteLine( "501 Syntax error, syntax: \"MAIL FROM:\" \"<\" address \">\" / \"<>\" [SP Mail-parameters] CRLF"); return; } string address = ""; int size = -1; string body = null; string ret = null; string envID = null; // Mailbox not between <>. if (!cmdText.StartsWith("<") || cmdText.IndexOf('>') == -1) { WriteLine( "501 Syntax error, syntax: \"MAIL FROM:\" \"<\" address \">\" / \"<>\" [SP Mail-parameters] CRLF"); return; } // Parse mailbox. else { address = cmdText.Substring(1, cmdText.IndexOf('>') - 1).Trim(); cmdText = cmdText.Substring(cmdText.IndexOf('>') + 1).Trim(); } #region Parse parameters string[] parameters = string.IsNullOrEmpty(cmdText) ? new string[0] : cmdText.Split(' '); foreach (string parameter in parameters) { string[] name_value = parameter.Split(new[] {'='}, 2); // SIZE if (Server.Extentions.Contains(SMTP_ServiceExtensions.SIZE) && name_value[0].ToUpper() == "SIZE") { // RFC 1870. // size-value ::= 1*20DIGIT if (name_value.Length == 1) { WriteLine("501 Syntax error: SIZE parameter value must be specified."); return; } if (!int.TryParse(name_value[1], out size)) { WriteLine("501 Syntax error: SIZE parameter value must be integer."); return; } // Message size exceeds maximum allowed message size. if (size > Server.MaxMessageSize) { WriteLine("552 Message exceeds fixed maximum message size."); return; } } // BODY else if (Server.Extentions.Contains(SMTP_ServiceExtensions._8BITMIME) && name_value[0].ToUpper() == "BODY") { // RFC 1652. // body-value ::= "7BIT" / "8BITMIME" / "BINARYMIME" // // BINARYMIME - defined in RFC 3030. if (name_value.Length == 1) { WriteLine("501 Syntax error: BODY parameter value must be specified."); return; } if (name_value[1].ToUpper() != "7BIT" && name_value[1].ToUpper() != "8BITMIME" && name_value[1].ToUpper() != "BINARYMIME") { WriteLine( "501 Syntax error: BODY parameter value must be \"7BIT\",\"8BITMIME\" or \"BINARYMIME\"."); return; } body = name_value[1].ToUpper(); } // RET else if (Server.Extentions.Contains(SMTP_ServiceExtensions.DSN) && name_value[0].ToUpper() == "RET") { // RFC 1891 5.3. // ret-value = "FULL" / "HDRS" if (name_value.Length == 1) { WriteLine("501 Syntax error: RET parameter value must be specified."); return; } if (name_value[1].ToUpper() != "FULL" && name_value[1].ToUpper() != "HDRS") { WriteLine( "501 Syntax error: RET parameter value must be \"FULL\" or \"HDRS\"."); return; } ret = name_value[1].ToUpper(); } // ENVID else if (Server.Extentions.Contains(SMTP_ServiceExtensions.DSN) && name_value[0].ToUpper() == "ENVID") { if (name_value.Length == 1) { WriteLine("501 Syntax error: ENVID parameter value must be specified."); return; } envID = name_value[1].ToUpper(); } // Unsupported parameter. else { WriteLine("555 Unsupported parameter: " + parameter); return; } } #endregion SMTP_MailFrom from = new SMTP_MailFrom(address, size, body, ret, envID); SMTP_Reply reply = new SMTP_Reply(250, "OK."); reply = OnMailFrom(from, reply); // MAIL accepted. if (reply.ReplyCode < 300) { m_pFrom = from; m_Transactions++; } WriteLine(reply.ToString()); }
/// <summary> /// Cleans up any resource being used. /// </summary> public override void Dispose() { if (IsDisposed) { return; } base.Dispose(); m_pAuthentications = null; m_EhloHost = null; m_pUser = null; m_pFrom = null; m_pTo = null; m_pMessageStream = null; }
/// <summary> /// Raises <b>MailFrom</b> event. /// </summary> /// <param name="from">MAIL FROM: value.</param> /// <param name="reply">Default SMTP server reply.</param> /// <returns>Returns SMTP server reply what must be sent to the connected client.</returns> private SMTP_Reply OnMailFrom(SMTP_MailFrom from, SMTP_Reply reply) { if (MailFrom != null) { SMTP_e_MailFrom eArgs = new SMTP_e_MailFrom(this, from, reply); MailFrom(this, eArgs); return eArgs.Reply; } return reply; }
/// <summary> /// Does reset as specified in RFC 5321. /// </summary> private void Reset() { if (IsDisposed) { return; } m_pFrom = null; m_pTo.Clear(); m_pMessageStream = null; m_BDatReadedCount = 0; }