Ответ 1
Используйте Message.get_payload
b = email.message_from_string(a)
if b.is_multipart():
for payload in b.get_payload():
# if payload.is_multipart(): ...
print payload.get_payload()
else:
print b.get_payload()
Кажется легко получить
From
To
Subject
и т.д. через
import email
b = email.message_from_string(a)
bbb = b['from']
ccc = b['to']
предполагая, что "a"
является строкой raw-email, которая выглядит примерно так.
a = """From [email protected] Thu Jul 25 19:28:59 2013
Received: from a1.local.tld (localhost [127.0.0.1])
by a1.local.tld (8.14.4/8.14.4) with ESMTP id r6Q2SxeQ003866
for <[email protected]>; Thu, 25 Jul 2013 19:28:59 -0700
Received: (from [email protected])
by a1.local.tld (8.14.4/8.14.4/Submit) id r6Q2Sxbh003865;
Thu, 25 Jul 2013 19:28:59 -0700
From: [email protected]
Subject: oooooooooooooooo
To: [email protected]
Cc:
X-Originating-IP: 192.168.15.127
X-Mailer: Webmin 1.420
Message-Id: <[email protected]>
Date: Thu, 25 Jul 2013 19:28:59 -0700 (PDT)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="bound1374805739"
This is a multi-part message in MIME format.
--bound1374805739
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
ooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooo
--bound1374805739--"""
ВОПРОС
как вы получите Body
этого письма через python?
Пока это единственный код, о котором я знаю, но мне еще нужно его протестировать.
if email.is_multipart():
for part in email.get_payload():
print part.get_payload()
else:
print email.get_payload()
Правильно ли это?
или может быть что-то более простое, например...
import email
b = email.message_from_string(a)
bbb = b['body']
?
Используйте Message.get_payload
b = email.message_from_string(a)
if b.is_multipart():
for payload in b.get_payload():
# if payload.is_multipart(): ...
print payload.get_payload()
else:
print b.get_payload()
Чтобы быть высокопоставленными, вы работаете с фактическим телом электронной почты (все же, при том, что вы не разбираете правую часть), вам нужно пропустить вложения и сосредоточиться на простой или html-части (в зависимости от ваших потребностей ) для дальнейшей обработки.
Поскольку ранее упомянутые вложения могут и очень часто имеют часть text/plain или text/html, этот образец без пули пропускает их, проверяя заголовок содержимого:
b = email.message_from_string(a)
body = ""
if b.is_multipart():
for part in b.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
# skip any text/plain (txt) attachments
if ctype == 'text/plain' and 'attachment' not in cdispo:
body = part.get_payload(decode=True) # decode
break
# not multipart - i.e. plain text, no attachments, keeping fingers crossed
else:
body = b.get_payload(decode=True)
BTW, walk()
итеративно изучает части мим, а get_payload(decode=True)
выполняет грязную работу по расшифровке base64 и т.д. для вас.
Некоторый фон - как я подразумевал, замечательный мир электронных писем MIME представляет собой множество подводных камней "неправильного" нахождения тела сообщения. В простейшем случае это в единственной части "text/plain" и get_payload() очень заманчиво, но мы не живем в простом мире - он часто окружен разнородным/альтернативным, связанным, смешанным и т.д. Контентом. Википедия описывает это плотно - MIME, но, учитывая, что все эти случаи ниже действительны - и распространены - нужно учитывать системы безопасности:
Очень часто - почти что вы получаете в обычном редакторе (Gmail, Outlook), отправляя отформатированный текст с приложением:
multipart/mixed
|
+- multipart/related
| |
| +- multipart/alternative
| | |
| | +- text/plain
| | +- text/html
| |
| +- image/png
|
+-- application/msexcel
Относительно простое - просто альтернативное представление:
multipart/alternative
|
+- text/plain
+- text/html
Для хорошего или плохого эта структура также действительна:
multipart/alternative
|
+- text/plain
+- multipart/related
|
+- text/html
+- image/jpeg
Надеюсь, это немного поможет.
P.S. Моя точка зрения не приближается к электронной почте - она кусает, когда вы меньше всего этого ожидаете:)
В python нет b['body']
. Вы должны использовать get_payload.
if isinstance(mailEntity.get_payload(), list):
for eachPayload in mailEntity.get_payload():
...do things you want...
...real mail body is in eachPayload.get_payload()...
else:
...means there is only text/plain part....
...use mailEntity.get_payload() to get the body...
Удачи.
Существует очень хороший пакет для анализа содержимого электронной почты с соответствующей документацией.
import mailparser
mail = mailparser.parse_from_file(f)
mail = mailparser.parse_from_file_obj(fp)
mail = mailparser.parse_from_string(raw_mail)
mail = mailparser.parse_from_bytes(byte_mail)
Как пользоваться:
mail.attachments: list of all attachments
mail.body
mail.to
Если электронные письма - это dataframe pandas и emails.message столбец для текста электронной почты
## Helper functions
def get_text_from_email(msg):
'''To get the content from email objects'''
parts = []
for part in msg.walk():
if part.get_content_type() == 'text/plain':
parts.append( part.get_payload() )
return ''.join(parts)
def split_email_addresses(line):
'''To separate multiple email addresses'''
if line:
addrs = line.split(',')
addrs = frozenset(map(lambda x: x.strip(), addrs))
else:
addrs = None
return addrs
import email
# Parse the emails into a list email objects
messages = list(map(email.message_from_string, emails['message']))
emails.drop('message', axis=1, inplace=True)
# Get fields from parsed email objects
keys = messages[0].keys()
for key in keys:
emails[key] = [doc[key] for doc in messages]
# Parse content from emails
emails['content'] = list(map(get_text_from_email, messages))
# Split multiple email addresses
emails['From'] = emails['From'].map(split_email_addresses)
emails['To'] = emails['To'].map(split_email_addresses)
# Extract the root of 'file' as 'user'
emails['user'] = emails['file'].map(lambda x:x.split('/')[0])
del messages
emails.head()
Вот код, который работает для меня каждый раз (для электронной почты Outlook):
#to read Subjects and Body of email in a folder (or subfolder)
import win32com.client
#import package
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
#create object
#get to the desired folder ([email protected] is my root folder)
root_folder =
outlook.Folders['[email protected]'].Folders['Inbox'].Folders['SubFolderName']
#('Inbox' and 'SubFolderName' are the subfolders)
messages = root_folder.Items
for message in messages:
if message.Unread == True: # gets only 'Unread' emails
subject_content = message.subject
# to store subject lines of mails
body_content = message.body
# to store Body of mails
print(subject_content)
print(body_content)
message.Unread = True # mark the mail as 'Read'
message = messages.GetNext() #iterate over mails