MimeKit 字符 Encoding/Decoding 问题
MimeKit Character Encoding/Decoding Issue
在使用 MimeKit
将 .eml
文件转换为 .msg
文件时,我 运行 遇到了一个似乎与编码有关的问题。
使用包含以下内容的 EML 文件,例如:
--__NEXTPART_20160610_5EF5CF91_471687D
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
添付ファイル名テスト
结果是正文内容中的垃圾:
・Y・t・t・@・C・・・シ・e・X・g
此外,当读取 EML 文件时,base-64 编码的 ü
字符显示为 ??
。我已经下载了最新版本的 MimeKit,但似乎没有什么不同。
.eml 文件可以在 Outlook 2016 中正确打开,但使用 MimeKit 似乎无法正确读取和解码文件。
你上面的 MIME 片段有一些问题:(
Content-Transfer-Encoding: 7bit
显然不是真的,虽然这不太可能是问题所在(MimeKit 正是因为这个原因忽略了 7bit
和 8bit
的值)。
然而,最重要的是,字符集参数是 iso-2022-jp
但内容本身很明显不是 iso-2022-jp
(看起来像 utf-8
)。
当您获得 TextPart.Text
值时,MimeKit 通过使用 Content-Type
header 中指定的字符集转换原始流内容来获取该字符串。如果那是错误的,那么 Text
属性 也会有错误的值。
好消息是 TextPart
有 GetText 方法允许您指定字符集覆盖。
我建议尝试:
var text = part.GetText (Encoding.UTF8);
看看是否可行。
FWIW,iso-2022-jp
是一种将日语字符强制转换为 7 位 ascii 形式的编码,看起来完全是乱码。这就是你的日语文本在 iso-2022-jp
:
中的样子
BE:IU%U%!%$%kL>%F%9%H
这就是我知道它不是 iso-2022-jp
:)
更新:
最终,解决方案可能是这样的:
var encodings = new List<Encoding> ();
string text = null;
try {
var encoding = Encoding.GetEncoding (part.ContentType.Charset,
new EncoderExceptionFallback (),
new DecoderExceptionFallback ());
encodings.Add (encoding);
} catch (ArgumentException) {
} catch (NotSupportedException) {
}
// add utf-8 as our first fallback
encodings.Add (Encoding.GetEncoding (65001,
new EncoderExceptionFallback (),
new DecoderExceptionFallback ()));
// add iso-8859-1 as our final fallback
encodings.Add (Encoding.GetEncoding (28591,
new EncoderExceptionFallback (),
new DecoderExceptionFallback ()));
for (int i = 0; i < encodings.Count; i++) {
try {
text = part.GetText (encodings[i]);
break;
} catch (DecoderFallbackException) {
// this means that the content did not convert cleanly
}
}
在使用 MimeKit
将 .eml
文件转换为 .msg
文件时,我 运行 遇到了一个似乎与编码有关的问题。
使用包含以下内容的 EML 文件,例如:
--__NEXTPART_20160610_5EF5CF91_471687D
Content-Type: text/plain; charset=iso-2022-jp
Content-Transfer-Encoding: 7bit
添付ファイル名テスト
结果是正文内容中的垃圾:
・Y・t・t・@・C・・・シ・e・X・g
此外,当读取 EML 文件时,base-64 编码的 ü
字符显示为 ??
。我已经下载了最新版本的 MimeKit,但似乎没有什么不同。
.eml 文件可以在 Outlook 2016 中正确打开,但使用 MimeKit 似乎无法正确读取和解码文件。
你上面的 MIME 片段有一些问题:(
Content-Transfer-Encoding: 7bit
显然不是真的,虽然这不太可能是问题所在(MimeKit 正是因为这个原因忽略了 7bit
和 8bit
的值)。
然而,最重要的是,字符集参数是 iso-2022-jp
但内容本身很明显不是 iso-2022-jp
(看起来像 utf-8
)。
当您获得 TextPart.Text
值时,MimeKit 通过使用 Content-Type
header 中指定的字符集转换原始流内容来获取该字符串。如果那是错误的,那么 Text
属性 也会有错误的值。
好消息是 TextPart
有 GetText 方法允许您指定字符集覆盖。
我建议尝试:
var text = part.GetText (Encoding.UTF8);
看看是否可行。
FWIW,iso-2022-jp
是一种将日语字符强制转换为 7 位 ascii 形式的编码,看起来完全是乱码。这就是你的日语文本在 iso-2022-jp
:
BE:IU%U%!%$%kL>%F%9%H
这就是我知道它不是 iso-2022-jp
:)
更新:
最终,解决方案可能是这样的:
var encodings = new List<Encoding> ();
string text = null;
try {
var encoding = Encoding.GetEncoding (part.ContentType.Charset,
new EncoderExceptionFallback (),
new DecoderExceptionFallback ());
encodings.Add (encoding);
} catch (ArgumentException) {
} catch (NotSupportedException) {
}
// add utf-8 as our first fallback
encodings.Add (Encoding.GetEncoding (65001,
new EncoderExceptionFallback (),
new DecoderExceptionFallback ()));
// add iso-8859-1 as our final fallback
encodings.Add (Encoding.GetEncoding (28591,
new EncoderExceptionFallback (),
new DecoderExceptionFallback ()));
for (int i = 0; i < encodings.Count; i++) {
try {
text = part.GetText (encodings[i]);
break;
} catch (DecoderFallbackException) {
// this means that the content did not convert cleanly
}
}