Articolo originale: https://www.freecodecamp.org/news/send-emails-using-code-4fcea9df63f/

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:

  1. Imposta il sever SMTP e fai il log in nel tuo account.
  2. Crea l'oggetto del messaggio MIMEMultipart e caricalo con l'intestazione appropriata per i campi From (da), To (a) e Subject (Oggetto).
  3. Aggiungi il corpo del messaggio.
  4. 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
read_contacts.py hosted with ❤ by GitHub

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)
read_template.py hosted with ❤ by GitHub

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)
setup_smtp.py hosted with ❤ by GitHub

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
send_email.py hosted with ❤ by GitHub

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