У меня есть многопользовательский объект сообщения электронной почты, и я хочу преобразовать вложение в это сообщение электронной почты в объект файла python. Это возможно? Если возможно, какой метод или класс в Python я должен учитывать для выполнения такой задачи?
Получение почтового вложения в файл файла python
Ответ 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:
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
Пара вещей, чтобы отметить:
- Мы явно указываем использовать новый класс
EmailMessage
в нашем методе чтения байтов через параметр_class=EmailMessage
- Вы можете прочитать ваше электронное сообщение (он же конверт) из таких источников, как байтовидный объект, двоичный файл или строка, благодаря встроенным методам в message.Parser API