2010-02-09 13 views
16

Je voudrais récupérer le message entier du serveur IMAP4. Dans docs python si ce bit trouvé de code qui fonctionne:Comment récupérer un corps d'e-mail en utilisant imaplib en python?

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

Je me demande si je peux toujours faire confiance que les données [0] [1] retourne 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 réussi à trouver la bonne structure de réponse pour le 'RFC822'. Il est également difficile de dire à la structure de résultat d'extraction de la documentation d'imaplib.

Voici ce que je reçois lors de la récupération RFC822:

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

Mais quand je vais chercher RFC822.SIZE je reçois:

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

Comment dois-je gérer correctement les données [0] liste ? Puis-je croire que quand c'est une liste de tuples, les tuples ont exactement 3 parties et la deuxième partie est la charge utile?

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

+0

si u le corps récupéré avec succès du courrier pouvez-vous s'il vous plaît partager le code? – hussain

Répondre

19

Non ... imaplib est une très bonne bibliothèque, c'est imap qui est si 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çu par e-mail, pas l'épreuve 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 __name__ == '__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 
+0

Bon de savoir que cela fonctionne pour vous. Mais des pensées pourquoi cela fonctionne comme décrit? –

+0

Les valeurs de retour correspondent à la réponse du serveur IMAP à jeton. – MattH

+0

Il est probable que les bibliothèques imap de plus haut niveau doivent gérer les faiblesses entre différentes implémentations imap, ou être incompatibles. – MattH

7

Le paquet IMAPClient est un peu juste plus facile de travailler avec. De la description:

Bibliothèque cliente IMAP facile à utiliser, Pythonique et complète .

+0

Je prends cela en charge. IMAPClient est très à utiliser et orienté objet. Il est beaucoup plus facile à utiliser qu'imaplib et n'a pas de problèmes majeurs. – zoobert

0

Cela a été ma solution pour extraire les informations utiles. Il a été fiable à ce jour:

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 
0

imap-tools bibliothèque pour travailler efficacement avec des messages électroniques utilisant le protocole IMAP.

  • travail transparent avec des attributs de lettres (y compris uid)
  • de travail avec des lettres dans les répertoires (copier, supprimer, drapeau, mouvement, vu)
  • travail avec des répertoires (liste, ensemble, obtenir, créer, existe , renommer, supprimer, état)
  • pas de dépendances externes