获取邮件附件到python文件对象

Jos*_*ogi 24 python email

我有一个电子邮件多部分消息对象,我想将该电子邮件中的附件转换为python文件对象.这可能吗?如果有可能,我应该考虑使用Python中的哪种方法或类来完成这样的任务?

Gar*_*ees 60

我真的不明白你的意思是"电子邮件多部分邮件对象".你的意思是属于这个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))
Run Code Online (Sandbox Code Playgroud)

如果您以编程方式从已收到的电子邮件中提取附件,则可能需要采取预防措施来防范病毒和特洛伊木马.特别是,你可能只应该提取你认为安全的MIME类型的附件,并且你可能想要选择自己的文件名,或者至少清理输出get_filename.

  • HTML邮件通常在页脚中包含图像,这些图像也作为附件发送.您可以通过查看内容处置来区分这些与"真实"附件:内联图像以"内联"开头,而实际附件以"附件"开头.没有获取内容处置的方法,但如果您只对实际附件感兴趣,可以调用part.get('Content-Disposition').startswith('attachment'). (3认同)

pma*_*ma_ 14

这是工作解决方案,消息是形式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))
Run Code Online (Sandbox Code Playgroud)


Jak*_*zuk 6

实际上使用现在建议的email.EmailMessage API(不要与旧的email.Message API混淆)很容易:

  1. 遍历所有消息元素并仅选择附件

  2. 只迭代附件

假设您将消息作为字节内容存储在信封变量中

解决方案一:

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
Run Code Online (Sandbox Code Playgroud)

解决方案 2:(最好是因为您不必遍历消息对象的其他部分)

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
Run Code Online (Sandbox Code Playgroud)

需要注意的几点:

  1. 我们EmailMessage通过_class=EmailMessage参数明确告诉在我们的字节读取方法中使用新类
  2. 借助 message.Parser API 中的内置方法,您可以从类似字节的对象、二进制文件对象或字符串等来源读取电子邮件消息(又名信封)