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

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

Когда я получаю эти письма, я хочу расшифровать имя. но есть и другие имена, которые не base64. Как с помощью языка программирования jython определить, является ли строка 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==? = "  

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
6
0
10 357
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

@gnud, @edg - Если я не неправильно понял, он спрашивает об имени файла, а не о его содержимом. @setori - Content-Trasfer-Encoding сообщает вам, как кодируется СОДЕРЖАНИЕ файла, а не «имя файла».

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

=? gb2312? B?

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

RFC говорит:

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

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

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

Setori 07.11.2008 17:57

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

=?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, используя эту информацию.

красиво, отсчет начиная с 0

Corey Trager 07.11.2008 13:39

Этот ответ основан на авторской документации?

Deestan 07.11.2008 14:55

Замечательно, спасибо за четкий ответ Томалак! Сложно решить, кто получит правильный ответ между вами и bobince, вы дали четкое представление о природе кодирования. Но я попробую использовать файл email.header.decode_header, он просто сделал это за меня! Но я все равно тебя повысил!

Setori 07.11.2008 17:57
Ответ принят как подходящий

Please note both Content-Transfer-Encoding have 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 явно отрицает это:

  • An 'encoded-word' MUST NOT appear within a 'quoted-string'.

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

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

Я пробовал просто вызвать вложение просто с помощью '=? Gb2312? B? ULGxvmhlbrixsb5nLnhscw ==? =', Но, к сожалению, оно просто разваливается и горько жалуется, я понятия не имею, почему, возможно, рассмотрение этой жалобы решит проблему быстрее, спасибо bobince ценить это

Setori 07.11.2008 18:02

На что жалуется и когда? ОС, вероятно, расстроится, если вы попытаетесь сохранить файл с этим именем, конечно, но каждый раз, когда вы берете имя файла из пользовательского ввода, вам потребуется очень строгая фильтрация, чтобы не допустить опасные символы - лучше всего разрешить только [a -zA-Z0-9_] (и также поймать пустую строку).

bobince 07.11.2008 19:46

И я был бы удивлен, если бы Outlook создал это, оно очень искажено даже по стандартам Microsoft! :-)

bobince 07.11.2008 19:49

+1 за реализацию на Python и всю дополнительную информацию. Ваше здоровье!

Tomalak 07.11.2008 21:39

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

Setori 10.11.2008 04:55

Я решил, что этого было достаточно: name = u ''. Join ([b вместо b, e в email.Header.decode_header (name)]) с таким именем файла ¸ ± ± ¾hen¸ ± ± ¾g.xls по крайней мере I есть доп! спасибо за помощь!

Setori 10.11.2008 05:07

это был внешний вид, вот заголовок «X-Mailer: Microsoft Office Outlook 11»

Setori 10.11.2008 09:47

Ах да, у Jython до сих пор нет CJKCodecs (встроенных в CPython с версии 2.4). Возможно, вы сможете получить доступ к ГБ через java.nio.charset.Charset - JRE не всегда устанавливает восточноазиатские кодеки, но JDK должен.

bobince 10.11.2008 16:52

головная боль bobince, но спасибо за совет! конечным пользователям не нужно видеть имя файла, и все, что нужно, - это .ext

Setori 11.11.2008 06:02

Однако несправедливо винить Outlook. Вот что производит Thunderbird (3.0b4): -------------- 000908030900000708050403 Content-Type: application / pdf; name = "2009 09 24 =? ISO-8859-1? Q? Einf = FChrung_der_elektronischen_Signatur _? = =? ISO-8859-1? Q? und_Verschl = FCsselung_von_EDIFACT-Nachrichten‌ = 2Epdf? = " Content-Transfer-Encoding: содержимое base64 - Расположение: навесное; имя файла * 0 * = ISO-8859-1 ''% 32% 30% 30% 39% 20% 30% 39% 20% 32% 34% 20% 45‌% 69% 6E% 66% FC; имя файла * 1 * =% 68% 72% 75% 6E% 67% 20% 64% 65% 72% 20% 65% 6C% 65% 6B% 74% 72‌% 6F% 6E% 69% 73; <...> слишком долго для комментариев

Ringding 06.11.2009 16:01

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

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

Вопрос: "" "Также мне действительно нужно знать, какой это тип файла, например .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.

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