J'ai un objet de message en plusieurs parties et je souhaite convertir la pièce jointe de ce message en objet de fichier python. Est-ce possible? Si cela est possible, quelle méthode ou classe en Python je devrais étudier pour effectuer une telle tâche?
Je ne comprends pas vraiment ce que vous entendez par "objet de message de messagerie multiple". Voulez-vous dire un objet appartenant à la classe email.message.Message
?
Si c'est ce que vous voulez dire, c'est simple. Sur un message en plusieurs parties, la méthode get_payload
renvoie une liste d'éléments de message (chacun étant lui-même un objet Message
). Vous pouvez parcourir ces parties et examiner leurs propriétés: par exemple, la méthode get_content_type
renvoie le type MIME de la partie et la méthode get_filename
renvoie le nom de fichier de la partie (le cas échéant). Ensuite, lorsque vous avez trouvé la bonne partie du message, vous pouvez appeler get_payload(decode=True)
pour obtenir le contenu décodé.
>>> 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))
Si vous extrayez par programme les pièces jointes des courriels que vous avez reçus, vous voudrez peut-être prendre des précautions contre les virus et les chevaux de Troie. En particulier, vous ne devriez probablement extraire que les pièces jointes dont les types MIME, vous le savez, sont sûrs, et vous voulez probablement choisir votre propre nom de fichier ou au moins nettoyer le résultat de get_filename
.
Voici la solution qui fonctionne, les messages sont sous forme de serveur 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))
En fait, en utilisant email.EmailMessage API _ (à ne pas confondre avec l'ancien API.mail.Message ) maintenant suggéré, il est assez facile de:
Itérer sur tous les éléments du message et sélectionner uniquement les pièces jointes
Itérer sur les pièces jointes seulement
Supposons que votre message soit stocké sous forme de contenu d'octet dans une variable d'enveloppe
Solution n ° 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
Solution n ° 2: (préférable car vous n'avez pas besoin de parcourir d'autres parties de votre objet message)
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
Quelques choses à noter:
EmailMessage
dans notre méthode de lecture d'octet via le paramètre _class=EmailMessage