Пример #1
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);
        }
Пример #2
0
        /// <summary>
        /// Try to make a address.
        /// </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["[" ( IPv4-address-literal / IPv6-address-literal / General-address-literal ) "]"]]></remarks>
        public bool TryMakeAddressLiteral(TokenEnumerator enumerator, out string address)
        {
            address = null;

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

            // skip any whitespace
            enumerator.TakeWhile(t => t.Kind == TokenKind.Space);

            if (TryMake(enumerator, TryMakeIpv4AddressLiteral, out address) == false)
            {
                return(false);
            }

            // skip any whitespace
            enumerator.TakeWhile(t => t.Kind == TokenKind.Space);

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

            return(address != null);
        }
Пример #3
0
        /// <summary>
        /// Try to make a path.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the path from.</param>
        /// <param name="mailbox">The path that was made, or undefined if it was not made.</param>
        /// <returns>true if the path was made, false if not.</returns>
        /// <remarks><![CDATA["<" [ A-d-l ":" ] Mailbox ">"]]></remarks>
        public bool TryMakePath(TokenEnumerator enumerator, out IMailbox mailbox)
        {
            mailbox = null;

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

            // Note, the at-domain-list must be matched, but also must be ignored
            // http://tools.ietf.org/html/rfc5321#appendix-C
            string atDomainList;

            if (TryMake(enumerator, TryMakeAtDomainList, out atDomainList))
            {
                // if the @domain list was matched then it needs to be followed by a colon
                if (enumerator.Take() != new Token(TokenKind.Punctuation, ":"))
                {
                    return(false);
                }
            }

            if (TryMake(enumerator, TryMakeMailbox, out mailbox) == false)
            {
                return(false);
            }

            return(enumerator.Take() == new Token(TokenKind.Symbol, ">"));
        }
Пример #4
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);
        }
Пример #5
0
        /// <summary>
        /// Try to make a quoted pair from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the text from.</param>
        /// <param name="text">The text that was made.</param>
        /// <returns>true if the quoted pair was made, false if not.</returns>
        /// <remarks><![CDATA[%d92 %d32-126]]></remarks>
        public bool TryMakeQuotedPairSmtp(TokenEnumerator enumerator, out string text)
        {
            text = null;

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

            text += enumerator.Take().Text;

            return(true);
        }
Пример #6
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);
        }
Пример #7
0
        /// <summary>
        /// Try to make the allowable characters in a base64 encoded string.
        /// </summary>
        /// <param name="enumerator">The enumerator to perform the make on.</param>
        /// <param name="base64Chars">The base64 characters that were found.</param>
        /// <returns>true if the base64-chars can be made, false if not.</returns>
        /// <remarks><![CDATA[ALPHA / DIGIT / "+" / "/"]]></remarks>
        static bool TryMakeBase64Chars(TokenEnumerator enumerator, out string base64Chars)
        {
            base64Chars = null;

            var token = enumerator.Take();

            switch (token.Kind)
            {
            case TokenKind.Text:
            case TokenKind.Number:
                base64Chars = token.Text;
                return(true);

            case TokenKind.Punctuation:
                switch (token.Text[0])
                {
                case '/':
                    base64Chars = token.Text;
                    return(true);
                }
                break;

            case TokenKind.Symbol:
                switch (token.Text[0])
                {
                case '+':
                    base64Chars = token.Text;
                    return(true);
                }
                break;
            }

            return(false);
        }
Пример #8
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.Take() != new Token(TokenKind.Symbol, "="))
            {
                return(false);
            }

            string value;

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

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

            return(true);
        }
Пример #9
0
        /// <summary>
        /// Try to make a QTextSMTP from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the text from.</param>
        /// <param name="text">The text that was made.</param>
        /// <returns>true if the quoted text was made, false if not.</returns>
        /// <remarks><![CDATA[%d32-33 / %d35-91 / %d93-126]]></remarks>
        public bool TryMakeQTextSmtp(TokenEnumerator enumerator, out string text)
        {
            text = null;

            var token = enumerator.Take();

            switch (token.Kind)
            {
            case TokenKind.Text:
            case TokenKind.Space:
            case TokenKind.Number:
            case TokenKind.Symbol:
                text += token.Text;
                return(true);

            case TokenKind.Punctuation:
                if (token.Text[0] == '"' || token.Text[0] == '\\')
                {
                    return(false);
                }
                text += token.Text;
                return(true);
            }

            return(false);
        }
Пример #10
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);
        }
Пример #11
0
        /// <summary>
        /// Try to make a text or number
        /// </summary>
        /// <param name="enumerator">The enumerator to make a text or number from.</param>
        /// <param name="textOrNumber">The text or number that was made, or undefined if it was not made.</param>
        /// <returns>true if the text or number was made, false if not.</returns>
        /// <remarks><![CDATA[ALPHA / DIGIT]]></remarks>
        public bool TryMakeTextOrNumber(TokenEnumerator enumerator, out string textOrNumber)
        {
            var token = enumerator.Take();

            textOrNumber = token.Text;

            return(token.Kind == TokenKind.Text || token.Kind == TokenKind.Number);
        }
Пример #12
0
        public void EnumerateTokens()
        {
            var tokenizer = new TokenEnumerator(new ByteArrayTokenReader(Segments));

            while (tokenizer.Peek() != Token.None)
            {
                tokenizer.Take();
            }
        }
Пример #13
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);
        }
Пример #14
0
        /// <summary>
        /// Try to make an Snum (number in the range of 0-255).
        /// </summary>
        /// <param name="enumerator">The enumerator to make the address from.</param>
        /// <param name="snum">The snum that was made, or undefined if it was not made.</param>
        /// <returns>true if the snum was made, false if not.</returns>
        /// <remarks><![CDATA[ 1*3DIGIT ]]></remarks>
        public bool TryMakeSnum(TokenEnumerator enumerator, out int snum)
        {
            var token = enumerator.Take();

            if (Int32.TryParse(token.Text, out snum) && token.Kind == TokenKind.Number)
            {
                return(snum >= 0 && snum <= 255);
            }

            return(false);
        }
Пример #15
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, "\""));
        }
Пример #16
0
        /// <summary>
        /// Try to make an "Atext" from the tokens.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the atext from.</param>
        /// <param name="atext">The atext that was made, or undefined if it was not made.</param>
        /// <returns>true if the atext was made, false if not.</returns>
        /// <remarks><![CDATA[atext]]></remarks>
        public bool TryMakeAtext(TokenEnumerator enumerator, out string atext)
        {
            atext = null;

            var token = enumerator.Take();

            switch (token.Kind)
            {
            case TokenKind.Text:
            case TokenKind.Number:
                atext = token.Text;
                return(true);

            case TokenKind.Punctuation:
                switch (token.Text[0])
                {
                case '!':
                case '#':
                case '%':
                case '&':
                case '\'':
                case '*':
                case '-':
                case '/':
                case '?':
                case '_':
                case '{':
                case '}':
                    atext = token.Text;
                    return(true);
                }
                break;

            case TokenKind.Symbol:
                switch (token.Text[0])
                {
                case '$':
                case '+':
                case '=':
                case '^':
                case '`':
                case '|':
                case '~':
                    atext = token.Text;
                    return(true);
                }
                break;
            }

            return(false);
        }
Пример #17
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);
        }
Пример #18
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);
        }
Пример #19
0
        /// <summary>
        /// Try to make a reverse path.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the reverse path from.</param>
        /// <param name="mailbox">The reverse path that was made, or undefined if it was not made.</param>
        /// <returns>true if the reverse path was made, false if not.</returns>
        /// <remarks><![CDATA[Path / "<>"]]></remarks>
        public bool TryMakeReversePath(TokenEnumerator enumerator, out IMailbox mailbox)
        {
            if (TryMake(enumerator, TryMakePath, out mailbox))
            {
                return(true);
            }

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

            // not valid according to the spec but some senders do it
            enumerator.TakeWhile(t => t.Kind == TokenKind.Space);

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

            mailbox = null;

            return(true);
        }
Пример #20
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, "-"));
        }
Пример #21
0
        /// <summary>
        /// Try to make an @domain.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the @domain from.</param>
        /// <param name="atDomain">The @domain that was made, or undefined if it was not made.</param>
        /// <returns>true if the @domain was made, false if not.</returns>
        /// <remarks><![CDATA["@" Domain]]></remarks>
        public bool TryMakeAtDomain(TokenEnumerator enumerator, out string atDomain)
        {
            atDomain = null;

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

            string domain;

            if (TryMake(enumerator, TryMakeDomain, out domain) == false)
            {
                return(false);
            }

            atDomain = String.Format("@{0}", domain);

            return(true);
        }
Пример #22
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);
        }
Пример #23
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);
        }
Пример #24
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);
        }
Пример #25
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);
        }
Пример #26
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);
        }
Пример #27
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);
        }
Пример #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 a mailbox.
        /// </summary>
        /// <param name="enumerator">The enumerator to make the mailbox from.</param>
        /// <param name="mailbox">The mailbox that was made, or undefined if it was not made.</param>
        /// <returns>true if the mailbox was made, false if not.</returns>
        /// <remarks><![CDATA[Local-part "@" ( Domain / address-literal )]]></remarks>
        public bool TryMakeMailbox(TokenEnumerator enumerator, out IMailbox mailbox)
        {
            mailbox = null;

            string localpart;

            if (TryMake(enumerator, TryMakeLocalPart, out localpart) == false)
            {
                return(false);
            }

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

            string domain;

            if (TryMake(enumerator, TryMakeDomain, out domain))
            {
                mailbox = new Mailbox(localpart, domain);

                return(true);
            }

            string address;

            if (TryMake(enumerator, TryMakeAddressLiteral, out address))
            {
                mailbox = new Mailbox(localpart, address);

                return(true);
            }

            return(false);
        }