예제 #1
0
        /// <summary>
        /// Parses a Received header value.
        /// </summary>
        /// <param name="headerValue">The value for the header to be parsed</param>
        /// <exception cref="ArgumentNullException"><exception cref="ArgumentNullException">If <paramref name="headerValue"/> is <see langword="null"/></exception></exception>
        public Received(string headerValue)
        {
            if (headerValue == null)
            {
                throw new ArgumentNullException("headerValue");
            }

            // Remember the raw input if someone whishes to use it
            Raw = headerValue;

            // Default Date value
            Date = DateTime.MinValue;

            // The date part is the last part of the string, and is preceeded by a semicolon
            // Some emails forgets to specify the date, therefore we need to check if it is there
            if (headerValue.Contains(";"))
            {
                string datePart = headerValue.Substring(headerValue.LastIndexOf(";") + 1);
                Date = Rfc2822DateTime.StringToDate(datePart);
            }

            Names = ParseDictionary(headerValue);
        }
        /// <summary>
        /// Parses a the value for the header Content-Disposition to a <see cref="ContentDisposition"/> object.
        /// </summary>
        /// <param name="headerValue">The value to be parsed</param>
        /// <returns>A <see cref="ContentDisposition"/> object</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="headerValue"/> is <see langword="null"/></exception>
        public static ContentDisposition ParseContentDisposition(string headerValue)
        {
            if (headerValue == null)
            {
                throw new ArgumentNullException("headerValue");
            }

            // See http://www.ietf.org/rfc/rfc2183.txt for RFC definition

            // Create empty ContentDisposition - we will fill in details as we read them
            ContentDisposition contentDisposition = new ContentDisposition();

            // Now decode the parameters
            List <KeyValuePair <string, string> > parameters = Rfc2231Decoder.Decode(headerValue);

            foreach (KeyValuePair <string, string> keyValuePair in parameters)
            {
                string key   = keyValuePair.Key.ToUpperInvariant().Trim();
                string value = keyValuePair.Value.Trim().RemoveQuotesIfAny();
                switch (key)
                {
                case "":
                    // This is the DispisitionType - it has no key since it is the first one
                    // and has no = in it.
                    contentDisposition.DispositionType = value;
                    break;

                // The correct name of the parameter is filename, but some emails also contains the parameter
                // name, which also holds the name of the file. Therefore we use both names for the same field.
                case "NAME":
                case "FILENAME":
                    // The filename might be in qoutes, and it might be encoded-word encoded
                    contentDisposition.FileName = EncodedWord.Decode(value);
                    break;

                case "CREATION-DATE":
                    // Notice that we need to create a new DateTime because of a failure in .NET 2.0.
                    // The failure is: you cannot give contentDisposition a DateTime with a Kind of UTC
                    // It will set the CreationDate correctly, but when trying to read it out it will throw an exception.
                    // It is the same with ModificationDate and ReadDate.
                    // This is fixed in 4.0 - maybe in 3.0 too.
                    // Therefore we create a new DateTime which have a DateTimeKind set to unspecified
                    DateTime creationDate = new DateTime(Rfc2822DateTime.StringToDate(value).Ticks);
                    contentDisposition.CreationDate = creationDate;
                    break;

                case "MODIFICATION-DATE":
                    DateTime midificationDate = new DateTime(Rfc2822DateTime.StringToDate(value).Ticks);
                    contentDisposition.ModificationDate = midificationDate;
                    break;

                case "READ-DATE":
                    DateTime readDate = new DateTime(Rfc2822DateTime.StringToDate(value).Ticks);
                    contentDisposition.ReadDate = readDate;
                    break;

                case "SIZE":
                    contentDisposition.Size = SizeParser.Parse(value);
                    break;

                case "CHARSET":     // ignoring invalid parameter in Content-Disposition
                    break;

                default:
                    if (key.StartsWith("X-"))
                    {
                        contentDisposition.Parameters.Add(key, value);
                        break;
                    }

                    throw new ArgumentException(
                              "Unknown parameter in Content-Disposition. Ask developer to fix! Parameter: " + key);
                }
            }

            return(contentDisposition);
        }
예제 #3
0
        /// <summary>
        /// Parses a single header and sets member variables according to it.
        /// </summary>
        /// <param name="headerName">The name of the header</param>
        /// <param name="headerValue">The value of the header in unfolded state (only one line)</param>
        /// <exception cref="ArgumentNullException">If <paramref name="headerName"/> or <paramref name="headerValue"/> is <see langword="null"/></exception>
        private void ParseHeader(string headerName, string headerValue)
        {
            if (headerName == null)
            {
                throw new ArgumentNullException("headerName");
            }

            if (headerValue == null)
            {
                throw new ArgumentNullException("headerValue");
            }

            switch (headerName.ToUpperInvariant())
            {
            // See http://tools.ietf.org/html/rfc5322#section-3.6.3
            case "TO":
                To = RfcMailAddress.ParseMailAddresses(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.3
            case "CC":
                Cc = RfcMailAddress.ParseMailAddresses(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.3
            case "BCC":
                Bcc = RfcMailAddress.ParseMailAddresses(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.2
            case "FROM":
                // There is only one MailAddress in the from field
                From = RfcMailAddress.ParseMailAddress(headerValue);
                break;

            // http://tools.ietf.org/html/rfc5322#section-3.6.2
            // The implementation here might be wrong
            case "REPLY-TO":
                // This field may actually be a list of addresses, but no
                // such case has been encountered
                ReplyTo = RfcMailAddress.ParseMailAddress(headerValue);
                break;

            // http://tools.ietf.org/html/rfc5322#section-3.6.2
            case "SENDER":
                Sender = RfcMailAddress.ParseMailAddress(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.5
            // RFC 5322:
            // The "Keywords:" field contains a comma-separated list of one or more
            // words or quoted-strings.
            // The field are intended to have only human-readable content
            // with information about the message
            case "KEYWORDS":
                string[] keywordsTemp = headerValue.Split(',');
                foreach (string keyword in keywordsTemp)
                {
                    // Remove the quotes if there is any
                    Keywords.Add(keyword.Trim().RemoveQuotesIfAny());
                }
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.7
            case "RECEIVED":
                // Simply add the value to the list
                Received.Add(new Received(headerValue.Trim()));
                break;

            case "IMPORTANCE":
                Importance = HeaderFieldParser.ParseImportance(headerValue.Trim());
                break;

            // See http://tools.ietf.org/html/rfc3798#section-2.1
            case "DISPOSITION-NOTIFICATION-TO":
                DispositionNotificationTo = RfcMailAddress.ParseMailAddresses(headerValue);
                break;

            case "MIME-VERSION":
                MimeVersion = headerValue.Trim();
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.5
            case "SUBJECT":
                Subject = EncodedWord.Decode(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.7
            case "RETURN-PATH":
                // Return-paths does not include a username, but we
                // may still use the address parser
                ReturnPath = RfcMailAddress.ParseMailAddress(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.4
            // Example Message-ID
            // <*****@*****.**>
            case "MESSAGE-ID":
                MessageId = HeaderFieldParser.ParseId(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.4
            case "IN-REPLY-TO":
                InReplyTo = HeaderFieldParser.ParseMultipleIDs(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.4
            case "REFERENCES":
                References = HeaderFieldParser.ParseMultipleIDs(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc5322#section-3.6.1))
            case "DATE":
                Date     = headerValue.Trim();
                DateSent = Rfc2822DateTime.StringToDate(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc2045#section-6
            // See ContentTransferEncoding class for more details
            case "CONTENT-TRANSFER-ENCODING":
                ContentTransferEncoding = HeaderFieldParser.ParseContentTransferEncoding(headerValue.Trim());
                break;

            // See http://tools.ietf.org/html/rfc2045#section-8
            case "CONTENT-DESCRIPTION":
                // Human description of for example a file. Can be encoded
                ContentDescription = EncodedWord.Decode(headerValue.Trim());
                break;

            // See http://tools.ietf.org/html/rfc2045#section-5.1
            // Example: Content-type: text/plain; charset="us-ascii"
            case "CONTENT-TYPE":
                ContentType = HeaderFieldParser.ParseContentType(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc2183
            case "CONTENT-DISPOSITION":
                ContentDisposition = HeaderFieldParser.ParseContentDisposition(headerValue);
                break;

            // See http://tools.ietf.org/html/rfc2045#section-7
            // Example: <foo4*[email protected]>
            case "CONTENT-ID":
                ContentId = HeaderFieldParser.ParseId(headerValue);
                break;

            default:
                // This is an unknown header

                // Custom headers are allowed. That means headers
                // that are not mentionen in the RFC.
                // Such headers start with the letter "X"
                // We do not have any special parsing of such

                // Add it to unknown headers
                UnknownHeaders.Add(headerName, headerValue);
                break;
            }
        }