Ecco alcuni esempi su come usare il package email per leggere, scrivere ed inviare semplici messaggi di posta elettronica, così come complessi messaggi MIME.
Iniziamo col vedere come creare e inviare un semplice messaggio di testo:
# importa smtplib per l'attuale funzione di invio import smtplib # importa i moduli email necessari from email.MIMEText import MIMEText # Apre un file di testo per la lettura. Per questo esempio supponiamo #+ che il file di testo contenga solo caratteri ASCII. fp = open(textfile, 'rb') # Crea un messaggio in puro testo msg = MIMEText(fp.read()) fp.close() # me == indirizzo di chi invia l'email # you == indirizzo di chi riceve l'email msg['Subject'] = 'The contents of %s' % textfile msg['From'] = me msg['To'] = you # Invia il messaggio tramite il nostro server SMTP ma non include #+ l'intestazione della busta. s = smtplib.SMTP() s.connect() s.sendmail(me, [you], msg.as_string()) s.close()
Ecco un esempio di come inviare un messaggio MIME contenente un gruppo di foto di famiglia che possono essere recuperate in una directory:
# importa smtplib per l'attuale funzione di invio import smtplib # Ecco i moduli del package email di cui abbiamo bisogno from email.MIMEImage import MIMEImage from email.MIMEMultipart import MIMEMultipart COMMASPACE = ', ' # Crea il messaggio email contenitore (outer). msg = MIMEMultipart() msg['Subject'] = 'Our family reunion' # me == indirizzo email di chi invia # family = la lista di tutti gli indirizzi email destinatari msg['From'] = me msg['To'] = COMMASPACE.join(family) msg.preamble = 'Our family reunion' # Fa in modo che il messaggio termini con un fine riga msg.epilogue = '' # Si presume che i file di immagine siano tutti in formato PNG for file in pngfiles: # Apre i file in modo binario. Lascia che la classe MIMEImage #+ automaticamente individui il tipo di immagine specifico. fp = open(file, 'rb') img = MIMEImage(fp.read()) fp.close() msg.attach(img) # Invia l'email tramite il nostro server SMTP. s = smtplib.SMTP() s.connect() s.sendmail(me, family, msg.as_string()) s.close()
Ecco un esempio di come inviare l'intero contenuto di una directory come messaggio email: 12.4
#!/usr/bin/env python """Invia il contenuto di una directory come messaggio MIME. Uso: dirmail [opzioni] from to [to ...]* Opzioni: -h / --help Stampa questo messaggio ed esce. -d directory --directory=directory Invia il contenuto della directory specificata altrimenti usa la directory corrente. Vengono inviati solo i file regolari della directory e non vengono coinvolte le sotto directory. `from' è l'indirizzo email di chi invia il messaggio. `to' è l'indirizzo email del destinatario del messaggio. Possono essere passati più destinatari. L'email viene inviata tramite inoltro al vostro server SMTP locale che quindi esegue il normale processo di consegna. La vostra macchina locale deve avere in esecuzione un server SMTP. """ import sys import os import getopt import smtplib # Per l'individuazione del tipo MIME in base a nome e estensione del file import mimetypes from email import Encoders from email.Message import Message from email.MIMEAudio import MIMEAudio from email.MIMEBase import MIMEBase from email.MIMEMultipart import MIMEMultipart from email.MIMEImage import MIMEImage from email.MIMEText import MIMEText COMMASPACE = ', ' def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) except getopt.error, msg: usage(1, msg) dir = os.curdir for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-d', '--directory'): dir = arg if len(args) < 2: usage(1) sender = args[0] recips = args[1:] # Crea il messaggio contenitore (outer) outer = MIMEMultipart() outer['Subject'] = 'Contents of directory %s' % os.path.abspath(dir) outer['To'] = COMMASPACE.join(recips) outer['From'] = sender outer.preamble = 'You will not see this in a MIME-aware mail reader.\n' # Fa in modo che il messaggio termini con un fine riga outer.epilogue = '' for filename in os.listdir(dir): path = os.path.join(dir, filename) if not os.path.isfile(path): continue # Individua il tipo del contenuto in base all'estensione del #+ file. La codifica verrà ignorata, anche se dovremmo effettuare #+ un controllo su cosette come file compressi e gzip. ctype, encoding = mimetypes.guess_type(path) if ctype is None or encoding is not None: # Non si capisce il tipo o il file è codificato (compresso) #+ quindi si usa un generico tipo bag-of-bits. ctype = 'application/octet-stream' maintype, subtype = ctype.split('/', 1) if maintype == 'text': fp = open(path) # Notate: dovrebbe gestire la tipologia del carattere usato msg = MIMEText(fp.read(), _subtype=subtype) fp.close() elif maintype == 'image': fp = open(path, 'rb') msg = MIMEImage(fp.read(), _subtype=subtype) fp.close() elif maintype == 'audio': fp = open(path, 'rb') msg = MIMEAudio(fp.read(), _subtype=subtype) fp.close() else: fp = open(path, 'rb') msg = MIMEBase(maintype, subtype) msg.set_payload(fp.read()) fp.close() # Codifica il carico utile usando Base64 Encoders.encode_base64(msg) # Imposta il parametro del nome del file msg.add_header('Content-Disposition', 'attachment', filename=filename) outer.attach(msg) # Adesso invia il messaggio s = smtplib.SMTP() s.connect() s.sendmail(sender, recips, outer.as_string()) s.close() if __name__ == '__main__': main()
Infine, ecco un esempio di come scompattare un messaggio MIME come il precedente, in una directory di file:
#!/usr/bin/env python """Scompatta un messaggio MIME in una directory di file. Uso: unpackmail [opzioni] msgfile Opzioni: -h / --help stampa questo messaggio ed esce. -d directory --directory=directory Scompatta il messaggio MIME nella directory indicata che verrà creata se non già esistente. msgfile è il percorso del file che contiene il messaggio MIME. """ import sys import os import getopt import errno import mimetypes import email def usage(code, msg=''): print >> sys.stderr, __doc__ if msg: print >> sys.stderr, msg sys.exit(code) def main(): try: opts, args = getopt.getopt(sys.argv[1:], 'hd:', ['help', 'directory=']) except getopt.error, msg: usage(1, msg) dir = os.curdir for opt, arg in opts: if opt in ('-h', '--help'): usage(0) elif opt in ('-d', '--directory'): dir = arg try: msgfile = args[0] except IndexError: usage(1) try: os.mkdir(dir) except OSError, e: # Ignora l'errore che evidenzia l'esistenza della directory if e.errno <> errno.EEXIST: raise fp = open(msgfile) msg = email.message_from_file(fp) fp.close() counter = 1 for part in msg.walk(): # multipart/* sono semplici contenitori if part.get_content_maintype() == 'multipart': continue # Le applicazioni dovrebbero veramente controllare a fondo il #+ nome del file fornito, in modo che il messaggio di posta #+ elettronica non possa essere usato per sovrascrivere file #+ importanti filename = part.get_filename() if not filename: ext = mimetypes.guess_extension(part.get_type()) if not ext: # Use a generic bag-of-bits extension ext = '.bin' filename = 'part-%03d%s' % (counter, ext) counter += 1 fp = open(os.path.join(dir, filename), 'wb') fp.write(part.get_payload(decode=1)) fp.close() if __name__ == '__main__': main()