как узнать, является ли строка base64 или нет - PullRequest
6 голосов
/ 07 ноября 2008

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

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

Т.е..

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

------=_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==?="  

Обратите внимание, что оба " Content-Transfer-Encoding " имеют base64

Ответы [ 6 ]

21 голосов
/ 07 ноября 2008

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

=?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, вы сталкиваетесь с строкой в ​​кодировке base-64 в позиции 3. После того, как вы ее декодировали, обязательно обратите внимание на кодировку в позиции 1, возможно Лучше всего конвертировать все это в UTF-8, используя эту информацию.

12 голосов
/ 07 ноября 2008

Обратите внимание, что оба Content-Transfer-Encoding имеют base64

Не имеет значения в этом случае, 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 прямо отрицает это:

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

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

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

7 голосов
/ 07 ноября 2008

@ gnud, @edg - Если я не понимаю, он спрашивает о имени файла, а не о содержимом файла @setori - Content-Trasfer-Encoding сообщает вам, как кодируется содержимое файла, а не «имя файла».

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

=? Gb2312? B

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

В RFC написано:

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

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

2 голосов
/ 06 ноября 2009

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

name = unicode(email.header.make_header(email.header.decode_header(x)))
0 голосов
/ 02 июня 2010

Вопрос: "" "Также мне действительно нужно знать, какой это тип файла, т.е. .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 - 2 китайских символа, которые вместе означают «копировать», а остальные являются буквальными символами ASCII.

0 голосов
/ 07 ноября 2008

Ну, вы разбираете заголовок письма в словарь. И затем вы проверяете, установлено ли Content-Transfer-Encoding и имеет ли оно значение "base64" или "base-64".

...