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()