Ошибка кодирования: в данных MIME-файла через AWS SES - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь получить данные вложения, такие как формат файла и имя файла, из MIME через aws SES.К сожалению, время от времени кодировка имени файла изменяется, например имя файла «3_amrishmishra_Entry Level Resume - 02.pdf» и в MIME оно выглядит как «=? UTF-8? Q? Amrishmishra = 5FEntry_Level_Resume_ = E2 = 80 = 93_02 = 2Epdf? =', любой способ получить точное имя файла?

if email_message.is_multipart():
message = ''
if "apply" in receiver_email.split('@')[0].split('_')[0] and isinstance(int(receiver_email.split('@')[0].split('_')[1]), int):
    for part in email_message.walk():
        content_type = str(part.get_content_type()).lower()
        content_dispo = str(part.get('Content-Disposition')).lower()
        print(content_type, content_dispo)

        if 'text/plain' in content_type and "attachment" not in content_dispo:
            message = part.get_payload()


        if content_type in ['application/pdf', 'text/plain', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'image/jpeg', 'image/jpg', 'image/png', 'image/gif'] and "attachment" in content_dispo:
            filename = part.get_filename()
            # open('/tmp/local' + filename, 'wb').write(part.get_payload(decode=True))
            # s3r.meta.client.upload_file('/tmp/local' + filename, bucket_to_upload, filename)

            data = {
                'base64_resume': part.get_payload(),
                'filename': filename,
            }
            data_list.append(data)
    try:
        api_data = {
            'email_data': email_data,
            'resumes_data': data_list
        }
        print(len(data_list))
        response = requests.post(url, data=json.dumps(api_data),
                                 headers={'content-type': 'application/json'})
        print(response.status_code, response.content)
    except Exception as e:
        print("error %s" % e)

1 Ответ

0 голосов
/ 24 февраля 2019

Этот синтаксис '=?UTF-8?Q?...?=' является MIME-кодированным словом .Он используется в электронной почте MIME, когда значение заголовка включает не-ASCII-символы (подробности в RFC 2047 ).Ваше имя файла вложения содержит символ «en dash», поэтому оно было отправлено с этой кодировкой.

Лучший способ справиться с этим зависит от используемой версии Python ...

Python 3

Обновленный пакет Python 3 email.parser может корректно декодировать заголовки RFC 2047 для вас:

# Python 3
from email import message_from_bytes, policy

raw_message_bytes = b"<< the MIME message you downloaded from SES >>"
message = message_from_bytes(raw_message_bytes, policy=policy.default)
for attachment in message.iter_attachments():
    # (EmailMessage.iter_attachments is new in Python 3)
    print(attachment.get_filename())
    # amrishmishra_Entry Level Resume – 02.pdf

Вы должны специально запроситьpolicy.default.Если вы этого не сделаете, синтаксический анализатор будет использовать политику compat32, которая копирует ошибочное поведение Python 2.7 - в том числе не декодирует RFC 2047. (Кроме того, ранние выпуски Python 3 все еще выталкивали ошибки в новом почтовом пакете, поэтомууверен, что вы используете Python 3.5 или более позднюю версию.)

Python 2

Если вы используете Python 2, опция best обновляетсядо Python 3.5 или более поздней версии, если это вообще возможно.У парсера электронной почты Python 2 много ошибок и ограничений , которые были исправлены с помощью массовой переписки в Python 3. (И переписывание добавило новые удобные функции, такие как iter_attachments(), показанные выше.)

Если выне можете переключиться на Python 3, вы можете самостоятельно расшифровать имя файла RFC 2047, используя email.header.decode_header:

# Python 2 (also works in Python 3, but you shouldn't need it there)
from email.header import decode_header

filename = '=?UTF-8?Q?amrishmishra=5FEntry_Level_Resume_=E2=80=93_02=2Epdf?='
decode_header(filename)
# [('amrishmishra_Entry Level Resume \xe2\x80\x93 02.pdf', 'utf-8')]

(decoded_string, charset) = decode_header(filename)[0]
decoded_string.decode(charset)
# u'amrishmishra_Entry Level Resume – 02.pdf'

Но опять же, если вы пытаетесь проанализировать электронную почту реального мирав Python 2.7 помните, что это, вероятно, только первая из нескольких проблем, с которыми вы столкнетесь.

Пакет django-anymail , который я поддерживаю, включает в себя версия совместимости из email.parser.BytesParser, которая пытается обойти несколько (но не все ) другие ошибки в парсинге электронной почты Python 2.7.Вы можете заимствовать этот (внутренний) код для своих целей.(Или, так как вы пометили свой вопрос Django, вы можете захотеть посмотреть на стандартную обработку Anymail входящей электронной почты , которая включает поддержку Amazon SES.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...