1) Другие (особенно в срочном порядке) отметили, что для буфера должно быть выделено некоторое пространство памяти. Для небольших значений N (скажем, N < = 4096) вы также можете выделить его в стеке:
#define BUFFER_SIZE 4096
char buffer[BUFFER_SIZE]
Это избавит вас от беспокойства по поводу того, что буфер delete[]
должен быть исключением быть брошенным.
Но помните, что стеки имеют конечный размер (как и кучи, но стеки более конечные), так что вы не хотите помещать туда слишком много.
2) Для кода возврата -1 вы не должны просто немедленно возвращаться (немедленное создание исключения еще более схематично.) Существуют определенные нормальные условия, с которыми вам нужно справиться, если ваш код должен быть чем-то большим, чем короткое домашнее задание. Например, EAGAIN может быть возвращен в errno, если в настоящее время нет данных на неблокирующем сокете. Взгляните на справочную страницу для чтения (2).
Я не совсем понимаю, что вы имеете в виду под «объектом составного сообщения электронной почты». Вы имеете в виду объект, принадлежащий к классу 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
.
Вот рабочее решение, сообщения формируются 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))
. На самом деле, используя предложенный 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
параметр