web-dev-qa-db-fra.com

Comment récupérer un corps d'email en utilisant imaplib en python?

Je voudrais récupérer le message entier du serveur IMAP4. Dans les documents Python, si ce code est trouvé, il fonctionne:

>>> t, data = M.fetch('1', '(RFC822)')
>>> body = data[0][1]

Je me demande si je peux toujours croire que data [0] [1] renvoie le corps du message. Quand j'ai lancé 'RFC822.SIZE', j'ai juste une chaîne au lieu d'un tuple.

J'ai parcouru rfc1730 mais je n'ai pas été en mesure de déterminer la structure de réponse appropriée pour le 'RFC822'. Il est également difficile de distinguer la structure du résultat d’extraction de la documentation d’imaplib.

Voici ce que je reçois en récupérant RFC822:

('OK', [('1 (RFC822 {858569}', 'body of the message', ')')])

Mais quand je récupère RFC822.SIZE je reçois:

('OK', ['1 (RFC822.SIZE 847403)'])

Comment dois-je gérer correctement la liste de données [0]? Puis-je croire que lorsqu'il s'agit d'une liste de n-uplets, les n-uplets ont exactement 3 parties et la deuxième partie est la charge utile?

Peut-être connaissez-vous une meilleure bibliothèque pour imap4?

20
Piotr Czapla

Non ... imaplib est une très bonne bibliothèque, c'est une carte tellement inintelligible.

Vous voudrez peut-être vérifier que t == 'OK', mais data[0][1] fonctionne comme prévu pour autant que je l’ai utilisé.

Voici un exemple rapide que j'utilise pour extraire les certificats signés que j'ai reçus par courrier électronique, pas à l'abri des bombes, mais convient à mes besoins

import getpass, os, imaplib, email
from OpenSSL.crypto import load_certificate, FILETYPE_PEM

def getMsgs(servername="myimapserverfqdn"):
  usernm = getpass.getuser()
  passwd = getpass.getpass()
  subject = 'Your SSL Certificate'
  conn = imaplib.IMAP4_SSL(servername)
  conn.login(usernm,passwd)
  conn.select('Inbox')
  typ, data = conn.search(None,'(UNSEEN SUBJECT "%s")' % subject)
  for num in data[0].split():
    typ, data = conn.fetch(num,'(RFC822)')
    msg = email.message_from_string(data[0][1])
    typ, data = conn.store(num,'-FLAGS','\\Seen')
    yield msg

def getAttachment(msg,check):
  for part in msg.walk():
    if part.get_content_type() == 'application/octet-stream':
      if check(part.get_filename()):
        return part.get_payload(decode=1)

if __== '__main__':
  for msg in getMsgs():
    payload = getAttachment(msg,lambda x: x.endswith('.pem'))
    if not payload:
      continue
    try:
      cert = load_certificate(FILETYPE_PEM,payload)
    except:
      cert = None
    if cert:
      cn = cert.get_subject().commonName
      filename = "%s.pem" % cn
      if not os.path.exists(filename):
        open(filename,'w').write(payload)
        print "Writing to %s" % filename
      else:
        print "%s already exists" % filename
27
MattH

Le paquet IMAPClient est un peu plus facile à utiliser. De la description:

Bibliothèque de clients IMAP facile à utiliser, Pythonic et complète .

10
Peter Hansen

C'était ma solution pour extraire les informations utiles. Cela a été fiable jusqu'à présent:

import datetime
import email
import imaplib
import mailbox


EMAIL_ACCOUNT = "[email protected]"
PASSWORD = "your password"

mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login(EMAIL_ACCOUNT, PASSWORD)
mail.list()
mail.select('inbox')
result, data = mail.uid('search', None, "UNSEEN") # (ALL/UNSEEN)
i = len(data[0].split())

for x in range(i):
    latest_email_uid = data[0].split()[x]
    result, email_data = mail.uid('fetch', latest_email_uid, '(RFC822)')
    # result, email_data = conn.store(num,'-FLAGS','\\Seen') 
    # this might work to set flag to seen, if it doesn't already
    raw_email = email_data[0][1]
    raw_email_string = raw_email.decode('utf-8')
    email_message = email.message_from_string(raw_email_string)

    # Header Details
    date_Tuple = email.utils.parsedate_tz(email_message['Date'])
    if date_Tuple:
        local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_Tuple))
        local_message_date = "%s" %(str(local_date.strftime("%a, %d %b %Y %H:%M:%S")))
    email_from = str(email.header.make_header(email.header.decode_header(email_message['From'])))
    email_to = str(email.header.make_header(email.header.decode_header(email_message['To'])))
    subject = str(email.header.make_header(email.header.decode_header(email_message['Subject'])))

    # Body details
    for part in email_message.walk():
        if part.get_content_type() == "text/plain":
            body = part.get_payload(decode=True)
            file_name = "email_" + str(x) + ".txt"
            output_file = open(file_name, 'w')
            output_file.write("From: %s\nTo: %s\nDate: %s\nSubject: %s\n\nBody: \n\n%s" %(email_from, email_to,local_message_date, subject, body.decode('utf-8')))
            output_file.close()
        else:
            continue
1
Edward Chapman

bibliothèque imap-tools pour une utilisation efficace des messages électroniques utilisant le protocole IMAP.

  • travail transparent avec attributs de lettre (y compris uid)
  • travailler avec des lettres dans des répertoires (copier, supprimer, marquer, déplacer, voir)
  • travailler avec des répertoires (liste, définir, obtenir, créer, existe, renommer, supprimer, statut)
  • pas de dépendances externes
0
Vladimir