Gmail API 返回的 text/plain 内容编码存在差异

Discrepancy in text/plain content encoding returned by Gmail API

我正在尝试使用 GMail API 阅读 multipart/mixed 封电子邮件。
目标是将 multipart/mixed 电子邮件的每个 text/plain 部分(可以有很多,采用不同的编码)正确解码为 C# 字符串(即 UTF-16):

public static string DecodeTextPart(Google.Apis.Gmail.v1.Data.MessagePart part)
{
    var content_type_header = part.Headers.FirstOrDefault(h => string.Equals(h.Name, "content-type", StringComparison.OrdinalIgnoreCase));

    if (content_type_header == null)
        throw new ArgumentException("No content-type header found in the email part");

    var content_type = new System.Net.Mime.ContentType(content_type_header.Value);

    if (!string.Equals(content_type.MediaType, "text/plain", StringComparison.OrdinalIgnoreCase))
        throw new ArgumentException("The part is not text/plain");

    return Encoding.GetEncoding(content_type.CharSet).GetString(GetAttachmentBytes(part.Body));
}

GetAttachmentBytes returns 原始附件字节,未经转换,从 GMail 使用的 base64url encoding 解码。

我发现在很多情况下这会产生无效的字符串,因为我为附件内容获取的原始字节似乎总是采用 UTF-8,即使同一部分的 content-type 声明否则。

例如鉴于电子邮件:

Date: ...
From: ...
Reply-To: ...
Message-ID: ...
To: ...
Subject: Test 1 text file
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="----------0E50FC0802A2FCCAA"

------------0E50FC0802A2FCCAA
Content-Type: text/plain; charset=windows-1251
Content-Transfer-Encoding: 8bit


Content test: Cyrillic, Windows-1251 (à, ÿ, æ)
------------0E50FC0802A2FCCAA
Content-Type: TEXT/PLAIN;
 name="Irrelevant.txt"
Content-transfer-encoding: base64
Content-Disposition: attachment;
 filename="Irrelevant.txt"

VGhpcyBmaWxlIGRvZXMgbm90IGNvbnRhaW4gdXNlZnVsIGluZm9ybWF0aW9u
------------0E50FC0802A2FCCAA--

,我成功找到了第一部分,上面的代码在 System.Net.Mime.ContentType 的帮助下计算出它是 charset=windows-1251,然后是 .GetString() returns 垃圾,因为实际GetAttachmentBytes 返回的原始字节对应于 UTF-8 编码,而不是 Windows-1251.

完全一样
Subject: Test 2 text file
MIME-Version: 1.0
Content-Type: multipart/mixed;
 boundary="----------0B716C1D8123D8710"

------------0B716C1D8123D8710
Content-Type: text/plain; charset=koi8-r
Content-Transfer-Encoding: 8bit


Content test: Cyrillic, koi-8 (Б, С, Ц)
------------0B716C1D8123D8710
Content-Type: TEXT/PLAIN;
 name="Irrelevant.txt"
Content-transfer-encoding: base64
Content-Disposition: attachment;
 filename="Irrelevant.txt"

VGhpcyBmaWxlIGRvZXMgbm90IGNvbnRhaW4gdXNlZnVsIGluZm9ybWF0aW9u
------------0B716C1D8123D8710--

请注意,编码名称后括号中的三个测试字母在两封电子邮件中是相同的,在 Unicode 中看起来像 (а, я, ж),但(正确地)在上面引用的电子邮件正文表示中看起来是错误的不同的编码。

如果我 "fix" 始终使用 Encoding.UTF8 而不是 GetEncoding(content_type.CharSet) 的函数,那么它似乎在我到目前为止所做的测试中有效。

同时,GMail 界面在这两种情况下都能正确显示字母,因此它必须使用正确声明的编码正确解析传入的电子邮件。

GMail API 是否将所有文本块重新编码为 UTF-8(包装在 base64url 中),但为它们报告原始 charset
因此,我是否应该始终在 GMail API 中使用 UTF-8 而忽略 content-typecharset=
还是我的代码有问题?

根据这两个资源:

该值确实是 转换为 UTF-8 部分的 base-64 编码表示。

据我所知,Google 并未对此进行记录。