как определить, является ли строка base64 или нет

StackOverflow https://stackoverflow.com/questions/271657

  •  06-07-2019
  •  | 
  •  

Вопрос

Мне приходит много электронных писем из разных источников.у всех них есть вложения, у многих из них названия вложений на китайском языке, поэтому эти имена преобразуются в base64 их почтовыми клиентами.

Когда я получаю эти электронные письма, я хочу расшифровать это имя.но есть и другие имена, которые не являются base64.Как я могу определить, является ли строка base64 или нет, используя джитон язык программирования?

Т.е.

Первое вложение:

------=_NextPart_000_0091_01C940CC.EF5AC860
Content-Type: application/vnd.ms-excel;
 name="Copy of Book1.xls"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="Copy of Book1.xls"

второе вложение:

------=_NextPart_000_0091_01C940CC.EF5AC860
Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="  

Пожалуйста, обратите внимание на оба "Передача контента-Кодирование" есть base64

Это было полезно?

Решение

Обратите внимание на оба Content-Transfer-Encoding есть база64

В данном случае это не имеет значения, т. Content-Transfer-Encoding применяется только к полезной нагрузке тела, а не к заголовкам.

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

Это RFC2047-закодированный атом заголовка.Функция stdlib для ее декодирования: email.header.decode_header.Однако для интерпретации результата этой функции все еще требуется небольшая постобработка:

import email.header
x= '=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?='
try:
    name= u''.join([
        unicode(b, e or 'ascii') for b, e in email.header.decode_header(x)
    ])
except email.Errors.HeaderParseError:
    pass # leave name as it was

Однако...

Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="

Это просто неправильно.Какой почтовик это создал?Кодирование RFC2047 может происходить только в атомах, а строка в кавычках не является атомом.RFC2047 §5 явно отрицает это:

  • «Закодированное слово» НЕ ДОЛЖНО появляться внутри «строки в кавычках».

Принятый способ кодирования заголовков параметров при наличии длинных строк или символов Юникода: RFC2231, а это совершенно новый мешок боли.Но вам следует использовать стандартную библиотеку анализа почты, которая справится с этой задачей за вас.

Таким образом, вы можете обнаружить '=?' в параметрах имени файла, если хотите, и попробуйте декодировать его через RFC2047.Однако, строго говоря, правильно будет поверить почтовику на слово и действительно вызвать файл =?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=!

Другие советы

Значение заголовка сообщает вам об этом:

=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?=

"=?"     introduces an encoded value
"gb2312" denotes the character encoding of the original value
"B"      denotes that B-encoding (equal to Base64) was used (the alternative 
         is "Q", which refers to something close to quoted-printable)
"?"      functions as a separator
"uLG..." is the actual value, encoded using the encoding specified before
"?="     ends the encoded value

Таким образом, разделение на "?" на самом деле дает вам это (обозначение JSON)

["=", "gb2312", "B", "uLGxvmhlbrixsb5nLnhscw==", "="]

В результирующем массиве, если "B" находится в позиции 2, вы столкнетесь со строкой, закодированной на базе 64, в позиции 3.Как только вы его расшифруете, обязательно обратите внимание на кодировку в позиции 1, вероятно, было бы лучше преобразовать все это в UTF-8, используя эту информацию.

@Gnud, @Edg - если я не пойму, он спрашивает об имени файла, а не о содержимовом файле @setori - контент -трейк -кодирование говорит вам, как кодируется содержание файла, а не «имя файла».

Я не эксперт, но эта часть имени файла рассказывает ему о следующих за ним символах:

=?gb2312?B?

Я ищу документацию в RFC...Ах!вот: http://tools.ietf.org/html/rfc2047

RFC говорит:

Обычно «закодированное слово» представляет собой последовательность печатаемых символов ASCII, которая начинается с «=?», заканчивается «?=» и имеет два символа «?» между ними.

Еще стоит обратить внимание на код SharpMimeTools, анализатора MIME (на C#), который я использую в своих отслеживание ошибок приложение, БагТрекер.NET

Существует лучший способ обработки вывода, чем метод bobince. decode_header.Я нашел это здесь: http://mail.python.org/pipermail/email-sig/2007-March/000332.html

name = unicode(email.header.make_header(email.header.decode_header(x)))

Итак, вы анализируете заголовок электронного письма в словаре.А затем вы проверяете, установлено ли Content-Transfer-Encoding, и если оно = «base64» или «base-64».

Вопрос:"""Кроме того, мне действительно нужно знать, какой это тип файла, т.е. .xls или .doc, поэтому мне нужно декодировать имя файла, чтобы правильно обработать вложение, но, как указано выше, кажется, что gb2312 не поддерживается в jython, знайте какие-нибудь обходные пути?"""

Данные:

Content-Type: application/vnd.ms-excel;
 name="=?gb2312?B?uLGxvmhlbrixsb5nLnhscw==?="

Наблюдения:

(1) Первая строка обозначает Microsoft Excel, поэтому .xls выглядит лучше, чем .doc

(2)

>>> import base64
>>> base64.b64decode("uLGxvmhlbrixsb5nLnhscw==")
'\xb8\xb1\xb1\xbehen\xb8\xb1\xb1\xbeg.xls'
>>>

(a) Расширение выглядит .xls -- нет необходимости в gb2312 кодек
(b) Если вам нужно имя файла, безопасное для файловой системы, вы можете использовать вариант base64 «-_» ИЛИ вы можете закодировать его в процентах.
(c) Что бы это ни стоило, имя файла XYhenXYg.xls где X и Y — два китайских символа, которые вместе означают «копию», а остальные — буквальные символы ASCII.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top