Python può inviare email senza installare nulla. La libreria standard include smtplib per la connessione SMTP e email.message.EmailMessage per costruire il messaggio, quindi uno script funzionante è circa quindici righe. Di seguito quello script con TLS fatto correttamente, e poi il motivo per passare a un HTTP API quando arriva traffico reale.
Come si invia un'email con la libreria standard?
EmailMessage costruisce il messaggio e imposta gli header. smtplib.SMTP_SSL apre una connessione cifrata sulla porta 465:
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "you@yourdomain.com"
msg["To"] = "recipient@example.org"
msg["Subject"] = "Your receipt"
msg.set_content("Thanks for your order. This is the plain-text version.")
msg.add_alternative("<p>Thanks for your order.</p>", subtype="html")
with smtplib.SMTP_SSL("smtp.example.com", 465) as server:
server.login("smtp-user", "smtp-password")
server.send_message(msg)
set_content scrive il corpo in testo semplice e add_alternative allega la versione HTML, così i client scelgono cosa possono renderizzare. Inviare entrambe le parti è una buona pratica e aiuta con la deliverability.
SSL o STARTTLS?
Esistono due percorsi di cifratura e usano porte diverse. SMTP_SSL sulla 465 negozia TLS dal primo byte. L'alternativa è SMTP in chiaro sulla 587 seguita da starttls(), che aggiorna una connessione in chiaro:
with smtplib.SMTP("smtp.example.com", 587) as server:
server.starttls()
server.login("smtp-user", "smtp-password")
server.send_message(msg)
Scegli in base a ciò che il tuo mail server supporta. Non inviare credenziali su una connessione non cifrata. Tieni username e password in variabili d'ambiente, lette con os.environ, non scritte nel codice.
Come si aggiunge un allegato?
add_attachment accetta i byte più un tipo MIME. Leggi il file in modalità binaria:
with open("invoice.pdf", "rb") as f:
msg.add_attachment(
f.read(),
maintype="application",
subtype="pdf",
filename="invoice-1042.pdf",
)
Perché abbandonare SMTP raw per la produzione?
Lo script funziona, ma la produzione aggiunge problemi che la libreria standard non risolve. Serve un mail server con una reputazione IP pulita, record SPF, DKIM e DMARC corretti, logica di retry per errori transitori e un modo per vedere bounce e reclami. Un HTTP API integra tutto questo. Ti autentichi con una chiave, invii JSON e leggi risposte strutturate invece di analizzare codici di stato SMTP.
Inviare con Bird
L'Bird Python SDK invia lo stesso messaggio senza il plumbing SMTP:
import bird
client = bird.Bird(api_key=os.environ["BIRD_API_KEY"])
data, error = client.emails.send(
from_="you@yourdomain.com",
to="delivered@bird.dev",
subject="Hello from Python",
html="<p>It works.</p>",
)
L'indirizzo sandbox delivered@bird.dev accetta sempre la posta, quindi la prima esecuzione conferma la chiave e il payload prima di puntare a destinatari reali. SDK restituisce una coppia (data, error), che mantiene la gestione degli errori esplicita invece di catturare eccezioni SMTP. Se PHP è più il tuo linguaggio, il walkthrough di PHPMailer copre l'equivalente in quell'ecosistema.
FAQ
Devo installare qualcosa per inviare email in Python?
No. smtplib e email.message sono nella libreria standard, quindi un invio SMTP base non richiede pacchetti. Aggiungi una dipendenza solo quando vuoi un client di livello superiore o un HTTP API.
Qual è la differenza tra la porta 465 e la 587?
La porta 465 si aspetta TLS fin dall'inizio, cosa che smtplib.SMTP_SSL gestisce. La porta 587 parte in chiaro e aggiorna con starttls(). Entrambe finiscono cifrate; negoziano semplicemente in momenti diversi.
Quando conviene passare da smtplib a un API?
Quando ti interessano deliverability, retry e tracciamento degli eventi. La libreria standard invia un messaggio; non gestisce la reputazione né riporta cosa succede dopo la consegna. Un API come Bird email copre quel livello.
Per la struttura completa di richiesta e risposta, la guida all'invio email illustra API da cima a fondo.