diff --git a/ImapClient.cs b/ImapClient.cs index f92baf4..033317e 100644 --- a/ImapClient.cs +++ b/ImapClient.cs @@ -540,7 +540,7 @@ string GetResponse(bool resolveLiterals = true) { /// The read bytes as an ASCII-encoded string. /// The underlying socket is closed or there was a failure /// reading from the network. - string GetData(int byteCount) { + string GetData(int byteCount, Encoding encoder = null) { byte[] buffer = new byte[4096]; using (var mem = new MemoryStream()) { lock (readLock) { @@ -551,7 +551,9 @@ string GetData(int byteCount) { byteCount = byteCount - read; } } - string s = Encoding.ASCII.GetString(mem.ToArray()); + if (encoder == null) + encoder = Encoding.ASCII; + string s = encoder.GetString(mem.ToArray()); ts.TraceInformation("S -> " + s); return s; } @@ -1148,7 +1150,7 @@ public MailMessage GetMessage(uint uid, ExaminePartDelegate callback, foreach (Bodypart part in parts) { // Let the delegate decide whether the part should be fetched or not. if (callback(part) == true) { - string content = GetBodypart(uid, part.PartNumber, seen, mailbox); + string content = GetBodypart(uid, part, seen, mailbox); message.AddBodypart(part, content); } } @@ -1458,7 +1460,7 @@ string GetBodystructure(uint uid, string mailbox = null) { /// network. /// The method was called in non-authenticated /// state, i.e. before logging in. - string GetBodypart(uint uid, string partNumber, bool seen = true, + string GetBodypart(uint uid, Bodypart part, bool seen = true, string mailbox = null) { AssertValid(); lock (sequenceLock) { @@ -1467,12 +1469,13 @@ string GetBodypart(uint uid, string partNumber, bool seen = true, StringBuilder builder = new StringBuilder(); string tag = GetTag(); string response = SendCommandGetResponse(tag + "UID FETCH " + uid + - " (BODY" + (seen ? null : ".PEEK") + "[" + partNumber + "])", false); + " (BODY" + (seen ? null : ".PEEK") + "[" + part.PartNumber + "])", false); while (response.StartsWith("*")) { Match m = Regex.Match(response, @"\* \d+ FETCH .* {(\d+)}"); if (m.Success) { int size = Convert.ToInt32(m.Groups[1].Value); - builder.Append(GetData(size)); + var bodyEncoder = part.Parameters.ContainsKey("Charset") ? Util.GetEncoding(part.Parameters["Charset"]) : Encoding.ASCII; + builder.Append(GetData(size, bodyEncoder)); response = GetResponse(); if (!Regex.IsMatch(response, @"\)\s*$")) throw new BadServerResponseException(response); diff --git a/MessageBuilder.cs b/MessageBuilder.cs index 31e367f..5df1cce 100644 --- a/MessageBuilder.cs +++ b/MessageBuilder.cs @@ -3,6 +3,7 @@ using System.Collections.Specialized; using System.IO; using System.Net.Mail; +using System.Net.Mime; using System.Text; using System.Text.RegularExpressions; @@ -340,7 +341,7 @@ internal static void AddBodypart(this MailMessage message, Bodypart part, string bytes = Util.Base64Decode(content); break; default: - bytes = Encoding.ASCII.GetBytes(content); + bytes = encoding.GetBytes(content); break; } } catch { @@ -374,7 +375,7 @@ internal static void AddBodypart(this MailMessage message, Bodypart part, string preferAlternative == false && hasName)) message.Attachments.Add(CreateAttachment(part, bytes)); else - message.AlternateViews.Add(CreateAlternateView(part, bytes)); + message.AlternateViews.Add(CreateAlternateView(part, bytes, encoding)); } /// @@ -416,7 +417,7 @@ static Attachment CreateAttachment(Bodypart part, byte[] bytes) { /// The MIME body part to create the alternate view from. /// An array of bytes composing the content of the alternate view. /// An initialized instance of the AlternateView class. - static AlternateView CreateAlternateView(Bodypart part, byte[] bytes) { + static AlternateView CreateAlternateView(Bodypart part, byte[] bytes, Encoding altViewContentEncoding) { MemoryStream stream = new MemoryStream(bytes); System.Net.Mime.ContentType contentType; try { @@ -425,6 +426,7 @@ static AlternateView CreateAlternateView(Bodypart part, byte[] bytes) { } catch { contentType = new System.Net.Mime.ContentType(); } + contentType.CharSet = altViewContentEncoding.BodyName; AlternateView view = new AlternateView(stream, contentType); try { view.ContentId = ParseMessageId(part.Id);