/// <summary>
        /// Parses IMAP date time from string.
        /// </summary>
        /// <param name="date">DateTime string.</param>
        /// <returns>Returns parsed date-time value.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>date</b> is null reference.</exception>
        public static DateTime ParseDate(string date)
        {
            if (date == null)
            {
                throw new ArgumentNullException("date");
            }

            return(MIME_Utils.ParseRfc2822DateTime(date));
        }
        /// <summary>
        /// Parses IMAP FETCH ENVELOPE from reader.
        /// </summary>
        /// <param name="r">Fetch reader.</param>
        /// <returns>Returns parsed envelope.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>r</b> is null reference.</exception>
        public static IMAP_t_Fetch_r_i_Envelope Parse(StringReader r)
        {
            if (r == null)
            {
                throw new ArgumentNullException("r");
            }

            /* RFC 3501 7.4.2. FETCH Response.
             *  ENVELOPE
             *   A parenthesized list that describes the envelope structure of a
             *   message.  This is computed by the server by parsing the
             *   [RFC-2822] header into the component parts, defaulting various
             *   fields as necessary.
             *
             *   The fields of the envelope structure are in the following
             *   order: date, subject, from, sender, reply-to, to, cc, bcc,
             *   in-reply-to, and message-id.  The date, subject, in-reply-to,
             *   and message-id fields are strings.  The from, sender, reply-to,
             *   to, cc, and bcc fields are parenthesized lists of address
             *   structures.
             *
             *   An address structure is a parenthesized list that describes an
             *   electronic mail address.  The fields of an address structure
             *   are in the following order: personal name, [SMTP]
             *   at-domain-list (source route), mailbox name, and host name.
             *
             *   [RFC-2822] group syntax is indicated by a special form of
             *   address structure in which the host name field is NIL.  If the
             *   mailbox name field is also NIL, this is an end of group marker
             *   (semi-colon in RFC 822 syntax).  If the mailbox name field is
             *   non-NIL, this is a start of group marker, and the mailbox name
             *   field holds the group name phrase.
             *
             *   If the Date, Subject, In-Reply-To, and Message-ID header lines
             *   are absent in the [RFC-2822] header, the corresponding member
             *   of the envelope is NIL; if these header lines are present but
             *   empty the corresponding member of the envelope is the empty
             *   string.
             *
             *      Note: some servers may return a NIL envelope member in the
             *      "present but empty" case.  Clients SHOULD treat NIL and
             *      empty string as identical.
             *
             *      Note: [RFC-2822] requires that all messages have a valid
             *      Date header.  Therefore, the date member in the envelope can
             *      not be NIL or the empty string.
             *
             *      Note: [RFC-2822] requires that the In-Reply-To and
             *      Message-ID headers, if present, have non-empty content.
             *      Therefore, the in-reply-to and message-id members in the
             *      envelope can not be the empty string.
             *
             *   If the From, To, cc, and bcc header lines are absent in the
             *   [RFC-2822] header, or are present but empty, the corresponding
             *   member of the envelope is NIL.
             *
             *   If the Sender or Reply-To lines are absent in the [RFC-2822]
             *   header, or are present but empty, the server sets the
             *   corresponding member of the envelope to be the same value as
             *   the from member (the client is not expected to know to do
             *   this).
             *
             *      Note: [RFC-2822] requires that all messages have a valid
             *      From header.  Therefore, the from, sender, and reply-to
             *      members in the envelope can not be NIL.
             */

            // Read "date".
            DateTime date  = DateTime.MinValue;
            string   dateS = r.ReadWord();

            if (!string.IsNullOrEmpty(dateS) && !dateS.Equals("NIL", Helpers.GetDefaultIgnoreCaseComparison()))
            {
                date = MIME_Utils.ParseRfc2822DateTime(dateS);
            }

            // Read "subject".
            string subject = ReadAndDecodeWord(r);

            // Read "from"
            Mail_t_Address[] from = ReadAddresses(r);

            //Read "sender"
            Mail_t_Address[] sender = ReadAddresses(r);

            // Read "reply-to"
            Mail_t_Address[] replyTo = ReadAddresses(r);

            // Read "to"
            Mail_t_Address[] to = ReadAddresses(r);

            // Read "cc"
            Mail_t_Address[] cc = ReadAddresses(r);

            // Read "bcc"
            Mail_t_Address[] bcc = ReadAddresses(r);

            // Read "in-reply-to"
            string inReplyTo = r.ReadWord();

            // Read "message-id"
            string messageID = r.ReadWord();

            return(new IMAP_t_Fetch_r_i_Envelope(date, subject, from, sender, replyTo, to, cc, bcc, inReplyTo, messageID));
        }
        /// <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);
        }