2mail — SMTP relay su infrastruttura belga

SMTP per Python — posta dal tuo script o dalla tua app Django che arriva

Python ha SMTP integrato: con smtplib invii un messaggio in una manciata di righe, e Django lo racchiude in un proprio livello di posta con le impostazioni EMAIL. Ciò che nessuno dei due fornisce è la recapitabilità — quella dipende dal server attraverso cui invii.

Che tu abbia uno script isolato, un'app Flask o un progetto Django: le impostazioni sono gli stessi cinque dati. Li fai puntare al tuo relay e il codice che compone i messaggi resta invariato.

Perché senza relay le cose vanno storte

La posta di Python arriva spesso dal retro: un report notturno, un'attività cron che invia fatture, uno script che avvisa quando una misura esce dai margini. Nessuno ci sta guardando — e quindi nessuno si accorge che il server ricevente le rifiuta in silenzio. Con Django si aggiunge la classica sorpresa del passaggio in produzione: in sviluppo tutto va alla console, in produzione verso provider reali che controllano davvero la reputazione.

Configurare l'SMTP in Python

1

Recupera i dati

Accedi al tuo account 2mail e recupera lì il tuo server SMTP, il nome utente e la password.

2

Inserisci in Python

In un progetto Django imposti le impostazioni EMAIL nei settings: il backend SMTP come backend di posta, l'host del relay, la porta 587, l'opzione STARTTLS attiva, nome utente e password e un indirizzo mittente predefinito sul tuo dominio. Se lavori direttamente con smtplib, ti connetti all'host sulla porta 587, chiami starttls, effettui l'accesso con nome utente e password e invii poi il messaggio. In entrambi i casi leggi i dati da variabili d'ambiente, non dal codice.

3

Autentica il dominio

Assicurati che SPF, DKIM e DMARC siano configurati correttamente per il tuo dominio, così i destinatari possono verificare che il messaggio provenga da te.

4

Prova

Invia dalla tua piattaforma un messaggio di prova a un indirizzo presso un grande provider e verifica che arrivi nella posta in arrivo e non nella cartella spam.

I campi richiesti da Python

Ogni piattaforma li chiama in modo leggermente diverso, ma si tratta sempre degli stessi cinque. I valori concreti sono legati al tuo account e li trovi nel tuo account 2mail — recuperali da lì, così sei certo di usare quelli giusti.

Campo Che cosa inserire
Server SMTP (host)Il nome del server dal tuo account 2mail.
PortaLa porta corrispondente alla cifratura scelta; il tuo account indica quale.
CifraturaTLS. Non inviare mai in chiaro — altrimenti le tue credenziali viaggiano leggibili sulla rete.
Nome utenteIl login SMTP del tuo account 2mail.
PasswordLa password corrispondente. Non usare mai la password della casella di posta di un collaboratore.

Configurazione SMTP per Python nel codice

Esempi funzionanti per la porta 587 con STARTTLS, pronti da copiare. Sostituisci l'indirizzo mittente con un indirizzo del tuo dominio e verifica nome del server e login nel tuo account 2mail. La password va in una variabile d'ambiente — mai nel codice e mai nel controllo di versione.

smtplib: connettersi sulla 587 con starttls()

La libreria standard è sufficiente. L'ordine conta: prima starttls(), e solo dopo login() — altrimenti la tua password passa in chiaro sulla linea, oppure il relay rifiuta l'autenticazione. Usa smtplib.SMTP e non SMTP_SSL: quest'ultimo va con la porta 465. Nome utente e password arrivano da variabili d'ambiente.

import os
import smtplib
import ssl
from email.message import EmailMessage

msg = EmailMessage()
msg["From"] = "Example <noreply@example.com>"
msg["To"] = "you@example.org"
msg["Subject"] = "SMTP test"
msg.set_content("Sent through the 2mail SMTP relay.")

context = ssl.create_default_context()

with smtplib.SMTP("relay.2mail.eu", 587, timeout=10) as server:
    server.starttls(context=context)  # upgrade to TLS first, log in afterwards
    server.login(os.environ["SMTP_USERNAME"], os.environ["SMTP_PASSWORD"])
    server.send_message(msg)          # call again for the next message, same connection

Django: le impostazioni EMAIL_*

Django non ha bisogno di alcun pacchetto aggiuntivo. Imposta il backend SMTP in modo esplicito: in sviluppo è spesso impostato sul backend console, e allora la produzione non invia nulla mentre tutto sembra funzionare. sendtestemail è un comando di gestione integrato con cui controlli le impostazioni senza dover richiamare una view o un task.

# settings.py
import os

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "relay.2mail.eu"
EMAIL_PORT = 587
EMAIL_USE_TLS = True   # STARTTLS - never together with EMAIL_USE_SSL
EMAIL_HOST_USER = os.environ["SMTP_USERNAME"]
EMAIL_HOST_PASSWORD = os.environ["SMTP_PASSWORD"]
EMAIL_TIMEOUT = 10
DEFAULT_FROM_EMAIL = "Example <noreply@example.com>"
SERVER_EMAIL = "noreply@example.com"   # sender of error reports to ADMINS

# Test from the shell:
#   python manage.py sendtestemail you@example.org

Flask-Mail: gli stessi cinque dati

Se lavori con Flask, Flask-Mail chiede gli stessi dati con altri nomi. Anche qui vale la stessa regola: MAIL_USE_TLS per la porta 587, e MAIL_USE_SSL resta disattivato.

import os
from flask import Flask
from flask_mail import Mail

app = Flask(__name__)
app.config.update(
    MAIL_SERVER="relay.2mail.eu",
    MAIL_PORT=587,
    MAIL_USE_TLS=True,    # STARTTLS
    MAIL_USE_SSL=False,
    MAIL_USERNAME=os.environ["SMTP_USERNAME"],
    MAIL_PASSWORD=os.environ["SMTP_PASSWORD"],
    MAIL_DEFAULT_SENDER="noreply@example.com",
)
mail = Mail(app)

Quali e-mail invia Python

Una volta configurato il relay, tutte queste passano tramite 2mail — non devi configurarle una per una.

Recupero password e verifica e-mail da Django
Report ed esportazioni pianificati da attività cron
Avvisi da script di monitoraggio e di elaborazione dati
Fatture e conferme da un'applicazione web
Report di errore agli amministratori

Insidie con Python

Opzione TLS e porta devono coincidere

Django prevede due impostazioni TLS separate: una per STARTTLS e una per TLS fin dall'inizio. Attiva solo l'impostazione STARTTLS; è quella corrispondente alla porta 587. Attivarle entrambe genera un errore di configurazione; non attivarne nessuna invia le tue credenziali in chiaro, e un relay giustamente lo rifiuta.

Una connessione per serie, non per messaggio

Uno script che apre una nuova connessione SMTP per ciascuno di mille messaggi si comporta come un aggressore. Apri una connessione, invia la serie, chiudi. Django dispone di una funzione per inviare più messaggi su una sola connessione.

Errori silenziosi nelle attività in background

Un'eccezione in un'attività cron sparisce in un file di log che nessuno legge. Intercetta gli errori di invio e segnalali dove si notano — e collega i webhook di 2mail per recapito e bounce, così vedi anche ciò che va storto <em>dopo</em> la consegna.

Messaggi di errore frequenti con Python

I messaggi che compaiono quando host, porta, cifratura o login non sono corretti — riportati alla lettera, così li riconosci nel tuo log, con accanto la causa e la soluzione.

Messaggio Causa Soluzione
smtplib.SMTPAuthenticationError: (535, b'5.7.8 Error: authentication failed: …') Il relay rifiuta le credenziali: nome utente o password errati, oppure una variabile d'ambiente che nel contesto di cron o del servizio ha un valore diverso rispetto alla tua shell. Stampa ciò che il processo legge effettivamente (il nome utente, mai la password) e usa il login SMTP del tuo account 2mail — non la password di una casella di posta.
smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server. login() viene chiamato prima di starttls(). Un relay offre l'autenticazione solo quando la connessione è cifrata; sulla connessione ancora in chiaro AUTH quindi non esiste. Chiama prima server.starttls(context=context) e solo dopo server.login(…). In Django: imposta EMAIL_USE_TLS = True.
ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:…) Il codice usa smtplib.SMTP_SSL (oppure, in Django, EMAIL_USE_SSL) sulla porta 587. Python inizia allora subito con un handshake TLS, mentre su quella porta il relay si aspetta prima SMTP semplice e passa a TLS solo dopo STARTTLS. La classica confusione tra 465 e 587. Usa smtplib.SMTP(…, 587) seguito da starttls(), oppure in Django EMAIL_USE_TLS = True con la porta 587.
smtplib.SMTPServerDisconnected: Connection unexpectedly closed La connessione è caduta prima o durante il dialogo. Di solito si tratta di uno script che tiene aperta una connessione e la riutilizza dopo una lunga pausa, mentre nel frattempo il server l'ha chiusa per inattività — oppure di una normale connessione SMTP verso una porta che si aspetta TLS dal primo byte. Apri una connessione per ogni serie di messaggi e chiudila al termine; intercetta l'eccezione e riconnettiti. Verifica di usare la porta 587 con starttls().
ValueError: EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so only set one of those settings to True. Nei settings di Django sono attive entrambe le opzioni TLS — spesso perché una arriva da un file di base condiviso e l'altra dai settings di produzione. Lascia soltanto EMAIL_USE_TLS = True e imposta EMAIL_USE_SSL = False.
SPF, DKIM e DMARC spiegati La recapitabilità

Un'altra piattaforma?

L'SMTP è un protocollo standard: ogni sistema che parla SMTP — un CRM, un ERP, un'applicazione proprietaria o un server — può inviare tramite 2mail con gli stessi cinque campi.

Domande frequenti sull'SMTP per Python

smtplib e Django inviano, ma non forniscono recapitabilità: quella dipende dal server attraverso cui invii. Una funzione mail locale o un server appena creato non ha autenticazione né reputazione. Un SMTP relay con record SPF, DKIM e DMARC corretti risolve la cosa.
Il backend SMTP come backend di posta, l'host del relay, la porta 587, l'opzione STARTTLS attiva, il tuo nome utente e la tua password e un indirizzo mittente predefinito sul tuo dominio. Conserva le credenziali in variabili d'ambiente, non nei settings.
Connettiti all'host sulla porta 587, richiama starttls, effettua l'accesso con nome utente e password e invia il messaggio. Per più messaggi usa la stessa connessione invece di aprirne una nuova per ciascuno.
Nel tuo account 2mail, per ogni applicazione. Sono legati all'account, quindi non li pubblichiamo sul sito. Crea preferibilmente credenziali proprie per ogni script o applicazione, così puoi revocarle a parte e seguire quel traffico separatamente.
Trust Guard Security Scanned
Chiama ora
Invia un'e-mail