Email

Enviar correos electrónicos con Python

Python puede enviar correo sin instalar nada. La biblioteca estándar incluye smtplib para la conexión SMTP y email.message.EmailMessage para construir el mensaje, así que un script funcional ocupa unas quince líneas. A continuación está ese script con TLS configurado correctamente, y después el argumento para pasar a una HTTP API cuando aparezca tráfico real.

¿Cómo envías correo con la biblioteca estándar?

EmailMessage construye el mensaje y establece las cabeceras por ti. smtplib.SMTP_SSL abre una conexión cifrada en el puerto 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 escribe el cuerpo en texto plano y add_alternative adjunta la versión HTML, para que los clientes elijan lo que pueden renderizar. Enviar ambas partes es buena práctica y ayuda con la entregabilidad.

¿SSL o STARTTLS?

Existen dos rutas de cifrado y usan puertos distintos. SMTP_SSL en el 465 negocia TLS desde el primer byte. La alternativa es SMTP en texto plano en el 587 seguido de starttls(), que actualiza una conexión sin cifrar:

with smtplib.SMTP("smtp.example.com", 587) as server:
    server.starttls()
    server.login("smtp-user", "smtp-password")
    server.send_message(msg)

Elige según lo que soporte tu servidor de correo. No envíes credenciales por una conexión sin cifrar. Guarda el nombre de usuario y la contraseña en variables de entorno, leídas con os.environ, no escritas directamente en el código.

¿Cómo añades un archivo adjunto?

add_attachment recibe los bytes más un tipo MIME. Lee el archivo en modo binario:

with open("invoice.pdf", "rb") as f:
    msg.add_attachment(
        f.read(),
        maintype="application",
        subtype="pdf",
        filename="invoice-1042.pdf",
    )

¿Por qué dejar SMTP directo en producción?

El script funciona, pero en producción aparecen problemas que la biblioteca estándar no resuelve. Necesitas un servidor de correo con buena reputación de IP, registros SPF, DKIM y DMARC correctos, lógica de reintentos para fallos transitorios y una forma de ver los rebotes y las quejas. Una HTTP API integra todo eso. Te autenticas con una clave, envías JSON y lees respuestas estructuradas en lugar de analizar códigos de estado SMTP.

Envíalo con Bird

El Bird Python SDK envía el mismo mensaje sin la fontanería de 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>",
)

La dirección sandbox de delivered@bird.dev siempre acepta correo, así que la primera ejecución confirma tu clave y tu payload antes de apuntar a destinatarios reales. SDK devuelve un par (data, error), lo que mantiene el manejo de errores explícito en vez de capturar excepciones de SMTP. Si PHP es más tu lenguaje, la guía de PHPMailer cubre el equivalente en ese ecosistema.

Preguntas frecuentes

¿Necesito instalar algo para enviar correo en Python?

No. smtplib y email.message están en la biblioteca estándar, así que un envío básico con SMTP no requiere paquetes. Solo añades una dependencia cuando quieres un cliente de más alto nivel o una HTTP API.

¿Cuál es la diferencia entre el puerto 465 y el 587?

El puerto 465 espera TLS desde el inicio, que smtplib.SMTP_SSL gestiona. El puerto 587 comienza en texto plano y actualiza con starttls(). Ambos terminan cifrados; solo negocian el cifrado en momentos distintos.

¿Cuándo debería cambiar de smtplib a una API?

Cuando te importen la entregabilidad, los reintentos y el seguimiento de eventos. La biblioteca estándar envía un mensaje; no gestiona la reputación ni informa de lo que ocurrió tras la entrega. Una API como Bird email cubre esa capa.

Para la forma completa de la solicitud y la respuesta, la guía de envío de correo recorre la API de principio a fin.

Construye sobre la misma red.

Obtén una clave API de prueba de inmediato. El acceso a producción se desbloquea cuando añades un método de pago y verificas un remitente.

Tu próxima idea.
Lista para conectar.