编码错误:通过AWS SES在MIME文件数据中

时间:2019-02-20 14:20:16

标签: python django mime amazon-ses

我正在尝试通过aws SES从MIME中检索附件数据,例如文件格式和文件名。不幸的是,文件名编码有时会更改,例如文件名是“ 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 :(得分:1)

此语法'=?UTF-8?Q?...?='MIME encoded word。标头值包含非ASCII字符(RFC 2047中的详细信息)时,将在MIME电子邮件中使用它。您的附件文件名包含一个“破折号”字符,这就是为什么它以这种编码发送的原因。

处理它的最佳方法取决于您所使用的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,则可以使用email.header.decode_header自己解码RFC 2047文件名:

# 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中的compatibility version,该程序试图解决Python中的几个(但不是 all other bugs 2.7电子邮件解析。您可能可以出于自己的目的借用该(内部)代码。 (或者,因为您标记了问题Django,所以您可能希望研究Anymail的规范化inbound email处理,其中包括Amazon SES支持。)