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






Ну, вы разбираете заголовок электронного письма в словарь. И затем вы проверяете, установлено ли 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.
Значение заголовка сообщает вам следующее:
=?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
Этот ответ основан на авторской документации?
Замечательно, спасибо за четкий ответ Томалак! Сложно решить, кто получит правильный ответ между вами и bobince, вы дали четкое представление о природе кодирования. Но я попробую использовать файл email.header.decode_header, он просто сделал это за меня! Но я все равно тебя повысил!
Please note both
Content-Transfer-Encodinghave 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 ценить это
На что жалуется и когда? ОС, вероятно, расстроится, если вы попытаетесь сохранить файл с этим именем, конечно, но каждый раз, когда вы берете имя файла из пользовательского ввода, вам потребуется очень строгая фильтрация, чтобы не допустить опасные символы - лучше всего разрешить только [a -zA-Z0-9_] (и также поймать пустую строку).
И я был бы удивлен, если бы Outlook создал это, оно очень искажено даже по стандартам Microsoft! :-)
+1 за реализацию на Python и всю дополнительную информацию. Ваше здоровье!
Также мне действительно нужно знать, какой это тип файла, например .xls или .doc, поэтому мне нужно декодировать имя файла, чтобы правильно обработать вложение, но, как указано выше, кажется, что gb2312 не поддерживается в jython, знаете какие-либо обходные пути?
Я решил, что этого было достаточно: name = u ''. Join ([b вместо b, e в email.Header.decode_header (name)]) с таким именем файла ¸ ± ± ¾hen¸ ± ± ¾g.xls по крайней мере I есть доп! спасибо за помощь!
это был внешний вид, вот заголовок «X-Mailer: Microsoft Office Outlook 11»
Ах да, у Jython до сих пор нет CJKCodecs (встроенных в CPython с версии 2.4). Возможно, вы сможете получить доступ к ГБ через java.nio.charset.Charset - JRE не всегда устанавливает восточноазиатские кодеки, но JDK должен.
головная боль bobince, но спасибо за совет! конечным пользователям не нужно видеть имя файла, и все, что нужно, - это .ext
Однако несправедливо винить 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; <...> слишком долго для комментариев
Есть способ лучше, чем метод Бобинса, для обработки вывода 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.
правильно, я спрашиваю после имени файла, а не содержимого, у меня никогда не было проблем с этим, даже если в нем есть китайские символы. как это все base64