示例#1
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 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){
                                string ip = parts[1].Trim();
                                if (ip.StartsWith("["))
                                    ip = ip.Substring(1);
                                if (ip.EndsWith("]"))
                                    ip = ip.Substring(0, ip.Length - 1);
                                if(Net_Utils.IsIPAddress(ip)){
                                    retVal.m_pFrom_TcpInfo = new Mail_t_TcpInfo(IPAddress.Parse(ip),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;
        }
示例#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: '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 char[]{':'},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].Trim());
            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;
        }
        /// <summary>
        /// Parses parameters from the specified reader.
        /// </summary>
        /// <param name="reader">MIME reader.</param>
        /// <exception cref="ArgumentNullException">Is raised when <b>reader</b> is null reference.</exception>
        public void Parse(MIME_Reader reader)
        {
            if(reader == null){
                throw new ArgumentNullException("reader");
            }

            /* RFC 2231.
                Asterisks ("*") are reused to provide the indicator that language and
                character set information is present and encoding is being used. A
                single quote ("'") is used to delimit the character set and language
                information at the beginning of the parameter value. Percent signs
                ("%") are used as the encoding flag, which agrees with RFC 2047.

                Character set and language information may be combined with the
                parameter continuation mechanism. For example:

                Content-Type: application/x-stuff
                    title*0*=us-ascii'en'This%20is%20even%20more%20
                    title*1*=%2A%2A%2Afun%2A%2A%2A%20
                    title*2="isn't it!"

                Note that:

                (1) Language and character set information only appear at
                    the beginning of a given parameter value.

                (2) Continuations do not provide a facility for using more
                    than one character set or language in the same
                    parameter value.

                (3) A value presented using multiple continuations may
                    contain a mixture of encoded and unencoded segments.

                (4) The first segment of a continuation MUST be encoded if
                    language and character set information are given.

                (5) If the first segment of a continued parameter value is
                    encoded the language and character set field delimiters
                    MUST be present even when the fields are left blank.
            */

            KeyValueCollection<string,_ParameterBuilder> parameters = new KeyValueCollection<string,_ParameterBuilder>();

            // Parse all parameter parts.
            string[] parameterParts = TextUtils.SplitQuotedString(reader.ToEnd(),';');
            foreach(string part in parameterParts){
                if(string.IsNullOrEmpty(part)){
                    continue;
                }

                string[] name_value = part.Trim().Split(new char[]{'='},2);
                string   paramName  = name_value[0].Trim();
                string   paramValue = null;
                if(name_value.Length == 2){
                    paramValue = TextUtils.UnQuoteString(name_value[1].Trim());
                }
                // Valueless parameter.
                //else{

                string[] nameParts = paramName.Split('*');
                int      index     = 0;
                bool     encoded   = nameParts.Length == 3;
                // Get multi value parameter index.
                if(nameParts.Length >= 2){
                    try{
                        index = Convert.ToInt32(nameParts[1]);
                    }
                    catch{
                    }
                }

                // Single value parameter and we already have parameter with such name, skip it.
                if(nameParts.Length < 2 && parameters.ContainsKey(nameParts[0])){
                    continue;
                }

                // Parameter builder doesn't exist for the specified parameter, create it.
                if(!parameters.ContainsKey(nameParts[0])){
                    parameters.Add(nameParts[0],new _ParameterBuilder(nameParts[0]));
                }

                parameters[nameParts[0]].AddPart(index,encoded,paramValue);
            }

            // Build parameters from parts.
            foreach(_ParameterBuilder b in parameters){
                m_pParameters.Add(b.Name,b.GetParamter());
            }

            m_IsModified = false;
        }