Подтвердить что ты не робот

Получение почтового вложения в файл файла python

У меня есть многопользовательский объект сообщения электронной почты, и я хочу преобразовать вложение в это сообщение электронной почты в объект файла python. Это возможно? Если возможно, какой метод или класс в Python я должен учитывать для выполнения такой задачи?

4b9b3361

Ответ 1

Я действительно не понимаю, что вы подразумеваете под "email multipart message object". Вы имеете в виду объект, принадлежащий классу 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.

Ответ 2

Вот рабочее решение, сообщения формируют сервер 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))

Ответ 3

На самом деле, используя предложенный сейчас email.EmailMessage API (не путайте со старым email.Message API), довольно легко:

  1. Перебирать все элементы сообщения и выбирать только вложения

  2. Перебирать только вложения

Предположим, что ваше сообщение хранится в виде байтового содержимого в переменной конверта.

Решение № 1:

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

Решение № 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

Пара вещей, чтобы отметить:

  1. Мы явно указываем использовать новый класс EmailMessage в нашем методе чтения байтов через параметр _class=EmailMessage
  2. Вы можете прочитать ваше электронное сообщение (он же конверт) из таких источников, как байтовидный объект, двоичный файл или строка, благодаря встроенным методам в message.Parser API