예제 #1
0
        /// <summary>
        /// Try to make an Esmtp-Parameter from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to perform the make on.</param>
        /// <param name="parameter">The esmtp-parameter that was made.</param>
        /// <returns>true if the esmtp-parameter can be made, false if not.</returns>
        /// <remarks><![CDATA[esmtp-keyword ["=" esmtp-value]]]></remarks>
        public bool TryMakeEsmtpParameter(TokenEnumerator enumerator, out KeyValuePair <string, string> parameter)
        {
            parameter = default(KeyValuePair <string, string>);

            string keyword;

            if (TryMake(enumerator, TryMakeEsmtpKeyword, out keyword) == false)
            {
                return(false);
            }

            if (enumerator.Peek().Kind == TokenKind.None || enumerator.Peek().Kind == TokenKind.Space)
            {
                parameter = new KeyValuePair <string, string>(keyword, null);
                return(true);
            }

            if (enumerator.Peek() != new Token(TokenKind.Symbol, "="))
            {
                return(false);
            }

            enumerator.Take();

            string value;

            if (TryMake(enumerator, TryMakeEsmtpValue, out value) == false)
            {
                return(false);
            }

            parameter = new KeyValuePair <string, string>(keyword, value);

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Make an AUTH command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The AUTH command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeAuth(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "AUTH"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            AuthenticationMethod method;

            if (Enum.TryParse(enumerator.Peek().Text, true, out method) == false)
            {
                _logger.LogVerbose("AUTH command requires a valid method (PLAIN or LOGIN)");

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            enumerator.Take();

            string parameter = null;

            if (enumerator.Count > 0 && _parser.TryMakeBase64(enumerator, out parameter) == false)
            {
                _logger.LogVerbose("AUTH parameter must be a Base64 encoded string");

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            command = new AuthCommand(_options.UserAuthenticator, method, parameter);
            return(true);
        }
예제 #3
0
        internal bool TryMakeEsmtpKeyword(TokenEnumerator enumerator, out string keyword)
        {
            keyword = null;
            Token left = enumerator.Peek(0);

            while (left.Kind == TokenKind.Text || left.Kind == TokenKind.Number || left == new Token(TokenKind.Punctuation, "-"))
            {
                keyword += enumerator.Consume(1).Text;
                left     = enumerator.Peek(0);
            }
            return(keyword != null);
        }
예제 #4
0
        internal bool TryMakeTextOrNumberOrHyphenString(TokenEnumerator enumerator, out string textOrNumberOrHyphenString)
        {
            textOrNumberOrHyphenString = null;
            Token left = enumerator.Peek(0);

            while (left.Kind == TokenKind.Text || left.Kind == TokenKind.Number || left == new Token(TokenKind.Punctuation, "-"))
            {
                textOrNumberOrHyphenString += enumerator.Consume(1).Text;
                left = enumerator.Peek(0);
            }
            return(textOrNumberOrHyphenString != null && left != new Token(TokenKind.Punctuation, "-"));
        }
예제 #5
0
        /// <summary>
        /// Try to make an Esmtp-Keyword from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to perform the make on.</param>
        /// <param name="keyword">The esmtp-keyword that was made.</param>
        /// <returns>true if the esmtp-keyword can be made, false if not.</returns>
        /// <remarks><![CDATA[(ALPHA / DIGIT) *(ALPHA / DIGIT / "-")]]></remarks>
        public bool TryMakeEsmtpKeyword(TokenEnumerator enumerator, out string keyword)
        {
            keyword = null;

            var token = enumerator.Peek();

            while (token.Kind == TokenKind.Text || token.Kind == TokenKind.Number || token == new Token(TokenKind.Punctuation, "-"))
            {
                keyword += enumerator.Take().Text;

                token = enumerator.Peek();
            }

            return(keyword != null);
        }
예제 #6
0
        /// <summary>
        /// Try to make an Esmtp-Value from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to perform the make on.</param>
        /// <param name="value">The esmtp-value that was made.</param>
        /// <returns>true if the esmtp-value can be made, false if not.</returns>
        /// <remarks><![CDATA[1*(%d33-60 / %d62-127)]]></remarks>
        public bool TryMakeEsmtpValue(TokenEnumerator enumerator, out string value)
        {
            value = null;

            var token = enumerator.Peek();

            while (token.Text.Length > 0 && token.Text.ToCharArray().All(ch => (ch >= 33 && ch <= 66) || (ch >= 62 && ch <= 127)))
            {
                value += enumerator.Take().Text;

                token = enumerator.Peek();
            }

            return(value != null);
        }
예제 #7
0
        /// <summary>
        /// Make an EHLO command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The EHLO command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeEhlo(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "EHLO"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            string domain;

            if (_parser.TryMakeDomain(enumerator, out domain))
            {
                command = new EhloCommand(domain, _options);
                return(true);
            }

            string address;

            if (_parser.TryMakeAddressLiteral(enumerator, out address))
            {
                command = new EhloCommand(address, _options);
                return(true);
            }

            errorResponse = SmtpResponse.SyntaxError;
            return(false);
        }
예제 #8
0
        internal bool TryMakeEsmtpValue(TokenEnumerator enumerator, out string value)
        {
            value = null;
            Token token = enumerator.Peek(0);

            while (token.Text.Length > 0)
            {
                if (!token.Text.ToCharArray().All((char ch) => (ch >= '!' && ch <= 'B') || (ch >= '>' && ch <= '\u007f')))
                {
                    break;
                }
                value += enumerator.Consume(1).Text;
                token  = enumerator.Peek(0);
            }
            return(value != null);
        }
예제 #9
0
        /// <summary>
        /// Make a RCTP command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The RCTP command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeRcpt(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "RCPT"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            if (enumerator.Take() != new Token(TokenKind.Text, "TO") || enumerator.Take() != new Token(TokenKind.Punctuation, ":"))
            {
                errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError, "missing the TO:");
                return(false);
            }

            // according to the spec, whitespace isnt allowed here anyway
            enumerator.TakeWhile(TokenKind.Space);

            IMailbox mailbox;

            if (_parser.TryMakePath(enumerator, out mailbox) == false)
            {
                _logger.LogVerbose("Syntax Error (Text={0})", enumerator.AsText());

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            // TODO: support optional service extension parameters here

            command = new RcptCommand(mailbox, _options.MailboxFilterFactory);
            return(true);
        }
예제 #10
0
        /// <summary>
        /// Try to make a text/number/hyphen string.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the text/number/hyphen from.</param>
        /// <param name="textOrNumberOrHyphenString">The text, number, or hyphen that was matched, or undefined if it was not matched.</param>
        /// <returns>true if a text, number or hyphen was made, false if not.</returns>
        /// <remarks><![CDATA[*( ALPHA / DIGIT / "-" ) Let-dig]]></remarks>
        public bool TryMakeTextOrNumberOrHyphenString(TokenEnumerator enumerator, out string textOrNumberOrHyphenString)
        {
            textOrNumberOrHyphenString = null;

            var token = enumerator.Peek();

            while (token.Kind == TokenKind.Text || token.Kind == TokenKind.Number || token == new Token(TokenKind.Punctuation, "-"))
            {
                textOrNumberOrHyphenString += enumerator.Take().Text;

                token = enumerator.Peek();
            }

            // can not end with a hyphen
            return(textOrNumberOrHyphenString != null && token != new Token(TokenKind.Punctuation, "-"));
        }
예제 #11
0
        /// <summary>
        /// Try to make an IPv4 address literal.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the address from.</param>
        /// <param name="address">The address that was made, or undefined if it was not made.</param>
        /// <returns>true if the address was made, false if not.</returns>
        /// <remarks><![CDATA[ Snum 3("."  Snum) ]]></remarks>
        public bool TryMakeIpv4AddressLiteral(TokenEnumerator enumerator, out string address)
        {
            address = null;

            int snum;

            if (TryMake(enumerator, TryMakeSnum, out snum) == false)
            {
                return(false);
            }

            address = snum.ToString(CultureInfo.InvariantCulture);

            for (var i = 0; i < 3 && enumerator.Peek() == new Token(TokenKind.Punctuation, "."); i++)
            {
                enumerator.Take();

                if (TryMake(enumerator, TryMakeSnum, out snum) == false)
                {
                    return(false);
                }

                address = String.Concat(address, '.', snum);
            }

            return(true);
        }
예제 #12
0
        public void EnumerateTokens()
        {
            var tokenizer = new TokenEnumerator(new ByteArrayTokenReader(Segments));

            while (tokenizer.Peek() != Token.None)
            {
                tokenizer.Take();
            }
        }
예제 #13
0
 internal bool TryMakeBase64(TokenEnumerator enumerator, out string base64)
 {
     base64 = null;
     while (enumerator.Peek(0).Kind != TokenKind.None)
     {
         string str;
         if (!TryMake <string>(enumerator, new TryMakeDelegate <string>(TryMakeBase64Chars), out str))
         {
             return(false);
         }
         base64 += str;
     }
     return(base64 != null && base64.Length % 4 == 0);
 }
예제 #14
0
 internal bool TryMakeMailParameters(TokenEnumerator enumerator, out IDictionary <string, string> parameters)
 {
     parameters = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
     while (enumerator.Peek(0).Kind != TokenKind.None)
     {
         KeyValuePair <string, string> item;
         if (!TryMake <KeyValuePair <string, string> >(enumerator, new TryMakeDelegate <KeyValuePair <string, string> >(TryMakeEsmtpParameter), out item))
         {
             return(false);
         }
         parameters.Add(item);
         enumerator.ConsumeWhile((Token t) => t.Kind == TokenKind.Space);
     }
     return(parameters.Count > 0);
 }
예제 #15
0
 internal bool TryMakeAtDomainList(TokenEnumerator enumerator, out string atDomainList)
 {
     if (!TryMake <string>(enumerator, new TryMakeDelegate <string>(TryMakeAtDomain), out atDomainList))
     {
         return(false);
     }
     while (enumerator.Peek(0) == new Token(TokenKind.Punctuation, ","))
     {
         enumerator.Consume(1);
         string arg;
         if (!TryMake <string>(enumerator, new TryMakeDelegate <string>(TryMakeAtDomain), out arg))
         {
             return(false);
         }
         atDomainList += string.Format(",{0}", arg);
     }
     return(true);
 }
예제 #16
0
 internal bool TryMakeDotString(TokenEnumerator enumerator, out string dotString)
 {
     if (!TryMake <string>(enumerator, new TryMakeDelegate <string>(TryMakeAtom), out dotString))
     {
         return(false);
     }
     while (enumerator.Peek(0) == new Token(TokenKind.Punctuation, "."))
     {
         enumerator.Consume(1);
         string str;
         if (!TryMake <string>(enumerator, new TryMakeDelegate <string>(TryMakeAtom), out str))
         {
             return(true);
         }
         dotString += "." + str;
     }
     return(true);
 }
예제 #17
0
            internal bool TryAccept(TokenEnumerator tokenEnumerator, out SmtpCommand command)
            {
                Tuple <State.MakeDelegate, int> tuple;

                if (!_state.Actions.TryGetValue(tokenEnumerator.Peek(0).Text, out tuple))
                {
                    string response = string.Format("expected {0}", string.Join("/", _state.Actions.Keys));
                    command = _commandFactory.MakeInvalid(SmtpReplyCode.SyntaxError, response);
                    return(false);
                }
                command = tuple.Item1(tokenEnumerator);
                if (!(command is InvalidCommand))
                {
                    _state = _states[tuple.Item2];
                    return(true);
                }
                return(false);
            }
예제 #18
0
        /// <summary>
        /// Try to make an Mail-Parameters from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to perform the make on.</param>
        /// <param name="parameters">The mail parameters that were made.</param>
        /// <returns>true if the mail parameters can be made, false if not.</returns>
        /// <remarks><![CDATA[esmtp-param *(SP esmtp-param)]]></remarks>
        public bool TryMakeMailParameters(TokenEnumerator enumerator, out IDictionary <string, string> parameters)
        {
            parameters = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            while (enumerator.Peek().Kind != TokenKind.None)
            {
                KeyValuePair <string, string> parameter;
                if (TryMake(enumerator, TryMakeEsmtpParameter, out parameter) == false)
                {
                    return(false);
                }

                parameters.Add(parameter);
                enumerator.TakeWhile(t => t.Kind == TokenKind.Space);
            }

            return(parameters.Count > 0);
        }
예제 #19
0
        internal SmtpCommand MakeAuth(TokenEnumerator enumerator)
        {
            enumerator.Consume(1);
            enumerator.ConsumeWhile((Token t) => t.Kind == TokenKind.Space);
            AuthenticationMethod method;

            if (!Enum.TryParse(enumerator.Peek(0).Text, true, out method))
            {
                return(MakeInvalid(SmtpReplyCode.SyntaxError, ""));
            }
            enumerator.Consume(1);
            string parameter = null;

            if (enumerator.Count > 0 && !_parser.TryMakeBase64(enumerator, out parameter))
            {
                return(MakeInvalid(SmtpReplyCode.SyntaxError, ""));
            }
            return(new AuthCommand(_server.UserAuthenticator, method, parameter));
        }
예제 #20
0
        /// <summary>
        /// Try to make a base64 encoded string.
        /// </summary>
        /// <param name="enumerator">The enumerator to perform the make on.</param>
        /// <param name="base64">The base64 encoded string that were found.</param>
        /// <returns>true if the base64 encoded string can be made, false if not.</returns>
        /// <remarks><![CDATA[ALPHA / DIGIT / "+" / "/"]]></remarks>
        public bool TryMakeBase64(TokenEnumerator enumerator, out string base64)
        {
            base64 = null;

            while (enumerator.Peek().Kind != TokenKind.None)
            {
                string base64Chars;
                if (TryMake(enumerator, TryMakeBase64Chars, out base64Chars) == false)
                {
                    return(false);
                }

                base64 += base64Chars;
            }

            // because the TryMakeBase64Chars method matches tokens, each Text token could make
            // up several Base64 encoded "bytes" so we ensure that we have a length divisible by 4
            return(base64 != null && base64.Length % 4 == 0);
        }
예제 #21
0
            /// <summary>
            /// Advances the enumerator to the next command in the stream.
            /// </summary>
            /// <param name="context">The session context to use for making session based transitions.</param>
            /// <param name="tokenEnumerator">The token enumerator to accept the command from.</param>
            /// <param name="command">The command that is defined within the token enumerator.</param>
            /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
            /// <returns>true if a valid command was found, false if not.</returns>
            public bool TryMake(SmtpSessionContext context, TokenEnumerator tokenEnumerator, out SmtpCommand command, out SmtpResponse errorResponse)
            {
                if (_states[_current].Transitions.TryGetValue(tokenEnumerator.Peek().Text, out _transition) == false)
                {
                    var response = $"expected {String.Join("/", _states[_current].Transitions.Keys)}";

                    command       = null;
                    errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError, response);

                    return(false);
                }

                if (_transition.Delegate(tokenEnumerator, out command, out errorResponse) == false)
                {
                    return(false);
                }

                return(true);
            }
예제 #22
0
        /// <summary>
        /// Make a MAIL command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The MAIL command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeMail(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "MAIL"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            if (enumerator.Take() != new Token(TokenKind.Text, "FROM") || enumerator.Take() != new Token(TokenKind.Punctuation, ":"))
            {
                errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError, "missing the FROM:");
                return(false);
            }

            // according to the spec, whitespace isnt allowed here but most servers send it
            enumerator.TakeWhile(TokenKind.Space);

            IMailbox mailbox;

            if (_parser.TryMakeReversePath(enumerator, out mailbox) == false)
            {
                _logger.LogVerbose("Syntax Error (Text={0})", enumerator.AsText());

                errorResponse = new SmtpResponse(SmtpReplyCode.SyntaxError);
                return(false);
            }

            enumerator.TakeWhile(TokenKind.Space);

            // match the optional (ESMTP) parameters
            IReadOnlyDictionary <string, string> parameters;

            if (_parser.TryMakeMailParameters(enumerator, out parameters) == false)
            {
                parameters = new Dictionary <string, string>();
            }

            command = new MailCommand(_options, mailbox, parameters);
            return(true);
        }
예제 #23
0
        /// <summary>
        /// Make an RSET command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The RSET command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeRset(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "RSET"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            if (enumerator.Count > 1)
            {
                _logger.LogVerbose("RSET command can not have parameters (found {0} parameters).", enumerator.Count);

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            command = RsetCommand.Instance;
            return(true);
        }
예제 #24
0
        /// <summary>
        /// Make an STARTTLS command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The STARTTLS command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeStartTls(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "STARTTLS"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            if (enumerator.Count > 1)
            {
                _logger.LogVerbose("STARTTLS command can not have parameters (Tokens={0})", enumerator.Count);

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            command = new StartTlsCommand(_options.ServerCertificate);
            return(true);
        }
예제 #25
0
        /// <summary>
        /// Make a DATA command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The DATA command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeData(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "DATA"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            if (enumerator.Count > 1)
            {
                _logger.LogVerbose("DATA command can not have parameters (Tokens={0})", enumerator.Count);

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            command = new DataCommand(_options.MessageStoreFactory);
            return(true);
        }
예제 #26
0
        /// <summary>
        /// Try to make a quoted-string from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the quoted-string from.</param>
        /// <param name="quotedString">The quoted-string that was made, or undefined if it was not made.</param>
        /// <returns>true if the quoted-string was made, false if not.</returns>
        /// <remarks><![CDATA[DQUOTE * QcontentSMTP DQUOTE]]></remarks>
        public bool TryMakeQuotedString(TokenEnumerator enumerator, out string quotedString)
        {
            quotedString = null;

            if (enumerator.Take() != new Token(TokenKind.Punctuation, "\""))
            {
                return(false);
            }

            while (enumerator.Peek() != new Token(TokenKind.Punctuation, "\""))
            {
                string text;
                if (TryMakeQContentSmtp(enumerator, out text) == false)
                {
                    return(false);
                }

                quotedString += text;
            }

            return(enumerator.Take() == new Token(TokenKind.Punctuation, "\""));
        }
예제 #27
0
        /// <summary>
        /// Try to make a domain name.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the domain name from.</param>
        /// <param name="domain">The domain name that was made, or undefined if it was not made.</param>
        /// <returns>true if the domain name was made, false if not.</returns>
        /// <remarks><![CDATA[sub-domain *("." sub-domain)]]></remarks>
        public bool TryMakeDomain(TokenEnumerator enumerator, out string domain)
        {
            if (TryMake(enumerator, TryMakeSubdomain, out domain) == false)
            {
                return(false);
            }

            while (enumerator.Peek() == new Token(TokenKind.Punctuation, "."))
            {
                enumerator.Take();

                string subdomain;
                if (TryMake(enumerator, TryMakeSubdomain, out subdomain) == false)
                {
                    return(false);
                }

                domain += String.Concat(".", subdomain);
            }

            return(true);
        }
예제 #28
0
        /// <summary>
        /// Make a HELO command from the given enumerator.
        /// </summary>
        /// <param name="enumerator">The enumerator to create the command from.</param>
        /// <param name="command">The HELO command that is defined within the token enumerator.</param>
        /// <param name="errorResponse">The error that indicates why the command could not be made.</param>
        /// <returns>Returns true if a command could be made, false if not.</returns>
        public bool TryMakeHelo(TokenEnumerator enumerator, out SmtpCommand command, out SmtpResponse errorResponse)
        {
            Debug.Assert(enumerator.Peek() == new Token(TokenKind.Text, "HELO"));

            command       = null;
            errorResponse = null;

            enumerator.Take();
            enumerator.TakeWhile(TokenKind.Space);

            string domain;

            if (_parser.TryMakeDomain(enumerator, out domain) == false)
            {
                _logger.LogVerbose("Could not match the domain name (Text={0}).", enumerator.AsText());

                errorResponse = SmtpResponse.SyntaxError;
                return(false);
            }

            command = new HeloCommand(domain);
            return(true);
        }
예제 #29
0
        /// <summary>
        /// Try to make an @domain list.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the @domain list from.</param>
        /// <param name="atDomainList">The @domain list that was made, or undefined if it was not made.</param>
        /// <returns>true if the @domain list was made, false if not.</returns>
        /// <remarks><![CDATA[At-domain *( "," At-domain )]]></remarks>
        public bool TryMakeAtDomainList(TokenEnumerator enumerator, out string atDomainList)
        {
            if (TryMake(enumerator, TryMakeAtDomain, out atDomainList) == false)
            {
                return(false);
            }

            // match the optional list
            while (enumerator.Peek() == new Token(TokenKind.Punctuation, ","))
            {
                enumerator.Take();

                string atDomain;
                if (TryMake(enumerator, TryMakeAtDomain, out atDomain) == false)
                {
                    return(false);
                }

                atDomainList += String.Format(",{0}", atDomain);
            }

            return(true);
        }
예제 #30
0
        /// <summary>
        /// Try to make a dot-string from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the dot-string from.</param>
        /// <param name="dotString">The dot-string that was made, or undefined if it was not made.</param>
        /// <returns>true if the dot-string was made, false if not.</returns>
        /// <remarks><![CDATA[Atom *("."  Atom)]]></remarks>
        public bool TryMakeDotString(TokenEnumerator enumerator, out string dotString)
        {
            if (TryMake(enumerator, TryMakeAtom, out dotString) == false)
            {
                return(false);
            }

            while (enumerator.Peek() == new Token(TokenKind.Punctuation, "."))
            {
                // skip the punctuation
                enumerator.Take();

                string atom;
                if (TryMake(enumerator, TryMakeAtom, out atom) == false)
                {
                    return(true);
                }

                dotString += String.Concat(".", atom);
            }

            return(true);
        }