Как получить расшифровать это имя файла вложения с Python?
Я уже расшифровал много имен файлов вложений электронной почты в моем коде.
Но именно это имя файла нарушает мой код.
Вот минимальный пример:
from email.header import decode_header
encoded_filename='=?UTF-8?B?U2FsZXNJbnZvaWNl?==?UTF-8?B?LVJlcG9ydC5wZGY=?='
decoded_header=decode_header(encoded_filename) # --> [('SalesInvoiceQ1|\x04\xb5I\x95\xc1\xbd\xc9\xd0\xb9\xc1\x91\x98', 'utf-8')]
filename=str(decoded_header[0][0]).decode(decoded_header[0][1])
Исключение:
UnicodeDecodeError: 'utf8' codec can't decode byte 0xb5 in position 16: invalid start byte
Не спрашивайте, как, но Thunderbird может расшифровать это имя файла: SalesInvoice-Report.pdf
Как я могу расшифровать это с помощью Python, как это могут сделать почтовые клиенты?
1 ответ
В этом заголовке есть два раздела Encoded-Word. Вы должны определить, где заканчивается один и начинается один:
>>> print decode_header(encoded_filename[:28])[0]
('SalesInvoice', 'utf-8')
>>> print decode_header(encoded_filename[28:])[0]
('-Report.pdf', 'utf-8')
Видимо, именно это и делает Thunderbird в этом случае; разбить строку на =?encoding?data?=
ломти. Обычно они должны быть разделены \r\n
(CARRIAGE RETURN + LINE FEED) персонажей, но в вашем случае они смешиваются вместе. Если вы повторно введете \r\n
разделитель значение декодирует правильно:
>>> decode_header(encoded_filename[:28] + '\r\n' + encoded_filename[28:])[0]
('SalesInvoice-Report.pdf', 'utf-8')
Вы можете использовать регулярное выражение для извлечения частей и повторного введения разделителя:
import re
from email.header import decode_header
quopri_entry = re.compile(r'=\?[\w-]+\?[QB]\?[^?]+?\?=')
def decode_multiple(encoded, _pattern=quopri_entry):
fixed = '\r\n'.join(_pattern.findall(encoded))
output = [b.decode(c) for b, c in decode_header(fixed)]
return ''.join(output)
Демо-версия:
>>> encoded_filename = '=?UTF-8?B?U2FsZXNJbnZvaWNl?==?UTF-8?B?LVJlcG9ydC5wZGY=?='
>>> decode_multiple(encoded_filename)
u'SalesInvoice-Report.pdf'
Конечно, возможно, у вас есть ошибка в том, как вы читаете заголовок в первую очередь. Убедитесь, что вы случайно не уничтожили существующий \r\n
разделитель при извлечении encoded_filename
значение.