/// <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;
        }
Exemple #2
0
        /// <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());
        }