我试图通过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)
这个语法'=?UTF-8?Q?...?='
是一个MIME encoded word。当标头值包含非ASCII字符(RFC 2047中的血腥细节)时,它在MIME电子邮件中使用。您的附件文件名包含“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,最好的选择是升级到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包中包含compatibility version的email.parser.BytesParser
,试图在Python 2.7电子邮件解析中解决几个(但不是全部)other bugs。您可以为您的目的借用该(内部)代码。 (或者既然你标记了你的问题Django,你可能想要查看Anymail的规范化inbound email处理,其中包括Amazon SES支持。)