Scopo | Lavora con i messaggi email in diversi formati di file locali. |
Versione Python | 1.4 e superiore |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per il modulo mailbox
Il modulo mailbox definisce una API comune per accedere a messaggi email salvati in formati di disco locale inclusi:
Ci sono classi base per Mailbox e Message , ed ogni formato di mailbox comprende una corrispondente coppia di sottoclassi per implementare il dettaglio per quel formato.
Il formato mbox è il più semplice da illustrare nella documentazione, visto che è interamente in testo semplice. Ogni mailbox viene salvata come singolo file, con tutti i messaggi concatenati assieme. Ogni volta che viene rilevata una riga che inizia con "From " (
From
seguito da un singolo spazio), essa viene trattata come l'inizio di un nuovo messaggio. Ogni volta che questi caratteri appaiono all'inizio di una riga nel corpo del messaggio, ad essi viene fatto precedere il prefisso ">".
Si istanzia la classe
email.mbox
passando il nome del file al costruttore. Se il file non esiste, viene creato quando ad esso si aggiungono messaggi usando
add()
.
import mailbox
import email.utils
from_addr = email.utils.formataddr(('Author', 'author@example.com'))
to_addr = email.utils.formataddr(('Recipient', 'recipient@example.com'))
mbox = mailbox.mbox('example.mbox')
mbox.lock()
try:
msg = mailbox.mboxMessage()
msg.set_unixfrom('author Sat Feb 7 01:05:34 2009')
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = 'Messaggio di prova n. 1'
msg.set_payload('Questo è il corpo del messaggio.\nFrom (dovrebbe essere prefissato con >).\nCi sono 3 righe.\n')
mbox.add(msg)
mbox.flush()
msg = mailbox.mboxMessage()
msg.set_unixfrom('author')
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = 'Messaggio di prova n. 2'
msg.set_payload('Questo è il corpo del secondo messaggio.\n')
mbox.add(msg)
mbox.flush()
finally:
mbox.unlock()
print open('example.mbox', 'r').read()
Il risultato di questo script è un nuovo file mailbox con 2 messaggi.
$ python mailbox_mbox_create.py From MAILER-DAEMON Fri Jan 1 10:45:21 2010 From: AuthorTo: Recipient Subject: Messaggio di prova n. 1 Questo è il corpo del messaggio. >From (dovrebbe essere prefissato da >). Ci sono 3 righe. From MAILER-DAEMON Fri Jan 1 10:45:21 2010 From: Author To: Recipient Subject: Messaggio di prova n. 2 Questo è il corpo del secondo messaggio.
Per leggere una mailbox esistente, aprirla, quindi trattare l'oggetto mbox come un dizionario. Le chiavi sono valori arbitrari definiti dall'istanza di mailbox e non hanno necessariamente un particolare significato se non come identificatori interni per gli oggetti messaggio.
import mailbox
mbox = mailbox.mbox('example.mbox')
for message in mbox:
print message['subject']
Si può iterare attraverso la mailbox aperta ma si tenga presente che, al contrario dei dizionari, l'iteratore predefinito per una mailbox lavora con i valori e non con le chiavi .
$ python mailbox_mbox_read.py Messaggio di prova n. 1 Messaggio di prova n. 2
Per rimuovere un messaggio esistente da un file mbox si usa la sua chiave con
remove()
oppure si usa
del()
.
import mailbox
mbox = mailbox.mbox('example.mbox')
to_remove = []
for key, msg in mbox.iteritems():
if '2' in msg['subject']:
print 'Rimuovo:', key
to_remove.append(key)
mbox.lock()
try:
for key in to_remove:
mbox.remove(key)
finally:
mbox.flush()
mbox.close()
print open('example.mbox', 'r').read()
Si noti l'uso di
lock()
ed
unlock()
per evitare problemi di accesso simultaneo al file, e
flush()
per forzare la scrittura su disco delle modifiche.
Rimuovo: 1 From MAILER-DAEMON Fri Jan 1 10:45:21 2010 From: AuthorTo: Recipient Subject: Messaggio di prova n. 1 Questo è il corpo del messaggio. >From (dovrebbe essere prefissato da >). Ci sono 3 righe.
Il formato Maildir fu creato per eliminare il problema di modifiche simultanee in un file mbox. Invece che usare un singolo file, ogni mailbox è una directory ed ogni messaggio è contenuto in un suo proprio file. Questo consente alle mailbox di essere nidificate, e quindi anche la API per la mailbox MailDir è estesa con metodi che lavorano con le sottodirectory.
L'unica vera differenza tra l'usare Maildir e mbox è che per istanziare l'oggetto
email.Maildir
si deve passare la directory che contiene la mailbox al costruttore. Come detto prima, se non esiste, la mailbox viene creata quando si aggiungono ad essa dei messaggi usando
add()
.
import mailbox
import email.utils
import os
from_addr = email.utils.formataddr(('Author', 'author@example.com'))
to_addr = email.utils.formataddr(('Recipient', 'recipient@example.com'))
mbox = mailbox.Maildir('Example')
mbox.lock()
try:
msg = mailbox.mboxMessage()
msg.set_unixfrom('author Sat Feb 7 01:05:34 2009')
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = 'Messaggio di prova n. 1'
msg.set_payload('Questo è il corpo del messaggio.\nFrom (dovrebbe essere prefissato da >).\nCi sono 3 righe.\n')
mbox.add(msg)
mbox.flush()
msg = mailbox.mboxMessage()
msg.set_unixfrom('author Sat Feb 7 01:05:34 2009')
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = 'Messaggio di prova n. 2'
msg.set_payload('Questo è il corpo del secondo messaggio.\n')
mbox.add(msg)
mbox.flush()
finally:
mbox.unlock()
for dirname, subdirs, files in os.walk('Example'):
print dirname
print '\tDirectories:', subdirs
for name in files:
fullname = os.path.join(dirname, name)
print
print '***', fullname
print open(fullname).read()
print '*' * 20
Visto che sono stati aggiunti messaggi alla mailbox, essi vanno nella "nuova" sottodirectory. Una volta "letti", un client potrebbe spostarli nella sottodirectory "cur".
Example Directories: ['new', 'cur', 'tmp'] Example/new Directories: [] *** Example/new/1262343445.M330873P12060Q2.robby-desktop From: AuthorTo: Recipient Subject: Messaggio di prova n. 2 Questo è il corpo del secondo messaggio. ******************** *** Example/new/1262343445.M328864P12060Q1.robby-desktop From: Author To: Recipient Subject: Messaggio di prova n. 1 Questo è il corpo del messaggio. From (dovrebbe essere prefissato da >). Ci sono 3 righe. ******************** Example/cur Directories: [] Example/tmp Directories: []
La lettura da una mailbox Maildir esistente funziona come con mbox.
import mailbox
mbox = mailbox.Maildir('Example')
for message in mbox:
print message['subject']
Si noti che non c'è garanzia che i messaggi siano letti in un qualche ordine particolare.
$ python mailbox_maildir_read.py Messaggio di prova n. 1 Messaggio di prova n. 2
Per rimuovere un messaggio esistente da una mailbox Maildir si usa la sua chiave con
remove()
oppure si usa
del
.
import mailbox
import os
mbox = mailbox.Maildir('Example')
to_remove = []
for key, msg in mbox.iteritems():
if '2' in msg['subject']:
print 'Rimuovo:', key
to_remove.append(key)
mbox.lock()
try:
for key in to_remove:
mbox.remove(key)
finally:
mbox.flush()
mbox.close()
for dirname, subdirs, files in os.walk('Example'):
print dirname
print '\tDirectory:', subdirs
for name in files:
fullname = os.path.join(dirname, name)
print
print '***', fullname
print open(fullname).read()
print '*' * 20
$ python mailbox_maildir_remove.py Rimuovo: 1262429441.M698437P6782Q2.robby-desktop Example Directory: ['new', 'cur', 'tmp'] Example/new Directory: [] *** Example/new/1262429441.M690618P6782Q1.robby-desktop From: AuthorTo: Recipient Subject: Messaggio di prova n. 1 Questo è il corpo del messaggio. From (dovrebbe essere prefissato da >). Ci sono 3 righe. ******************** Example/cur Directory: [] Example/tmp Directory: []
Le sottodirectory o cartelle di una mailbox Maildir possono essere gestite direttamente tramite i metodi della classe Maildir. I chiamanti possono elencare, recuperare, creare e rimuovere sottocartelle per una mailbox specifica.
import mailbox
import os
def show_maildir(name):
os.system('find %s -print' % name)
mbox = mailbox.Maildir('Example')
print 'Prima:', mbox.list_folders()
show_maildir('Example')
print
print '#' * 30
print
mbox.add_folder('sottocartella')
print 'creata sottocartella:', mbox.list_folders()
show_maildir('Example')
subfolder = mbox.get_folder('sottocartella')
print 'sottocartella contiene:', subfolder.list_folders()
print
print '#' * 30
print
subfolder.add_folder('secondo_livello')
print 'creato secondo_livello:', subfolder.list_folders()
show_maildir('Example')
print
print '#' * 30
print
subfolder.remove_folder('secondo_livello')
print 'secondo_livello rimosso:', subfolder.list_folders()
show_maildir('Example')
Il nome della directory per una cartella viene costruito prefissando il nome della cartella con
.
.
$ python mailbox_maildir_folders.py Prima: [] Example Example/new Example/new/1262429441.M690618P6782Q1.robby-desktop Example/cur Example/tmp ############################## creata sottocartella: ['sottocartella'] Example Example/new Example/new/1262429441.M690618P6782Q1.robby-desktop Example/cur Example/tmp Example/.sottocartella Example/.sottocartella/new Example/.sottocartella/maildirfolder Example/.sottocartella/cur Example/.sottocartella/tmp sottocartella contiene: [] ############################## creato secondo_livello: ['secondo_livello'] Example Example/new Example/new/1262429441.M690618P6782Q1.robby-desktop Example/cur Example/tmp Example/.sottocartella Example/.sottocartella/.secondo_livello Example/.sottocartella/.secondo_livello/new Example/.sottocartella/.secondo_livello/maildirfolder Example/.sottocartella/.secondo_livello/cur Example/.sottocartella/.secondo_livello/tmp Example/.sottocartella/new Example/.sottocartella/maildirfolder Example/.sottocartella/cur Example/.sottocartella/tmp ############################## secondo_livello rimosso: [] Example Example/new Example/new/1262429441.M690618P6782Q1.robby-desktop Example/cur Example/tmp Example/.sottocartella Example/.sottocartella/new Example/.sottocartella/maildirfolder Example/.sottocartella/cur Example/.sottocartella/tmp
MH è un altro formato mailbox multi file, usato da alcuni gestori di mail. Babyl e MMDF sono formati a file singolo con separatori dei messaggi diversi rispetto a mbox. Nessuno di essi sembra essere altrettanto popolare di mbox o Maildir. I formati a file singolo supportano al stessa API di mbox, e MH include i metodi legati alle cartelle che si trovano nella classe Maildir.
Vedere anche: