From c3029c77312990b27ebe9c8368ce8ddc8e5641af Mon Sep 17 00:00:00 2001 From: cshrper Date: Wed, 16 Mar 2016 19:50:26 +0200 Subject: [PATCH 1/2] Update EncodedWord.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bug occurs when I load Message from ".eml" file, that has been created some other program, and it has the MailAddress encoded in UTF-8, for example: I got decoded value "Лучшему кл��енту " instead of "Лучшему клиенту " you can test old version with headers: X-Sender: =?utf-8?Q?=D0=A3=D0=B2=D0=B0=D0=B6=D0=B0=D0=B5=D0=BC=D1=8B=D0?= =?utf-8?Q?=B9_=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D1=89=D0=B8=D0=BA?= X-Receiver: =?utf-8?Q?=D0=9B=D1=83=D1=87=D1=88=D0=B5=D0=BC=D1=83_=D0=BA?= =?utf-8?Q?=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D1=83?= X-Receiver: =?utf-8?Q?=D0=9B=D1=83=D1=87=D1=88=D0=B5=D0=BC=D1=83_=D0=B4?= =?utf-8?Q?=D1=80=D1=83=D0=B3=D1=83_=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0?= =?utf-8?Q?=B3=D0=BE_=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D0=B0?= MIME-Version: 1.0 From: =?utf-8?Q?=D0=A3=D0=B2=D0=B0=D0=B6=D0=B0=D0=B5=D0=BC=D1=8B=D0=B9?= =?utf-8?Q?_=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D1=89=D0=B8=D0=BA?= To: =?utf-8?Q?=D0=9B=D1=83=D1=87=D1=88=D0=B5=D0=BC=D1=83_=D0=BA=D0=BB=D0?= =?utf-8?Q?=B8=D0=B5=D0=BD=D1=82=D1=83?= , =?utf-8?Q?=D0=9B=D1=83=D1=87=D1=88=D0=B5=D0=BC=D1=83_=D0=B4=D1=80=D1?= =?utf-8?Q?=83=D0=B3=D1=83_=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=B3=D0=BE?= =?utf-8?Q?_=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D0=B0?= --- OpenPop/Mime/Decode/EncodedWord.cs | 116 +++++++++++++++++------------ 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/OpenPop/Mime/Decode/EncodedWord.cs b/OpenPop/Mime/Decode/EncodedWord.cs index c916f39..de36f0e 100644 --- a/OpenPop/Mime/Decode/EncodedWord.cs +++ b/OpenPop/Mime/Decode/EncodedWord.cs @@ -77,56 +77,76 @@ public static string Decode(string encodedWords) encodedWords = Regex.Replace(encodedWords, replaceRegex, "${first}${second}"); encodedWords = Regex.Replace(encodedWords, replaceRegex, "${first}${second}"); - string decodedWords = encodedWords; - MatchCollection matches = Regex.Matches(encodedWords, encodedWordRegex); - foreach (Match match in matches) - { - // If this match was not a success, we should not use it - if (!match.Success) continue; - - string fullMatchValue = match.Value; - - string encodedText = match.Groups["Content"].Value; - string encoding = match.Groups["Encoding"].Value; - string charset = match.Groups["Charset"].Value; - - // Get the encoding which corrosponds to the character set - Encoding charsetEncoding = EncodingFinder.FindEncoding(charset); - - // Store decoded text here when done - string decodedText; - - // Encoding may also be written in lowercase - switch (encoding.ToUpperInvariant()) - { - // RFC: - // The "B" encoding is identical to the "BASE64" - // encoding defined by RFC 2045. - // http://tools.ietf.org/html/rfc2045#section-6.8 - case "B": - decodedText = Base64.Decode(encodedText, charsetEncoding); - break; - - // RFC: - // The "Q" encoding is similar to the "Quoted-Printable" content- - // transfer-encoding defined in RFC 2045. - // There are more details to this. Please check - // http://tools.ietf.org/html/rfc2047#section-4.2 - // - case "Q": - decodedText = QuotedPrintable.DecodeEncodedWord(encodedText, charsetEncoding); - break; - - default: - throw new ArgumentException("The encoding " + encoding + " was not recognized"); - } - - // Repalce our encoded value with our decoded value - decodedWords = decodedWords.Replace(fullMatchValue, decodedText); - } + if (matches.Count > 0) + { + #region decode words + string encoding = null; + string charset = null; + + // Find encoding and charset + foreach (Match match in matches) + { + if (match.Success) + { + encoding = match.Groups["Encoding"].Value; + charset = match.Groups["Charset"].Value; + break; + } + } + if (encoding == null) + throw new ArgumentException("The encoding " + encoding + " was not recognized"); + + // Join all ecncoded text + StringBuilder matchCache = new StringBuilder(); + StringBuilder encodedCache = new StringBuilder(); + foreach (Match match in matches) + { + // If this match was not a success, we should not use it + if (!match.Success) + continue; + + matchCache.Append(match.Value); + encodedCache.Append(match.Groups["Content"].Value); + } + string encodedText = encodedCache.ToString(); + + // Get the encoding which corrosponds to the character set + Encoding charsetEncoding = EncodingFinder.FindEncoding(charset); + + // Store decoded text here when done + string decodedText; + + // Encoding may also be written in lowercase + switch (encoding.ToUpperInvariant()) + { + // RFC: + // The "B" encoding is identical to the "BASE64" + // encoding defined by RFC 2045. + // http://tools.ietf.org/html/rfc2045#section-6.8 + case "B": + decodedText = Base64.Decode(encodedText, charsetEncoding); + break; + + // RFC: + // The "Q" encoding is similar to the "Quoted-Printable" content- + // transfer-encoding defined in RFC 2045. + // There are more details to this. Please check + // http://tools.ietf.org/html/rfc2047#section-4.2 + // + case "Q": + decodedText = QuotedPrintable.DecodeEncodedWord(encodedText, charsetEncoding); + break; + + default: + throw new ArgumentException("The encoding " + encoding + " was not recognized"); + } + + decodedWords = decodedWords.Replace(matchCache.ToString(), decodedText); + #endregion + } return decodedWords; } } -} \ No newline at end of file +} From b981ca4e488ff33f1f7eb980324011df066b17c2 Mon Sep 17 00:00:00 2001 From: cshrper Date: Wed, 16 Mar 2016 19:56:10 +0200 Subject: [PATCH 2/2] Update EncodedWord.cs --- OpenPop/Mime/Decode/EncodedWord.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenPop/Mime/Decode/EncodedWord.cs b/OpenPop/Mime/Decode/EncodedWord.cs index de36f0e..1f747d3 100644 --- a/OpenPop/Mime/Decode/EncodedWord.cs +++ b/OpenPop/Mime/Decode/EncodedWord.cs @@ -77,6 +77,8 @@ public static string Decode(string encodedWords) encodedWords = Regex.Replace(encodedWords, replaceRegex, "${first}${second}"); encodedWords = Regex.Replace(encodedWords, replaceRegex, "${first}${second}"); + string decodedWords = encodedWords; + MatchCollection matches = Regex.Matches(encodedWords, encodedWordRegex); if (matches.Count > 0) {