예제 #1
0
        public void TestEncodedWordLithuanian()
        {
            const string input = "=?ISO-8859-13?Q?Fwd=3A_Dvira=E8iai_vasar=E0_vagiami_da=FEniau=2C_bet_draust?=";

            string result = EncodedWord.Decode(input);

            Assert.AreEqual("Fwd: Dviračiai vasarą vagiami dažniau, bet draust", result);
        }
예제 #2
0
        public void TestEncodedWordDanish()
        {
            const string subject = "=?iso-8859-1?Q?SV:_Ticket(13349550)_-_Sp=F8rgsm=E5l_omkring_CBB_privat?=";

            string result = EncodedWord.Decode(subject);

            Assert.AreEqual("SV: Ticket(13349550) - Spørgsmål omkring CBB privat", result);
        }
예제 #3
0
        public void TestOnlyWhiteSpaceBetweenEncodingsAreIgnored()
        {
            const string input = "(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=) (=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)";

            string result = EncodedWord.Decode(input);

            Assert.AreEqual("(ab) (ab)", result);
        }
예제 #4
0
        public void TestWhiteSpaceBetweenEncodingsAreIgnoredWithMultipleParts2()
        {
            const string input = "(=?UTF-8?Q?a?= =?UTF-8?Q?b?= =?UTF-8?Q?c?= =?UTF-8?Q?a?= =?UTF-8?Q?b?= =?UTF-8?Q?c?=)";

            string result = EncodedWord.Decode(input);

            Assert.AreEqual("(abcabc)", result);
        }
예제 #5
0
 /// <summary>
 /// This will decode a single value of the form: %3D%3DIamHere
 /// Which is basically a <see cref="EncodedWord"/> form just using % instead of =
 /// </summary>
 /// <param name="valueToDecode">The value to decode</param>
 /// <param name="encoding">The encoding used to decode with</param>
 /// <returns>The decoded value that corresponds to <paramref name="valueToDecode"/></returns>
 private static String DecodeSingleValueEx(String valueToDecode, String encoding)
 {
     // The encoding used is the same as QuotedPrintable, we only
     // need to change % to =
     // And otherwise make it look like the correct EncodedWord encoding
     valueToDecode = "=?" + encoding + "?Q?" + valueToDecode.Replace("%", "=") + "?=";
     return(EncodedWord.Decode(valueToDecode));
 }
예제 #6
0
        /// <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);

            foreach (KeyValuePair <string, string> keyValuePair in parameters)
            {
                string key   = keyValuePair.Key.Trim();
                string value = keyValuePair.Value.Trim();
                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.
                    contentType.MediaType = value;
                    break;

                case "boundary":
                    contentType.Boundary = StringHelper.RemoveQuotesIfAny(value);
                    break;

                case "charset":
                    string toInsert = StringHelper.RemoveQuotesIfAny(value);
                    contentType.CharSet = toInsert;
                    break;

                case "name":
                    contentType.Name = EncodedWord.Decode(StringHelper.RemoveQuotesIfAny(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);
        }
예제 #7
0
        public void TestEncodedWordOnSubjectWithSpaces()
        {
            const string subject =
                "=?iso-8859-1?Q?Re: Yahoo! Mail (comment acc=E9der, restaurer, etc)?=";

            string result = EncodedWord.Decode(subject);

            Assert.AreEqual("Re: Yahoo! Mail (comment accéder, restaurer, etc)", result);
        }
예제 #8
0
        public void TestEncodedWordOnNonEncodedString()
        {
            const string notEncodedString =
                "test that this is not touched ?! ?=..?= =?...?=";

            string result = EncodedWord.Decode(notEncodedString);

            Assert.AreEqual(notEncodedString, result);
        }
예제 #9
0
        /// <summary>
        /// Parses an email address from a MIME header<br/>
        /// <br/>
        /// Examples of input:
        /// <c>Eksperten mailrobot &lt;[email protected]&gt;</c><br/>
        /// <c>"Eksperten mailrobot" &lt;[email protected]&gt;</c><br/>
        /// <c>&lt;[email protected]&gt;</c><br/>
        /// <c>[email protected]</c><br/>
        /// <br/>
        /// It might also contain encoded text, which will then be decoded.
        /// </summary>
        /// <param name="input">The value to parse out and email and/or a username</param>
        /// <returns>A <see cref="RfcMailAddress"/></returns>
        /// <exception cref="ArgumentNullException">If <paramref name="input"/> is <see langword="null"/></exception>
        /// <remarks>
        /// <see href="http://tools.ietf.org/html/rfc5322#section-3.4">RFC 5322 section 3.4</see> for more details on email syntax.<br/>
        /// <see cref="EncodedWord.Decode">For more information about encoded text</see>.
        /// </remarks>
        internal static RfcMailAddress ParseMailAddress(string input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            // Decode the value, if it was encoded
            input = EncodedWord.Decode(input.Trim());

            // Find the location of the email address
            var indexStartEmail = input.LastIndexOf('<');
            var indexEndEmail   = input.LastIndexOf('>');

            try
            {
                if (indexStartEmail >= 0 && indexEndEmail >= 0)
                {
                    // Check if there is a username in front of the email address
                    var username = indexStartEmail > 0 ? input.Substring(0, indexStartEmail).Trim() : string.Empty;

                    // Parse out the email address without the "<"  and ">"
                    indexStartEmail = indexStartEmail + 1;
                    var emailLength  = indexEndEmail - indexStartEmail;
                    var emailAddress = input.Substring(indexStartEmail, emailLength).Trim();

                    // There has been cases where there was no emailaddress between the < and >
                    if (!string.IsNullOrEmpty(emailAddress))
                    {
                        // If the username is quoted, MailAddress' constructor will remove them for us
                        return(new RfcMailAddress(new MailAddress(emailAddress, username), input));
                    }
                }

                // This might be on the form [email protected]
                // Check if there is an email, if notm there is no need to try
                if (input.Contains("@"))
                {
                    return(new RfcMailAddress(new MailAddress(input), input));
                }
            }
            catch (FormatException)
            {
                // Sometimes invalid emails are sent, like [email protected]. (last period is illigal)
                // Ignore the error
            }

            // It could be that the format used was simply a name
            // which is indeed valid according to the RFC
            // Example:
            // Eksperten mailrobot
            return(new RfcMailAddress(input));
        }
예제 #10
0
        private void CreateEncodeWord()
        {
            EncodedWord = Word;
            List <char> goodLetters = GoodGuesses.Select(g => g.Letter).ToList();

            foreach (char c in Word.Distinct())
            {
                if (!goodLetters.Contains(c))
                {
                    EncodedWord = EncodedWord.Replace(c, '_');
                }
            }
        }
예제 #11
0
        /// <summary>
        /// This will decode a single value of the form: %3D%3DIamHere
        /// Which is basically a <see cref="EncodedWord"/> form just using % instead of =
        /// </summary>
        /// <param name="valueToDecode">The value to decode</param>
        /// <param name="encoding">The encoding used to decode with</param>
        /// <returns>The decoded value that corresponds to <paramref name="valueToDecode"/></returns>
        /// <exception cref="ArgumentNullException">If <paramref name="valueToDecode"/> is <see langword="null"/></exception>
        /// <exception cref="ArgumentNullException">If <paramref name="encoding"/> is <see langword="null"/></exception>
        private static string DecodeSingleValue(string valueToDecode, string encoding)
        {
            if (valueToDecode == null)
            {
                throw new ArgumentNullException("valueToDecode");
            }

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

            // The encoding used is the same as QuotedPrintable, we only
            // need to change % to =
            // And otherwise make it look like the correct EncodedWord encoding
            valueToDecode = "=?" + encoding + "?Q?" + valueToDecode.Replace("%", "=") + "?=";
            return(EncodedWord.Decode(valueToDecode));
        }
예제 #12
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(StringUtility.RemoveQuotesIfAny(keyword.Trim()));
                }
                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;
            }
        }
예제 #13
0
        /// <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(nameof(headerValue));
            }

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

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

            // Now decode the parameters
            var parameters = Rfc2231Decoder.Decode(headerValue);

            foreach (var keyValuePair in parameters)
            {
                var key   = keyValuePair.Key.ToUpperInvariant().Trim();
                var value = Utility.RemoveQuotesIfAny(keyValuePair.Value.Trim());
                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
                    var creationDate = new DateTime(Rfc2822DateTime.StringToDate(value).Ticks);
                    contentDisposition.CreationDate = creationDate;
                    break;

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

                case "READ-DATE":
                    var 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
                case "VOICE":
                    break;

                default:
                    if (!key.StartsWith("X-"))
                    {
                        throw new ArgumentException(
                                  "Unknown parameter in Content-Disposition. Ask developer to fix! Parameter: " + key);
                    }
                    contentDisposition.Parameters.Add(key, value);
                    break;
                }
            }

            return(contentDisposition);
        }
예제 #14
0
        /// <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(nameof(headerValue));
            }

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

            // Now decode the parameters
            var parameters = Rfc2231Decoder.Decode(headerValue);

            foreach (var keyValuePair in parameters)
            {
                var key   = keyValuePair.Key.ToUpperInvariant().Trim();
                var value = Utility.RemoveQuotesIfAny(keyValuePair.Value.Trim());
                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.

                    // Check for illegal content-type
                    var v = value.ToUpperInvariant().Trim('\0');
                    if (v.Equals("TEXT") || v.Equals("TEXT/"))
                    {
                        value = "text/plain";
                    }

                    contentType.MediaType = value;
                    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);
        }
예제 #15
0
        /// <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);
        }
예제 #16
0
        /// <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.Trim();
                string value = keyValuePair.Value;
                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;

                case "filename":
                    // The filename might be in qoutes, and it might be encoded-word encoded
                    contentDisposition.FileName = EncodedWord.Decode(StringHelper.RemoveQuotesIfAny(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.Replace("\"", "")).Ticks);
                    contentDisposition.CreationDate = creationDate;
                    break;

                case "modification-date":
                    DateTime midificationDate = new DateTime(Rfc2822DateTime.StringToDate(value.Replace("\"", "")).Ticks);
                    contentDisposition.ModificationDate = midificationDate;
                    break;

                case "read-date":
                    DateTime readDate = new DateTime(Rfc2822DateTime.StringToDate(value.Replace("\"", "")).Ticks);
                    contentDisposition.ReadDate = readDate;
                    break;

                case "size":
                    contentDisposition.Size = int.Parse(value, CultureInfo.InvariantCulture);
                    break;

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

            return(contentDisposition);
        }
예제 #17
0
        /// <summary>
        /// Parses an email address from a MIME header<br/>
        /// <br/>
        /// Examples of input:
        /// <c>Eksperten mailrobot &lt;[email protected]&gt;</c><br/>
        /// <c>"Eksperten mailrobot" &lt;[email protected]&gt;</c><br/>
        /// <c>&lt;[email protected]&gt;</c><br/>
        /// <c>[email protected]</c><br/>
        /// <br/>
        /// It might also contain encoded text, which will then be decoded.
        /// </summary>
        /// <param name="input">The value to parse out and email and/or a username</param>
        /// <returns>A <see cref="MailAddress"/></returns>
        /// <exception cref="ArgumentNullException">If <paramref name="input"/> is <see langword="null"/></exception>
        /// <remarks>
        /// <see href="http://tools.ietf.org/html/rfc5322#section-3.4">RFC 5322 section 3.4</see> for more details on email syntax.<br/>
        /// <see cref="EncodedWord.Decode">For more information about encoded text</see>.
        /// </remarks>
        internal static MailAddress ParseMailAddress(string input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            // Decode the value, if it was encoded
            input = EncodedWord.Decode(input.Trim());

            // Find the location of the email address
            int indexStartEmail = input.LastIndexOf('<');
            int indexEndEmail   = input.LastIndexOf('>');
            int indexAtEmail    = input.LastIndexOf('@');
            //Display Name
            string displayName = "", address = "";

            //Find it
            if (indexStartEmail == -1 || indexEndEmail == -1)
            {
                if (indexAtEmail != -1)
                {
                    displayName = input.Substring(0, indexAtEmail);
                    address     = input;
                }
            }
            else
            {
                // Check if there is a username in front of the email address
                if (indexStartEmail > 0)
                {
                    // Parse out the user
                    displayName = input.Substring(0, indexStartEmail).Trim();
                    displayName = displayName.Trim('"');
                }
                else
                {
                    // There was no user
                    displayName = string.Empty;
                }

                // Parse out the email address without the "<"  and ">"
                indexStartEmail = indexStartEmail + 1;
                int emailLength = indexEndEmail - indexStartEmail;
                address = input.Substring(indexStartEmail, emailLength).Trim();
            }
            //Regex mailRegex = new Regex(@"^\w+@\w+(\.\w+)+(\,\w+@\w+(\.\w+)+)*$");
            //严格验证
            //mailRegex.IsMatch(address)
            //宽松验证
            if (!address.Contains("@"))
            {
                throw new FormatException(string.Format("无效的 Mail 地址格式:{0}", address));
            }

            MailAddress mailAddress = new MailAddress(displayName, address);

            // It could be that the format used was simply a name
            // which is indeed valid according to the RFC
            // Example:
            // Eksperten mailrobot
            return(mailAddress);
        }
예제 #18
0
        /// <summary>
        /// Parses an email address from a MIME header<br/>
        /// <br/>
        /// Examples of input:
        /// <c>Eksperten mailrobot &lt;[email protected]&gt;</c><br/>
        /// <c>"Eksperten mailrobot" &lt;[email protected]&gt;</c><br/>
        /// <c>&lt;[email protected]&gt;</c><br/>
        /// <c>[email protected]</c><br/>
        /// <br/>
        /// It might also contain encoded text, which will then be decoded.
        /// </summary>
        /// <param name="input">The value to parse out and email and/or a username</param>
        /// <returns>A <see cref="RfcMailAddress"/></returns>
        /// <exception cref="ArgumentNullException">If <paramref name="input"/> is <see langword="null"/></exception>
        /// <remarks>
        /// <see href="http://tools.ietf.org/html/rfc5322#section-3.4">RFC 5322 section 3.4</see> for more details on email syntax.<br/>
        /// <see cref="EncodedWord.Decode">For more information about encoded text</see>.
        /// </remarks>
        internal static RfcMailAddress ParseMailAddress(string input)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }

            // Decode the value, if it was encoded
            input = EncodedWord.Decode(input.Trim());

            //Remove any redundant sets of angle brackets around the email address
            int lastOpenAngleBracketIdx  = input.LastIndexOf('<');
            int lastCloseAngleBracketIdx = input.LastIndexOf('>');

            //Find the index of the first angle bracket in this series of angle brackets, e.g "a>b" <<*****@*****.**>> wouldn't find the angle bracket in the display name
            int firstOpenAngleBracketIdx  = lastOpenAngleBracketIdx;
            int firstCloseAngleBracketIdx = lastCloseAngleBracketIdx;

            while (firstOpenAngleBracketIdx > 0 && //There is a character before the last open angle bracket
                   input[firstOpenAngleBracketIdx - 1] == '<' &&
                   //The character before the last open angle bracket is another open angle bracket
                   input[firstCloseAngleBracketIdx - 1] == '>')
            //The character before the last close angle bracket is another close angle bracket
            {
                //Update the first angle bracket indices
                firstOpenAngleBracketIdx--;
                firstCloseAngleBracketIdx--;
            }

            //If the email address in the input string is enclosed in multiple angle brackets
            if (firstOpenAngleBracketIdx != lastOpenAngleBracketIdx)
            {
                //Remove the multiple angle brackets surrounding the email address from the input string leaving just a single set
                input = input.Substring(0, firstOpenAngleBracketIdx) +
                        //Part before any angle brackets (display name if there is one)
                        input.Substring(lastOpenAngleBracketIdx, firstCloseAngleBracketIdx - lastOpenAngleBracketIdx + 1);
                //actual email address, including one angle bracket either side
            }

            // Find the location of the email address
            int indexStartEmail = input.LastIndexOf('<');
            int indexEndEmail   = input.LastIndexOf('>');

            try {
                if (indexStartEmail >= 0 && indexEndEmail >= 0)
                {
                    string username;
                    // Check if there is a username in front of the email address
                    if (indexStartEmail > 0)
                    {
                        // Parse out the user
                        username = input.Substring(0, indexStartEmail).Trim();
                    }
                    else
                    {
                        // There was no user
                        username = string.Empty;
                    }

                    // Parse out the email address without the "<"  and ">"
                    indexStartEmail = indexStartEmail + 1;
                    int    emailLength  = indexEndEmail - indexStartEmail;
                    string emailAddress = input.Substring(indexStartEmail, emailLength).Trim();

                    // There has been cases where there was no emailaddress between the < and >
                    if (!string.IsNullOrEmpty(emailAddress))
                    {
                        // If the username is quoted, MailAddress' constructor will remove them for us
                        return(new RfcMailAddress(new MailAddress(emailAddress, username), input));
                    }
                }

                // This might be on the form [email protected]
                // Check if there is an email, if notm there is no need to try
                if (input.Contains("@"))
                {
                    return(new RfcMailAddress(new MailAddress(input), input));
                }
            }
            catch (FormatException) {
                // Sometimes invalid emails are sent, like [email protected]. (last period is illigal)
                //DefaultLogger.Log.LogError("RfcMailAddress: Improper mail address: \"" + input + "\"");
            }

            // It could be that the format used was simply a name
            // which is indeed valid according to the RFC
            // Example:
            // Eksperten mailrobot
            return(new RfcMailAddress(input));
        }