Articolo originale: Send Emails Using Python
Come esercizio di apprendimento, mi sono recentemente immerso in Python 3 per trovare un modo per inviare email. Probabilmente ci sono dei metodi più diretti per svolgere questa operazione, ma quello che ti illustrerò per me funziona bene.
Ecco la situazione: hai i nomi e gli indirizzi email di alcuni contatti, e vuoi inviare un messaggio a ognuno di loro scrivendo "Caro [nome]" all'inizio del messaggio.
Per semplicità, puoi immagazzinare i dettagli dei contatti in un file, piuttosto che in un database e puoi conservare in un file anche il modello del messaggio che vorresti inviare.
Il modulo di Python smtplib è praticamente tutto ciò di cui hai bisogno per inviare semplici email senza oggetto o informazioni aggiuntive. Ma per le email reali ti occorre un oggetto e molte altre informazioni - magari anche foto e allegati.
Ed è qui che il pacchetto email di Python entra in gioco. Tieni a mente che non è possibile inviare una email usando il pacchetto email da solo, ma ti occorrono sia email
che smtplib
.
Controlla anche la documentazione ufficiale di entrambi.
Ecco i quattro step di base per inviare email con Python:
- Imposta il sever SMTP e fai il log in nel tuo account.
- Crea l'oggetto del messaggio
MIMEMultipart
e caricalo con l'intestazione appropriata per i campiFrom
(da),To
(a) eSubject
(Oggetto). - Aggiungi il corpo del messaggio.
- Invia il messaggio usando l'oggetto SMTP server.
Adesso analizziamo tutto il processo.
Diciamo che il tuo file dei contatti mycontacts.txt
ha il seguente contenuto:
user@computer ~ $ cat mycontacts.txt
john johndoe@example.com
katie katie2016@example.com
Ogni riga rappresenta un singolo contatto, in cui il nome è seguito dall'indirizzo email, tutto scritto in minuscolo. Farò in modo che sia la logica di programmazione a convertire ogni campo in maiuscolo dove necessario. Tutto questo è piuttosto semplice in Python.
Poi, abbiamo il file message.txt
, contenente il modello del messaggio:
user@computer ~ $ cat message.txt
Dear ${PERSON_NAME},
This is a test message.
Have a great weekend!
Yours Truly
Nota il codice ${PERSON_NAME}
. Questo è un template di stringa in Python. I template di stringa possono essere sostituiti facilmente con altre stringhe; in quest'esempio, ${PERSON_NAME}
verrà sostituito con il nome reale della persona, come vedremo a breve.
Adesso iniziamo col codice Python. Prima di tutto, dobbiamo leggere i contatti dal file mycontacts.txt
. Potremmo generalizzare questa parte con una funzione.
# Function to read the contacts from a given contact file and return a
# list of names and email addresses
def get_contacts(filename):
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
La funzione get_contacts()
accetta il nome di un file come argomento. Apre il file leggendo ogni riga (ogni contatto), divide nome ed email e li aggiunge in due liste separate. Infine, restituisce le due liste.
Abbiamo anche bisogno di una funzione per leggere il file template (come message.txt
) e restituire un oggetto Template
con il suo contenuto.
from string import Template
def read_template(filename):
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
Proprio come la funzione precedente, anche questa accetta un file come argomento.
Per inviare un'email, hai bisogno di usare il protocollo SMTP (Simple Mail Transfer Protocol). Come menzionato in precedenza, Python fornisce delle librerie per gestire questa operazione.
# import the smtplib module. It should be included in Python by default
import smtplib
# set up the SMTP server
s = smtplib.SMTP(host='your_host_address_here', port=your_port_here)
s.starttls()
s.login(MY_ADDRESS, PASSWORD)
Il frammento di codice qui sopra, importa smtplib
e poi crea l'stanza SMTP che racchiude una connessione SMTP. Accetta come parametro l'indirizzo dell'host e il numero port, da entrambi i quali dipendono le impostazioni del SMPT del tuo particolare provider del servizio email. Ad esempio, nel caso di Outlook, la riga 4 sarebbe:
s = smtplib.SMTP(host='smtp-mail.outlook.com', port=587)
Dovresti usare l'indirizzo dell'host e il numero port del tuo provider di servizio email durante tutta l'operazione.
MY_ADDRESS
e PASSWORD
qui sopra, sono due variabili che contengono l'indirizzo email completo e la password dell'account che stai per utilizzare.
Questo è un ottimo momento per recuperare l'informazione di contatto e il modello dei messaggi da usare nelle funzioni che abbiamo definito precedentemente.
names, emails = get_contacts('mycontacts.txt') # read contacts
message_template = read_template('message.txt')
Per ognuno di questi contatti, inviamo un'email separatamente.
# import necessary packages
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# For each contact, send the email:
for name, email in zip(names, emails):
msg = MIMEMultipart() # create a message
# add in the actual person name to the message template
message = message_template.substitute(PERSON_NAME=name.title())
# setup the parameters of the message
msg['From']=MY_ADDRESS
msg['To']=email
msg['Subject']="This is TEST"
# add in the message body
msg.attach(MIMEText(message, 'plain'))
# send the message via the server set up earlier.
s.send_message(msg)
del msg
Per ogni nome ed email (dal file dei contatti), stai creando un oggetto MIMEMultipart, impostando le intestazioni dei contenuti di tipo From
, To
e Subject
come delle parole chiave di un dizionario, e poi aggiungendo il corpo del messaggio all'oggetto MIMEMultipart come semplice testo. Potresti voler leggere la documentazione per trovare altre informazioni su altri MIME con cui fare qualche prova.
Nota che nella riga 10, stiamo sostituendo ${PERSON_NAME}
con il nome reale estratto dal file dei contatti usando un meccanismo template in Python.
In questo particolare esempio, sto cancellando l'oggetto MIMEMultipart
e ri-creandolo ogni volta che itero attraverso il loop.
Una volta fatto questo, puoi inviare il messaggio usando la funzione send_message() dell'oggetto SMTP precedentemente creato.
Ecco il codice completo:
import smtplib
from string import Template
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
MY_ADDRESS = 'my_address@example.comm'
PASSWORD = 'mypassword'
def get_contacts(filename):
"""
Return two lists names, emails containing names and email addresses
read from a file specified by filename.
"""
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
def read_template(filename):
"""
Returns a Template object comprising the contents of the
file specified by filename.
"""
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
def main():
names, emails = get_contacts('mycontacts.txt') # read contacts
message_template = read_template('message.txt')
# set up the SMTP server
s = smtplib.SMTP(host='your_host_address_here', port=your_port_here)
s.starttls()
s.login(MY_ADDRESS, PASSWORD)
# For each contact, send the email:
for name, email in zip(names, emails):
msg = MIMEMultipart() # create a message
# add in the actual person name to the message template
message = message_template.substitute(PERSON_NAME=name.title())
# Prints out the message body for our sake
print(message)
# setup the parameters of the message
msg['From']=MY_ADDRESS
msg['To']=email
msg['Subject']="This is TEST"
# add in the message body
msg.attach(MIMEText(message, 'plain'))
# send the message via the server set up earlier.
s.send_message(msg)
del msg
# Terminate the SMTP session and close the connection
s.quit()
if __name__ == '__main__':
main()
Ed ecco fatto! Credo che adesso il codice sia abbastanza chiaro.
Sentiti libero di copiarlo e adattarlo alle tue necessità.
Buona programmazione :)