Расхождение в кодировке текста / простого содержимого, возвращаемого API Gmail - PullRequest
1 голос
/ 09 января 2020

Я экспериментирую с чтением multipart/mixed писем с помощью GMail API.
Цель состоит в том, чтобы правильно декодировать каждую text/plain часть письма multipart/mixed (их может быть много в разных кодировках) в C# string (то есть 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 возвращает необработанные байты вложения без преобразования, декодированные из кодировки base64url , которую использует GMail.

Я обнаружил, что во многих случаях это приводит к неправильным строкам, потому что необработанные байты, которые я получаю для содержимого вложения, по-видимому, всегда находятся в 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--

, я успешно нахожу первую часть, код выше показывает, что она charset=windows-1251 с помощью System.Net.Mime.ContentType, а затем .GetString() возвращает мусор, потому что фактический необработанные байты, возвращаемые 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--

Обратите внимание, что три круглые буквы в скобках после кодировки NAM Они одинаковы в обоих письмах, и в Unicode выглядят как (а, я, ж), но (правильно) выглядят неправильно в представлении тела письма, приведенном выше, из-за различных кодировок.

Если я "исправлю" функцию, чтобы всегда используйте Encoding.UTF8 вместо GetEncoding(content_type.CharSet), тогда он работает в тестах, которые я до сих пор проводил.

В то же время интерфейс GMail правильно отображает буквы в обоих случаях, поэтому должен правильно проанализировать входящие электронные письма, используя правильные объявленные кодировки.

Это тот случай, когда API GMail перекодирует все текстовые блоки в UTF-8 (обернутый в base64url), но сообщает исходный charset для них?
Поэтому я должен всегда использовать UTF-8 с GMail API и игнорировать content-type charset=?
Или есть проблема с моим кодом?

1 Ответ

2 голосов
/ 09 января 2020

Согласно этим двум ресурсам:

Значение действительно представляет собой кодированное в base-64 представление детали , преобразованное в UTF-8 .

Однако, насколько я могу найти, это не задокументировано Google.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...