将邮件附件获取为Python文件对象
我有一个电子邮件的多部分消息对象,我想把这个邮件中的附件转换成Python的文件对象。这可能吗?如果可以的话,我应该查找Python中的哪个方法或类来完成这个任务呢?
3 个回答
11
其实现在推荐使用的 email.EmailMessage API(不要和旧的 email.Message API 混淆)其实很简单,可以做到:
遍历所有的消息元素,只选择附件
只遍历附件
假设你把消息存储在一个叫做 envelope 的变量里,内容是字节格式的。
解决方案一:
import email
from email.message import EmailMessage
email_message: EmailMessage = email.message_from_bytes(envelope, _class=EmailMessage)
for email_message_part in email_message.walk():
if email_message.is_attachment():
# Do something with your attachment
解决方案二:(更推荐这个,因为你不需要遍历消息对象的其他部分)
import email
from email.message import EmailMessage
email_message: EmailMessage = email.message_from_bytes(envelope, _class=EmailMessage)
for email_message_attachment in email_message.iter_attachments():
# Do something with your attachment
有几点需要注意:
- 我们在读取字节时,明确告诉程序使用新的
EmailMessage
类,这通过_class=EmailMessage
参数来实现。 - 你可以通过内置的方法从 message.Parser API 中读取你的邮件消息(也就是 envelope),来源可以是 字节对象、二进制文件对象或字符串。
21
这里有一个可用的解决方案,消息来自IMAP服务器。
self.imap.select()
typ, data = self.imap.uid('SEARCH', 'ALL')
msgs = data[0].split()
print "Found {0} msgs".format(len(msgs))
for uid in msgs:
typ, s = self.imap.uid('FETCH', uid, '(RFC822)')
mail = email.message_from_string(s[0][1])
print "From: {0}, Subject: {1}, Date: {2}\n".format(mail["From"], mail["Subject"], mail["Date"])
if mail.is_multipart():
print 'multipart'
for part in mail.walk():
ctype = part.get_content_type()
if ctype in ['image/jpeg', 'image/png']:
open(part.get_filename(), 'wb').write(part.get_payload(decode=True))
73
我不太明白你说的“电子邮件多部分消息对象”是什么意思。你是指属于 email.message.Message
类的对象吗?
如果是这个意思,那其实很简单。在一个多部分的消息中,get_payload
方法会返回一个消息部分的列表(每个部分本身也是一个 Message
对象)。你可以遍历这些部分,查看它们的属性:比如,get_content_type
方法会返回这个部分的 MIME 类型,而 get_filename
方法会返回这个部分的文件名(如果消息中指定了的话)。当你找到正确的消息部分后,可以调用 get_payload(decode=True)
来获取解码后的内容。
>>> import email
>>> msg = email.message_from_file(open('message.txt'))
>>> len(msg.get_payload())
2
>>> attachment = msg.get_payload()[1]
>>> attachment.get_content_type()
'image/png'
>>> open('attachment.png', 'wb').write(attachment.get_payload(decode=True))
如果你是通过编程从收到的电子邮件中提取附件,建议你要小心病毒和木马。特别是,你应该只提取那些你知道是安全的 MIME 类型的附件,并且最好自己选择文件名,或者至少要对 get_filename
的输出进行处理,确保安全。