示例#1
0
        /// <summary>
        /// Reads SMTP "Mailbox" from the specified MIME reader.
        /// </summary>
        /// <param name="reader">MIME reader.</param>
        /// <returns>Returns SMTP "Mailbox" or null if no SMTP mailbox available.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>reader</b> is null reference.</exception>
        internal static string SMTP_Mailbox(MIME_Reader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }

            // TODO:

            /* RFC 5321.
                Mailbox        = Local-part "@" ( Domain / address-literal )
                Local-part     = Dot-string / Quoted-string ; MAY be case-sensitive
                Dot-string     = Atom *("."  Atom)
            */

            StringBuilder retVal = new StringBuilder();
            if (reader.Peek(true) == '\"')
            {
                retVal.Append("\"" + reader.QuotedString() + "\"");
            }
            else
            {
                retVal.Append(reader.DotAtom());
            }

            if (reader.Peek(true) != '@')
            {
                return null; ;
            }
            else
            {
                // Eat "@".
                reader.Char(true);

                retVal.Append('@');
                retVal.Append(reader.DotAtom());
            }

            return retVal.ToString();
        }
示例#2
0
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Sender: [email protected]'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_Mailbox Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new char[] { ':' }, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            MIME_Reader r = new MIME_Reader(name_value[1].Trim());

            string word = r.QuotedReadToDelimiter(new char[] { ',', '<', ':' });

            // Invalid value.
            if (word == null)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }
            // name-addr
            else if (r.Peek(true) == '<')
            {
                Mail_h_Mailbox h = new Mail_h_Mailbox(name_value[0], new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word)) : null, r.ReadParenthesized()));
                h.m_ParseValue = value;

                return(h);
            }
            // addr-spec
            else
            {
                Mail_h_Mailbox h = new Mail_h_Mailbox(name_value[0], new Mail_t_Mailbox(null, word));
                h.m_ParseValue = value;

                return(h);
            }
        }
        /// <summary>
        /// Parses <b>mailbox-list</b> from specified string value.
        /// </summary>
        /// <param name="value">The <b>mailbox-list</b> string value.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when <b>value</b> is not valid <b>mailbox-list</b> value.</exception>
        public static Mail_t_MailboxList Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            MIME_Reader        r      = new MIME_Reader(value);
            Mail_t_MailboxList retVal = new Mail_t_MailboxList();

            while (true)
            {
                string word = r.QuotedReadToDelimiter(new char[] { ',', '<' });
                // We processed all data.
                if (string.IsNullOrEmpty(word) && r.Available == 0)
                {
                    break;
                }
                // name-addr
                else if (r.Peek(true) == '<')
                {
                    retVal.Add(new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word.Trim())) : null, r.ReadParenthesized()));
                }
                // addr-spec
                else
                {
                    retVal.Add(new Mail_t_Mailbox(null, word));
                }

                // We have more addresses.
                if (r.Peek(true) == ',')
                {
                    r.Char(false);
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Content-Type: text/plain'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_MailboxList Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new[] { ':' }, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            /* RFC 5322 3.4.
             *  mailbox       =   name-addr / addr-spec
             *
             *  name-addr     =   [display-name] angle-addr
             *
             *  angle-addr    =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
             *
             *  display-name  =   phrase
             *
             *  mailbox-list  =   (mailbox *("," mailbox)) / obs-mbox-list
             */

            MIME_Reader r = new MIME_Reader(MIME_Utils.UnfoldHeader(name_value.Length == 2 ? name_value[1].TrimStart() : ""));

            Mail_h_MailboxList retVal = new Mail_h_MailboxList(name_value[0], new Mail_t_MailboxList());

            while (true)
            {
                string word = r.QuotedReadToDelimiter(new[] { ',', '<', ':' });
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    break;
                }
                // name-addr
                else if (r.Peek(true) == '<')
                {
                    retVal.m_pAddresses.Add(
                        new Mail_t_Mailbox(
                            word != null
                                ? MIME_Encoding_EncodedWord.DecodeAll(word)
                                : null,
                            r.ReadParenthesized()));
                }
                // addr-spec
                else
                {
                    retVal.m_pAddresses.Add(new Mail_t_Mailbox(null, word));
                }

                // We have more addresses.
                if (r.Peek(true) == ',')
                {
                    r.Char(false);
                }
            }

            retVal.m_ParseValue = value;
            retVal.m_pAddresses.AcceptChanges();

            return(retVal);
        }
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Content-Type: text/plain'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_MailboxList Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new[] {':'}, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            /* RFC 5322 3.4.
                mailbox       =   name-addr / addr-spec

                name-addr     =   [display-name] angle-addr

                angle-addr    =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr

                display-name  =   phrase

                mailbox-list  =   (mailbox *("," mailbox)) / obs-mbox-list
            */

            MIME_Reader r = new MIME_Reader(MIME_Utils.UnfoldHeader(name_value.Length == 2 ? name_value[1].TrimStart() : ""));

            Mail_h_MailboxList retVal = new Mail_h_MailboxList(name_value[0], new Mail_t_MailboxList());

            while (true)
            {
                string word = r.QuotedReadToDelimiter(new[] {',', '<', ':'});
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    break;
                }
                    // name-addr
                else if (r.Peek(true) == '<')
                {
                    retVal.m_pAddresses.Add(
                        new Mail_t_Mailbox(
                            word != null
                                ? MIME_Encoding_EncodedWord.DecodeAll(word)
                                : null,
                            r.ReadParenthesized()));
                }
                    // addr-spec
                else
                {
                    retVal.m_pAddresses.Add(new Mail_t_Mailbox(null, word));
                }

                // We have more addresses.
                if (r.Peek(true) == ',')
                {
                    r.Char(false);
                }
            }

            retVal.m_ParseValue = value;
            retVal.m_pAddresses.AcceptChanges();

            return retVal;
        }
示例#6
0
        /// <summary>
        /// Parses <b>address-list</b> from specified string value.
        /// </summary>
        /// <param name="value">The <b>address-list</b> string value.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when <b>value</b> is not valid <b>address-list</b> value.</exception>
        public static Mail_t_AddressList Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            /* RFC 5322 3.4.
             *  address         =   mailbox / group
             *  mailbox         =   name-addr / addr-spec
             *  name-addr       =   [display-name] angle-addr
             *  angle-addr      =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
             *  group           =   display-name ":" [group-list] ";" [CFWS]
             *  display-name    =   phrase
             *  mailbox-list    =   (mailbox *("," mailbox)) / obs-mbox-list
             *  address-list    =   (address *("," address)) / obs-addr-list
             *  group-list      =   mailbox-list / CFWS / obs-group-list
             */

            MIME_Reader        r      = new MIME_Reader(value);
            Mail_t_AddressList retVal = new Mail_t_AddressList();

            while (true)
            {
                string word = r.QuotedReadToDelimiter(new char[] { ',', '<', ':' });
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    break;
                }
                // group
                else if (r.Peek(true) == ':')
                {
                    Mail_t_Group group = new Mail_t_Group(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word)) : null);
                    // Consume ':'
                    r.Char(true);

                    while (true)
                    {
                        word = r.QuotedReadToDelimiter(new char[] { ',', '<', ':', ';' });
                        // We processed all data.
                        if ((word == null && r.Available == 0) || r.Peek(false) == ';')
                        {
                            break;
                        }
                        // In valid address list value.
                        else if (word == string.Empty)
                        {
                            throw new ParseException("Invalid address-list value '" + value + "'.");
                        }
                        // name-addr
                        else if (r.Peek(true) == '<')
                        {
                            group.Members.Add(new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word)) : null, r.ReadParenthesized()));
                        }
                        // addr-spec
                        else
                        {
                            group.Members.Add(new Mail_t_Mailbox(null, word));
                        }

                        // We reached at the end of group.
                        if (r.Peek(true) == ';')
                        {
                            r.Char(true);
                            break;
                        }
                        // We have more addresses.
                        if (r.Peek(true) == ',')
                        {
                            r.Char(false);
                        }
                    }

                    retVal.Add(group);
                }
                // name-addr
                else if (r.Peek(true) == '<')
                {
                    retVal.Add(new Mail_t_Mailbox(word != null ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word.Trim())) : null, r.ReadParenthesized()));
                }
                // addr-spec
                else
                {
                    retVal.Add(new Mail_t_Mailbox(null, word));
                }

                // We have more addresses.
                if (r.Peek(true) == ',')
                {
                    r.Char(false);
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Sender: [email protected]'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_Received Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new char[] { ':' }, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            Mail_h_Received retVal = new Mail_h_Received("a", "b", DateTime.MinValue);

            MIME_Reader r = new MIME_Reader(name_value[1]);

            while (true)
            {
                string word = r.Word();
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    break;
                }
                // We have comment, just eat it.
                else if (r.StartsWith("("))
                {
                    r.ReadParenthesized();
                }
                // We have date-time or unknown-data.
                else if (r.StartsWith(";"))
                {
                    // Eat ';'
                    r.Char(false);

                    try{
                        retVal.m_Time = MIME_Utils.ParseRfc2822DateTime(r.QuotedReadToDelimiter(new char[] { ';' }));
                    }
                    catch {
                        // We hane some unknown data, skip it.
                    }
                }
                else
                {
                    // We have some unexpected char like: .,= ... . Just eat it.
                    if (word == null)
                    {
                        r.Char(true);
                        continue;
                    }

                    word = word.ToUpperInvariant();

                    if (word == "FROM")
                    {
                        retVal.m_From = r.DotAtom();

                        r.ToFirstChar();
                        if (r.StartsWith("("))
                        {
                            string[] parts = r.ReadParenthesized().Split(' ');
                            if (parts.Length == 1)
                            {
                                if (Net_Utils.IsIPAddress(parts[0]))
                                {
                                    retVal.m_pFrom_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[0]), null);
                                }
                            }
                            else if (parts.Length == 2)
                            {
                                if (Net_Utils.IsIPAddress(parts[1]))
                                {
                                    retVal.m_pFrom_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[1]), parts[0]);
                                }
                            }
                        }
                    }
                    else if (word == "BY")
                    {
                        retVal.m_By = r.DotAtom();

                        r.ToFirstChar();
                        if (r.StartsWith("("))
                        {
                            string[] parts = r.ReadParenthesized().Split(' ');
                            if (parts.Length == 1)
                            {
                                if (Net_Utils.IsIPAddress(parts[0]))
                                {
                                    retVal.m_pBy_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[0]), null);
                                }
                            }
                            else if (parts.Length == 2)
                            {
                                if (Net_Utils.IsIPAddress(parts[1]))
                                {
                                    retVal.m_pBy_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[1]), parts[0]);
                                }
                            }
                        }
                    }
                    else if (word == "VIA")
                    {
                        retVal.m_Via = r.Word();
                    }
                    else if (word == "WITH")
                    {
                        retVal.m_With = r.Word();
                    }
                    else if (word == "ID")
                    {
                        // msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]

                        if (r.StartsWith("<"))
                        {
                            retVal.m_ID = r.ReadParenthesized();
                        }
                        else
                        {
                            retVal.m_ID = r.Atom();
                        }
                    }
                    else if (word == "FOR")
                    {
                        r.ToFirstChar();

                        // path / angle-address
                        if (r.StartsWith("<"))
                        {
                            retVal.m_For = r.ReadParenthesized();
                        }
                        else
                        {
                            string mailbox = Mail_Utils.SMTP_Mailbox(r);
                            if (mailbox == null)
                            {
                                throw new ParseException("Invalid Received: For parameter value '" + r.ToEnd() + "'.");
                            }
                            retVal.m_For = mailbox;
                        }
                    }
                    // Unknown, just eat value.
                    else
                    {
                        r.Word();
                    }
                }
            }

            retVal.m_ParseValue = value;

            return(retVal);
        }
        public static Mail_t_AddressList ParseAddressList(string value)
        {
            MIME_Reader r = new MIME_Reader(value);

            /* RFC 5322 3.4.
                address         =   mailbox / group

                mailbox         =   name-addr / addr-spec

                name-addr       =   [display-name] angle-addr

                angle-addr      =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr

                group           =   display-name ":" [group-list] ";" [CFWS]

                display-name    =   phrase

                mailbox-list    =   (mailbox *("," mailbox)) / obs-mbox-list

                address-list    =   (address *("," address)) / obs-addr-list

                group-list      =   mailbox-list / CFWS / obs-group-list
            */

            Mail_t_AddressList retVal = new Mail_t_AddressList();

            while (true)
            {
                string word = r.QuotedReadToDelimiter(new[] { ',', '<', ':' });
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    if (retVal.Count == 0)
                    {
                        if (CheckEmail(value))
                        {
                            retVal.Add(new Mail_t_Mailbox(null, value));
                        }
                    }
                    
                    break;
                }
                // skip old group address format
                else if (r.Peek(true) == ':')
                {
                    // Consume ':'
                    r.Char(true);
                }
                // name-addr
                else if (r.Peek(true) == '<')
                {
                    string address = r.ReadParenthesized();

                    if (CheckEmail(address))
                    {
                        retVal.Add(
                            new Mail_t_Mailbox(
                                word != null
                                    ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word))
                                    : null,
                                address));
                    }
                }
                // addr-spec
                else
                {
                    if (CheckEmail(word))
                    {
                        retVal.Add(new Mail_t_Mailbox(null, word));
                    }
                }

                // We have more addresses.
                if (r.Peek(true) == ',')
                {
                    r.Char(false);
                }
            }

            return retVal;
        }
示例#9
0
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Sender: [email protected]'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_Mailbox Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new[] {':'}, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            MIME_Reader r = new MIME_Reader(name_value[1]);

            string word = r.QuotedReadToDelimiter(new[] {',', '<', ':'});
            // Invalid value.
            if (word == null)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }
                // name-addr
            else if (r.Peek(true) == '<')
            {
                Mail_h_Mailbox h = new Mail_h_Mailbox(name_value[0],
                                                      new Mail_t_Mailbox(
                                                          word != null
                                                              ? MIME_Encoding_EncodedWord.DecodeS(
                                                                    TextUtils.UnQuoteString(word))
                                                              : null,
                                                          r.ReadParenthesized()));
                h.m_ParseValue = value;

                return h;
            }
                // addr-spec
            else
            {
                Mail_h_Mailbox h = new Mail_h_Mailbox(name_value[0], new Mail_t_Mailbox(null, word));
                h.m_ParseValue = value;

                return h;
            }
        }
示例#10
0
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Sender: [email protected]'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_Received Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new[] {':'}, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            Mail_h_Received retVal = new Mail_h_Received("a", "b", DateTime.MinValue);

            MIME_Reader r = new MIME_Reader(name_value[1]);

            while (true)
            {
                string word = r.Word();
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    break;
                }
                    // We have comment, just eat it.
                else if (r.StartsWith("("))
                {
                    r.ReadParenthesized();
                }
                    // We have date-time.
                else if (r.StartsWith(";"))
                {
                    // Eat ';'
                    r.Char(false);

                    retVal.m_Time = MIME_Utils.ParseRfc2822DateTime(r.ToEnd());
                }
                else
                {
                    // We have some unexpected char like: .,= ... . Just eat it.
                    if (word == null)
                    {
                        r.Char(true);
                        continue;
                    }

                    word = word.ToUpperInvariant();

                    if (word == "FROM")
                    {
                        retVal.m_From = r.DotAtom();

                        r.ToFirstChar();
                        if (r.StartsWith("("))
                        {
                            string[] parts = r.ReadParenthesized().Split(' ');
                            if (parts.Length == 1)
                            {
                                if (Net_Utils.IsIPAddress(parts[0]))
                                {
                                    retVal.m_pFrom_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[0]),
                                                                                null);
                                }
                            }
                            else if (parts.Length == 2)
                            {
                                if (Net_Utils.IsIPAddress(parts[1]))
                                {
                                    retVal.m_pFrom_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[1]),
                                                                                parts[0]);
                                }
                            }
                        }
                    }
                    else if (word == "BY")
                    {
                        retVal.m_By = r.DotAtom();

                        r.ToFirstChar();
                        if (r.StartsWith("("))
                        {
                            string[] parts = r.ReadParenthesized().Split(' ');
                            if (parts.Length == 1)
                            {
                                if (Net_Utils.IsIPAddress(parts[0]))
                                {
                                    retVal.m_pBy_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[0]), null);
                                }
                            }
                            else if (parts.Length == 2)
                            {
                                if (Net_Utils.IsIPAddress(parts[1]))
                                {
                                    retVal.m_pBy_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(parts[1]),
                                                                              parts[0]);
                                }
                            }
                        }
                    }
                    else if (word == "VIA")
                    {
                        retVal.m_Via = r.Word();
                    }
                    else if (word == "WITH")
                    {
                        retVal.m_With = r.Word();
                    }
                    else if (word == "ID")
                    {
                        // msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]

                        if (r.StartsWith("<"))
                        {
                            retVal.m_ID = r.ReadParenthesized();
                        }
                        else
                        {
                            retVal.m_ID = r.Atom();
                        }
                    }
                    else if (word == "FOR")
                    {
                        r.ToFirstChar();

                        // path / angle-address
                        if (r.StartsWith("<"))
                        {
                            retVal.m_For = r.ReadParenthesized();
                        }
                        else
                        {
                            string mailbox = Mail_Utils.SMTP_Mailbox(r);
                            if (mailbox == null)
                            {
                                throw new ParseException("Invalid Received: For parameter value '" + r.ToEnd() +
                                                         "'.");
                            }
                            retVal.m_For = mailbox;
                        }
                    }
                        // Unknown, just eat value.
                    else
                    {
                        r.Word();
                    }
                }
            }

            retVal.m_ParseValue = value;

            return retVal;
        }
示例#11
0
        public static Mail_t_AddressList ParseAddressList(string value)
        {
            MIME_Reader r = new MIME_Reader(value);

            /* RFC 5322 3.4.
             *  address         =   mailbox / group
             *
             *  mailbox         =   name-addr / addr-spec
             *
             *  name-addr       =   [display-name] angle-addr
             *
             *  angle-addr      =   [CFWS] "<" addr-spec ">" [CFWS] / obs-angle-addr
             *
             *  group           =   display-name ":" [group-list] ";" [CFWS]
             *
             *  display-name    =   phrase
             *
             *  mailbox-list    =   (mailbox *("," mailbox)) / obs-mbox-list
             *
             *  address-list    =   (address *("," address)) / obs-addr-list
             *
             *  group-list      =   mailbox-list / CFWS / obs-group-list
             */

            Mail_t_AddressList retVal = new Mail_t_AddressList();

            while (true)
            {
                string word = r.QuotedReadToDelimiter(new[] { ',', '<', ':' });
                // We processed all data.
                if (word == null && r.Available == 0)
                {
                    if (retVal.Count == 0)
                    {
                        if (CheckEmail(value))
                        {
                            retVal.Add(new Mail_t_Mailbox(null, value));
                        }
                    }

                    break;
                }
                // skip old group address format
                else if (r.Peek(true) == ':')
                {
                    // Consume ':'
                    r.Char(true);
                }
                // name-addr
                else if (r.Peek(true) == '<')
                {
                    string address = r.ReadParenthesized();

                    if (CheckEmail(address))
                    {
                        retVal.Add(
                            new Mail_t_Mailbox(
                                word != null
                                    ? MIME_Encoding_EncodedWord.DecodeS(TextUtils.UnQuoteString(word))
                                    : null,
                                address));
                    }
                }
                // addr-spec
                else
                {
                    if (CheckEmail(word))
                    {
                        retVal.Add(new Mail_t_Mailbox(null, word));
                    }
                }

                // We have more addresses.
                if (r.Peek(true) == ',')
                {
                    r.Char(false);
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Parses header field from the specified value.
        /// </summary>
        /// <param name="value">Header field value. Header field name must be included. For example: 'Return-Path: &lt;[email protected]&gt;'.</param>
        /// <returns>Returns parsed header field.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>value</b> is null reference.</exception>
        /// <exception cref="ParseException">Is raised when header field parsing errors.</exception>
        public static Mail_h_ReturnPath Parse(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            string[] name_value = value.Split(new[] {':'}, 2);
            if (name_value.Length != 2)
            {
                throw new ParseException("Invalid header field value '" + value + "'.");
            }

            Mail_h_ReturnPath retVal = new Mail_h_ReturnPath(null);

            MIME_Reader r = new MIME_Reader(name_value[1]);
            r.ToFirstChar();
            // Return-Path missing <>, some server won't be honor RFC.
            if (!r.StartsWith("<"))
            {
                retVal.m_Address = r.ToEnd();
            }
            else
            {
                retVal.m_Address = r.ReadParenthesized();
            }

            return retVal;
        }