2012-12-01 18 views
12

Sto cercando di ottenere tutti i messaggi da un account Gmail che potrebbe contenere alcuni allegati di grandi dimensioni (circa 30 MB). Ho solo bisogno dei nomi, non di tutti i file. Ho trovato un pezzo di codice per ottenere un messaggio e il nome del attaccamento, ma scarica il file e quindi leggere il suo nome:Ottieni il nome file allegato Gmail senza scaricarlo

import imaplib, email 

#log in and select the inbox 
mail = imaplib.IMAP4_SSL('imap.gmail.com') 
mail.login('username', 'password') 
mail.select('inbox') 

#get uids of all messages 
result, data = mail.uid('search', None, 'ALL') 
uids = data[0].split() 

#read the lastest message 
result, data = mail.uid('fetch', uids[-1], '(RFC822)') 
m = email.message_from_string(data[0][1]) 

if m.get_content_maintype() == 'multipart': #multipart messages only 
    for part in m.walk(): 
     #find the attachment part 
     if part.get_content_maintype() == 'multipart': continue 
     if part.get('Content-Disposition') is None: continue 

     #save the attachment in the program directory 
     filename = part.get_filename() 
     fp = open(filename, 'wb') 
     fp.write(part.get_payload(decode=True)) 
     fp.close() 
     print '%s saved!' % filename 

devo fare questo una volta al minuto, quindi non posso scaricare centinaia di MB di dati. Sono un principiante nello scripting web, quindi qualcuno potrebbe aiutarmi? In realtà non ho bisogno di usare imaplib, qualsiasi lib python sarà ok per me.

migliori saluti

+0

È possibile inviare solo 20 MB in gmail lo sai? – 0x90

+0

Intendo tutti gli allegati in tutti i messaggi. – mopsiok

risposta

8

Invece di scaricare RFC822, che è l'intero contenuto, è possibile specificare BODYSTRUCTURE.

La struttura dati risultante da imaplib è piuttosto confusa, ma dovresti essere in grado di trovare il nome file, il tipo di contenuto e le dimensioni di ciascuna parte del messaggio senza scaricare l'intera cosa.

+0

E questo è quello che stavo cercando ... Il risultato è davvero confuso, ma funziona. Grazie mille! – mopsiok

+0

Questo è esattamente quello che stavo cercando anche io. Ma hai qualche indizio su come analizzare quella stringa di risultati pazzi? @mopsiok, come hai fatto ad affrontarlo? – jjon

+1

Ho fatto alcuni test con esso, ma i risultati non sono stati molto piacevoli. In realtà trovo l'elenco degli allegati abbastanza insufficiente per la mia applicazione. Alla fine ricevo tutto il contenuto della posta, il testo e tutti gli allegati passando attraverso di esso. Non ho il codice di analisi, come ho detto è stato inefficace. Scusate... – mopsiok

3

Se sapete qualcosa circa il nome del file, è possibile utilizzare la X-GM-RAW gmail extensions for imap SEARCH command. Queste estensioni consentono di utilizzare qualsiasi query gmail advanced search per filtrare i messaggi. In questo modo puoi limitare i download ai messaggi corrispondenti o escludere alcuni messaggi che non desideri.

mail.uid('search', None, 'X-GM-RAW', 
     'has:attachment filename:pdf in:inbox -label:parsed')) 

La ricerca sopra per i messaggi con allegati PDF in INBOX non etichettati come "analizzati".

Alcuni consigli pro:

  • etichetta i messaggi che hanno già analizzato, quindi non è necessario per andare a prendere di nuovo loro (il -label: analizzato il filtro nell'esempio di cui sopra)
  • utilizzare sempre il versione uid invece degli ID sequenziali standard (lo stai già facendo)
  • sfortunatamente MIME è disordinato: ci sono molti client che fanno cose strane (o semplicemente sbagliate). Potresti provare a scaricare e analizzare solo le intestazioni, ma ne vale la pena?

[modifica]

Se si etichetta un messaggio dopo l'analisi, è possibile ignorare i messaggi che avete analizzato già. Questo dovrebbe essere abbastanza ragionevole da monitorare la tua casella di posta di classe.

Forse vivete in un angolo del mondo dove la larghezza di banda internet è più costosa del tempo del programmatore; in questo caso, puoi recuperare solo le intestazioni e cercare "Content-disposition" == "attachment; filename = somefilename.ext".

+0

È bello, ma il problema è che non so nulla sull'allegato. Sto scrivendo uno script per "scansionare" tutta la posta in arrivo di Gmail del mio account di classe e dirmi se è qualcosa di nuovo, comprese le informazioni sugli allegati (nome e dimensioni). La ricerca di messaggi non letti non funzionerebbe perché l'account è utilizzato da 30 persone. – mopsiok

+0

Almeno puoi saltare i messaggi senza allegati e i messaggi che hai già analizzato; nota che puoi anche filtrare per dimensione. –

+0

Certo che posso, ma non c'è alcun problema nel saltare i messaggi che ho già analizzato. Il problema è analizzare i prossimi 20 messaggi con 20MB di allegati all'interno, in un minuto. – mopsiok

2

UN FETCH dell'elemento di dati del messaggio RFC822 è funzionalmente equivalente a BODY[]. IMAP4 supporta altri elementi di dati del messaggio, elencati in section 6.4.5 of RFC 3501.

Provare a richiedere un set diverso di voci di dati messaggio per ottenere solo le informazioni necessarie. Ad esempio, potresti provare RFC822.HEADER o forse BODY.PEEK[MIME].

0

Vecchia domanda, ma volevo solo condividere la soluzione a questo mi è venuto fuori oggi. Cerca tutte le e-mail con allegati e visualizza l'uid, il mittente, l'oggetto e un elenco di allegati formattato.codice relativo A cura di mostrare come formattare BODYSTRUCTURE:

data = mailobj.uid('fetch', mail_uid, '(BODYSTRUCTURE)')[1] 
    struct = data[0].split()   
    list = []      #holds list of attachment filenames 

    for j, k in enumerate(struct): 
     if k == '("FILENAME"': 
      count = 1 
      val = struct[j + count] 
      while val[-3] != '"': 
       count += 1 
       val += " " + struct[j + count] 
      list.append(val[1:-3]) 
     elif k == '"FILENAME"': 
      count = 1 
      val = struct[j + count] 
      while val[-1] != '"': 
       count += 1 
       val += " " + struct[j + count] 
      list.append(val[1:-1]) 

ho anche pubblicato su GitHub.

Problemi correlati