15 agosto 2016, un pezzo di 14 minuti di Dev Mukherjee
La maggior parte dei servizi Internet ha bisogno di inviare email ai propri utenti. La costruzione del messaggio è un compito separato dall’invio dell’email. Questo post dimostra la corretta costruzione di messaggi Multipurpose Internet Mail Extensions (MIME) in Python.
I messaggi MIME hanno molti sottotipi per incapsulare diversi tipi di contenuto. La libreria MIME di Python fornisce dei wrapper per lavorare con essi. Esploreremo i seguenti sottotipi per dimostrare come confezionare correttamente i messaggi:
-
mixed
usato per inviare contenuti di diverso tipo, in linea o come allegati -
alternative
usato per inviare versioni alternative dello stesso contenuto, per esempio raggruppare il testo semplice e le versioni HTML di un corpo di email -
related
usato per includere risorse correlate in linea o come allegati, per esempio immagini usate nel contenuto HTML
Il messaggio email che creeremo in questo post conterrà:
- Versioni HTML e testo semplice del contenuto del corpo
- Un file allegato (che in questo caso è un file generato
ICS
) - Optionally have an image in the HTML content
Iniziamo a creare un messaggio MIME mixed
multipart che ospiterà i vari componenti (corpo della mail, immagini visualizzate in linea e allegati scaricabili) del nostro messaggio:
from email.mime.multipart import MIMEMultipart# By default the type is set to mixedmessage = MIMEMultipart()message = "Hello World"message = "Anomaly Support <[email protected]>"message = "Anomaly Reception <[email protected]>"# If a Reply-To is explicitly provided then the email client will# use this address when the user hit the reply button message = "Anomaly Support <[email protected]>"
HTML e contenuto del corpo del testo semplice
Creeremo un messaggio alternative
che ha due allegati, il primo contenente la versione di testo semplice del messaggio email seguito dalla versione HTML.
Il contenuto HTML e quello testuale sarebbero tipicamente prodotti con l’assistenza di un motore di template. Per gli scopi di questo post assumo che tu abbia già generato il contenuto e che sia disponibile come variabile Python str
.
Il messaggio alternative
viene creato istanziando un oggetto MIMEMultipart
, questa volta chiedendo al costruttore di usare il sottotipo alternative
.
textual_message = MIMEMultipart('alternative')
Usa l’helper MIMEText
per creare gli allegati di testo semplice e HTML.
from email.mime.text import MIMEText# I assume that you have a variable called txt_content# with the textual rendition of the message, this could# have been generated via a templating engineplaintext_part = MIMEText(txt_content, 'plain')textual_message.attach(plaintext_part)# likewise a variable called html_content with the HTMLhtml_part = MIMEText(html_content, 'html')textual_message.attach(html_part)
Attacca il messaggio alternative
al messaggio padre mixed
per creare il corpo testuale del messaggio e-mail.
# Attach this to the mixed type messagemessage.attach(textual_message)
Allegato scaricabile
File testuali o binari possono essere allegati alla tua e-mail usando l’helper MIMEApplication
. Viene istanziato con il contenuto dell’allegato seguito dal tipo MIME dell’allegato, cioè per un application/pdf
si fornisce la porzione pdf
.
Di default il contenuto sarebbe contenuto in linea. Per renderlo un allegato, usate il metodo add_header
sull’istanza MIMEApplication
e dichiarate che è un allegato. Poiché il contenuto dell’allegato è ora parte di un messaggio codificato, è necessario fornire esplicitamente meta informazioni come un nome di file.
from email.mime.application import MIMEApplicationpdf_file = MIMEApplication(pdf_file_data, "pdf")pdf_file.add_header('Content-Disposition', 'attachment', filename='report.pdf')
L’helper MIMEApplication
codifica automaticamente Base64
i contenuti quando sono allegati ai messaggi:
message.attach(pdf_file)
Immagine opzionale da usare nel corpo HTML
Considera un’immagine che vuoi mostrare nel corpo della mail ma che non vuoi offrire al destinatario per il download. Avresti bisogno di usare un messaggio related
per avvolgere il corpo dell’email contenuto nel messaggio alternate
che abbiamo creato prima e allegare il messaggio related
al messaggio originale mixed
.
Ti servirà anche l’uso della sottoclasse MIMEImage
per assicurarti che l’immagine sia codificata correttamente. Per prima cosa, crea un messaggio MIMEMultipart
del sottotipo related
:
related_message = MIMEMultipart('related')
Crea un’istanza di MIMEImage
che conterrà il contenuto dell’immagine:
from email.MIMEImage import MIMEImage# Content of an image that relates to the HTML messageimage = MIMEImage(image_binary_contents)# Lets you reference the image locally in HTMLimage.add_header('Content-ID', '<image1>')
Aggiungendo un’intestazione Content-ID
potrai fare riferimento all’immagine nel contenuto HTML come <img src="cid:image1">
. Attacca il messaggio alternate
creato originariamente al messaggio related
seguito dall’istanza MIMEImage
:
# Attach the alternative textural message to the # related messagerelated_message.attach(textual_message)# Attach the image to the related messagerelated_message.attach(image)
Finalmente attacca il messaggio related
al messaggio mixed
:
# Attach the related message to our parent messagemessage.attach(related_message)
Codifica e invio dell’e-mail
Una volta che hai mescolato e abbinato vari tipi e sottotipi MIME
, il tuo messaggio può essere codificato chiamando la funzione as_string
. Questa, a sua volta, chiede ad ogni sottomessaggio e allegato di rendersi come un messaggio coerente. Il risultato è la stringa che puoi inviare tramite SMTP
come email.
encoded_email = message.as_string()
smtplib
fornisce un client SMTP
che può consegnare questo messaggio per te. È abbastanza semplice. A seconda della vostra applicazione e della configurazione del server, potete scegliere di usare relay locali o relay direttamente a un server SMTP disponibile. Lo lascerò alle esigenze specifiche delle vostre applicazioni.
from smtplib import SMTPsmtp = SMTP("localhost", 25)smtp.sendmail(message, message, encoded_email)smtp.quit()
Nota: La direttiva Reply-To
non è parte del payload SMTP; è gestita come parte del messaggio MIME
.