Il semble facile d’obtenir le
From
To
Subject
etc via
import email
b = email.message_from_string(a)
bbb = b['from']
ccc = b['to']
en admettant que "a"
est la chaîne de courrier électronique brute qui ressemble à ceci.
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 root@localhost)
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: <1374805739.3861@a1>
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--"""
LA QUESTION
comment obtenez-vous le Body
de cet email via python?
Jusqu'à présent, c'est le seul code que je connaisse mais je n'ai pas encore testé.
if email.is_multipart():
for part in email.get_payload():
print part.get_payload()
else:
print email.get_payload()
est-ce la bonne façon ?
ou peut-être qu'il y a quelque chose de plus simple, comme ...
import email
b = email.message_from_string(a)
bbb = b['body']
?
Utilisez 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()
Pour être très positif, vous travaillez avec le corps de l’e-mail (mais avec la possibilité de ne pas analyser la bonne partie), vous devez ignorer les pièces jointes et vous concentrer sur la partie simple ou html (selon vos besoins). En traitement.
Comme les pièces jointes susmentionnées peuvent et sont très souvent des parties text/plain ou text/html, cet exemple non protégé contre les balles les ignore en vérifiant l'en-tête content-disposition:
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()
itère merveilleusement sur les parties mime, et get_payload(decode=True)
effectue le travail compliqué sur le décodage en base64, etc. pour vous.
Un peu d’arrière-plan - comme je l’ai laissé entendre, le monde merveilleux des courriels MIME présente de nombreux pièges pour retrouver "à tort" le corps du message. Dans le cas le plus simple, il s'agit de la seule partie "text/plain" et get_payload () est très tentant, mais nous ne vivons pas dans un monde simple - il est souvent entouré de contenu multipart/alternatif, connexe, mixte, etc. Wikipedia le décrit très bien - MIME , mais compte tenu de tous les cas ci-dessous, ils sont valables - et communs -, il faut tenir compte des filets de sécurité:
Très commun - à peu près ce que vous obtenez dans l'éditeur normal (Gmail, Outlook) en envoyant du texte formaté avec une pièce jointe:
multipart/mixed
|
+- multipart/related
| |
| +- multipart/alternative
| | |
| | +- text/plain
| | +- text/html
| |
| +- image/png
|
+-- application/msexcel
Relativement simple - juste une représentation alternative:
multipart/alternative
|
+- text/plain
+- text/html
Pour le meilleur ou pour le pire, cette structure est également valide:
multipart/alternative
|
+- text/plain
+- multipart/related
|
+- text/html
+- image/jpeg
J'espère que ça aide un peu.
P.S. Mon problème est de ne pas approcher l'email à la légère - ça mord quand on s'y attend le moins :)
Il n'y a pas b['body']
en python. Vous devez utiliser 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...
Bonne chance.
Il est très bon package disponible pour analyser le contenu de l'email avec la documentation appropriée.
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)
Comment utiliser:
mail.attachments: list of all attachments
mail.body
mail.to
Si emails est le pandas dataframe et emails.message la colonne pour le texte de l'e-mail
## 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()