使用 MimeKit/MailKit 进行内容编码

Posted

技术标签:

【中文标题】使用 MimeKit/MailKit 进行内容编码【英文标题】:Content encoding using MimeKit/MailKit 【发布时间】:2015-07-23 13:10:51 【问题描述】:

我们遇到了一些编码问题,特别是在使用 8bit 作为内容传输编码时。 首先,谁能告诉我a-umlaut的8bit编码值是什么样的?

处理编码的最佳实践是什么?

我尝试使用 MIME 实体的WriteTo() 方法将内容写入流中,该方法适用于除 8 位编码之外的任何情况。

更新: 目前正在使用 MimeKit 示例之一中发布的代码:

using (MemoryStream memStm = new MemoryStream())

    mime.WriteTo(memStm);
    message.MimeMessage = Encoding.UTF8.GetString(memStm.ToArray());

但是当我的 MIME 包含特殊字符时,它似乎是某种双重编码,例如: ㄧㄧ 将导致类似: ¿½

我怎样才能摆脱那些双重编码的情况?

【问题讨论】:

为什么要将二进制数据转换成字符串? MimeMessage.WriteTo() 输出的内容不应该被转换为任何可能的用例的字符串。 MimeMessage 可以在整个消息数据中包含多个字符集的文本,因此使用单个字符集编码进行转换无法可靠地工作。 我需要他 Mime 作为字符串。 message.MimeMessage 只是一个字符串属性。以前我使用过 mime.ToString()(mime 是 MailKit API 的 typeof MimeMessage,很抱歉造成混淆),但 tostring 与 æøå 等丹麦字符存在问题,这就是我使用 WriteTo() 的原因。所以基本上,我有一个 MailKit.MimeMessage 类型,我想要一个字符串,我可以将它发送到我的客户端并在我的 IE 中表示为 .mht 文件。 您不能为此使用字符串,您需要使用 byte[] 来代替。 MIME 是一个复合文档,其中每个部分都可以有自己的字符集。无法使用单个字符集转换器将具有多个字符集的复合文档转换为字符串。 因此,如果我想通过使用带有 XML 文档作为数据类型的 HTTP 请求将我的 mime 消息传输到客户端,那么 mime 元素部分必须是字节数组而不是我当前的字符串类型? 正确,您必须为此使用字节数组。 【参考方案1】:

8 位 MIME 传输编码基本上是“无编码”,因此任何用 8 位编码编码的 MIME 数据都与给定字符集中数据的二进制表示相同。例如,'ä' 在 UTF-8 中表示为以下字节序列:0xC30xA4。使用 8 位时,您的 MIME 数据将是完全相同的字节序列。 quoted-printablebase64 等其他传输编码将以不同方式对这些字节进行编码,例如如w6Q==C3=A4

要点是 MIME 字符集 指定如何以二进制形式表示字符,MIME 内容传输编码 指定这些字节如何在 MIME 文档本身中进行编码.

至于最佳实践,现代电子邮件服务器和客户端将乐于处理 8 位编码的电子邮件。不过,习惯是使用quoted-printablebase64

至于双编码问题,äÄ 双 UTF-8 编码的序列看起来与¿½ 不同,所以我认为那里还有其他问题。我不熟悉 MimeKit 并且您的代码示例不包含足够的信息,但是如果您使用更完整的重现代码更新您的问题,我将很乐意更新我的答案。

【讨论】:

所以如果我有一个 mime 文件看起来像 Content-Type: text/plain;charset="iso-8859-1";内容传输编码:8bit;如果我查看原始字符串,ä 看起来像 0xC30xA4?? @grmihel:嗯,在这种特殊情况下,它将是一个单字节,0xE4。这是因为iso-8859-1 可以表示ä 字符并将其表示为单个0xE4 字节(参见htmlhelp.com/reference/charset/iso224-255.html,十进制0xE4 == 228)。但是,如果您的标头显示为Content-Type: text/plain;charset="utf-8"; Content-Transfer-Encoding: 8bit,您将得到我在回复中谈到的两个字节。

以上是关于使用 MimeKit/MailKit 进行内容编码的主要内容,如果未能解决你的问题,请参考以下文章

使用 Javascript 检索二进制文件内容,base64 对其进行编码并使用 Python 对其进行反向解码

使用请求包装器RequestWrapper 对博客内容进行编码

使用apache-commons-lang3框架,对html内容进行编码和反编码

如何让 beautifulsoup 对脚本标签的内容进行编码和解码

使用apache-commons-lang3架构对HTML内容进行编码和反编码

使用chardet模块获取文件的编码格式,进而正确的读取文件内容