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

            // We create an empty Content-Type which we will fill in when we see the values
            ContentType contentType = new ContentType();

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

            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 MediaType - it has no key since it is the first one mentioned in the
                    // headerValue and has no = in it.

                    if (!setMediaType)
                    {
                        // Check for illegal content-type
                        string v = value.ToUpperInvariant();
                        if (v.Equals("TEXT") || v.Equals("TEXT/"))
                        {
                            value = "text/plain";
                        }

                        contentType.MediaType = cleanMediaType(value);

                        //Have now set the media type, ignore any later entries without a key (see #21)
                        setMediaType = true;
                    }
                    else
                    {
                        //DefaultLogger.Log.LogDebug("Multiple values without a key in the Content Type header. Only the first will get used as the media type");
                    }

                    break;

                case "BOUNDARY":
                    contentType.Boundary = value;
                    break;

                case "CHARSET":
                    contentType.CharSet = value;
                    break;

                case "NAME":
                    contentType.Name = EncodedWord.Decode(value);
                    break;

                default:
                    // This is to shut up the code help that is saying that contentType.Parameters
                    // can be null - which it cant!
                    if (contentType.Parameters == null)
                    {
                        throw new Exception(
                                  "The ContentType parameters property is null. This will never be thrown.");
                    }

                    // We add the unknown value to our parameters list
                    // "Known" unknown values are:
                    // - title
                    // - report-type
                    contentType.Parameters.Add(key, value);
                    break;
                }
            }

            return(contentType);
        }
        /// <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);
        }