/// <summary> /// Default constructor. /// </summary> /// <param name="session">Owner SMTP server session.</param> /// <param name="to">RCPT TO: value.</param> /// <param name="reply">SMTP server reply.</param> /// <exception cref="ArgumentNullException">Is raised when <b>session</b>, <b>to</b> or <b>reply</b> is null reference.</exception> public SMTP_e_RcptTo(SMTP_Session session, SMTP_RcptTo to, SMTP_Reply reply) { if (session == null) { throw new ArgumentNullException("session"); } if (to == null) { throw new ArgumentNullException("from"); } if (reply == null) { throw new ArgumentNullException("reply"); } m_pSession = session; m_pRcptTo = to; m_pReply = reply; }
/// <summary> /// Raises <b>RcptTo</b> event. /// </summary> /// <param name="to">RCPT TO: 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 OnRcptTo(SMTP_RcptTo to, SMTP_Reply reply) { if (RcptTo != null) { SMTP_e_RcptTo eArgs = new SMTP_e_RcptTo(this, to, reply); RcptTo(this, eArgs); return eArgs.Reply; } return reply; }
private void RCPT(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: send 'MAIL FROM:' first."); return; } // RFC 3030 BDAT. if (m_pMessageStream != null) { WriteLine("503 Bad sequence of commands: BDAT command is pending."); return; } /* RFC 5321 4.1.1.3. rcpt = "RCPT TO:" ( "<Postmaster@" Domain ">" / "<Postmaster>" / Forward-path ) [SP Rcpt-parameters] CRLF Rcpt-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. Note that, in a departure from the usual rules for local-parts, the "Postmaster" string shown above is treated as case-insensitive. Forward-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("TO:")) { // Remove TO: from command text. cmdText = cmdText.Substring(3).Trim(); } else { WriteLine( "501 Syntax error, syntax: \"RCPT TO:\" \"<\" address \">\" [SP Rcpt-parameters] CRLF"); return; } string address = ""; SMTP_Notify notify = SMTP_Notify.NotSpecified; string orcpt = null; // Mailbox not between <>. if (!cmdText.StartsWith("<") || cmdText.IndexOf('>') == -1) { WriteLine( "501 Syntax error, syntax: \"RCPT TO:\" \"<\" address \">\" [SP Rcpt-parameters] CRLF"); return; } // Parse mailbox. else { address = cmdText.Substring(1, cmdText.IndexOf('>') - 1).Trim(); cmdText = cmdText.Substring(cmdText.IndexOf('>') + 1).Trim(); } if (address == string.Empty) { WriteLine( "501 Syntax error('address' value must be specified), syntax: \"RCPT TO:\" \"<\" address \">\" [SP Rcpt-parameters] CRLF"); return; } #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); // NOTIFY if (Server.Extentions.Contains(SMTP_ServiceExtensions.DSN) && name_value[0].ToUpper() == "NOTIFY") { /* RFC 1891 5.1. notify-esmtp-value = "NEVER" / 1#notify-list-element notify-list-element = "SUCCESS" / "FAILURE" / "DELAY" a. Multiple notify-list-elements, separated by commas, MAY appear in a NOTIFY parameter; however, the NEVER keyword MUST appear by itself. */ if (name_value.Length == 1) { WriteLine("501 Syntax error: NOTIFY parameter value must be specified."); return; } string[] notifyItems = name_value[1].ToUpper().Split(','); foreach (string notifyItem in notifyItems) { if (notifyItem.Trim().ToUpper() == "NEVER") { notify |= SMTP_Notify.Never; } else if (notifyItem.Trim().ToUpper() == "SUCCESS") { notify |= SMTP_Notify.Success; } else if (notifyItem.Trim().ToUpper() == "FAILURE") { notify |= SMTP_Notify.Failure; } else if (notifyItem.Trim().ToUpper() == "DELAY") { notify |= SMTP_Notify.Delay; } // Invalid or not supported notify item. else { WriteLine("501 Syntax error: Not supported NOTIFY parameter value '" + notifyItem + "'."); return; } } } // ORCPT else if (Server.Extentions.Contains(SMTP_ServiceExtensions.DSN) && name_value[0].ToUpper() == "ORCPT") { if (name_value.Length == 1) { WriteLine("501 Syntax error: ORCPT parameter value must be specified."); return; } orcpt = name_value[1].ToUpper(); } // Unsupported parameter. else { WriteLine("555 Unsupported parameter: " + parameter); } } #endregion // Maximum allowed recipients exceeded. if (m_pTo.Count >= Server.MaxRecipients) { WriteLine("452 Too many recipients"); return; } SMTP_RcptTo to = new SMTP_RcptTo(address, notify, orcpt); SMTP_Reply reply = new SMTP_Reply(250, "OK."); reply = OnRcptTo(to, reply); // RCPT accepted. if (reply.ReplyCode < 300) { if (!m_pTo.ContainsKey(address.ToLower())) { m_pTo.Add(address.ToLower(), to); } } WriteLine(reply.ToString()); }