Enviar correos automáticos con Python (SMTP)
Cómo enviar correos desde Python con smtplib: texto, HTML y adjuntos. Con la configuración real de Gmail y el paso de la contraseña de aplicación que a todos les falla la primera vez.
Enviar correos desde un script abre muchas puertas: avisos automáticos, reportes que llegan solos, notificaciones cuando algo termina. Python trae todo lo necesario en la librería estándar smtplib, sin instalar nada. La parte que de verdad cuesta no es el código, es la autenticación del proveedor. Vamos por ambas.
El obstáculo real: la contraseña de aplicación
Antes del código, esto, porque es donde falla el 90% de la gente. Gmail (y la mayoría de proveedores modernos) ya no te deja usar tu contraseña normal en un script por seguridad. Necesitas una “contraseña de aplicación”: una clave especial de 16 caracteres que generas para que la use el programa.
Para Gmail: activa la verificación en dos pasos en tu cuenta de Google, y luego ve a la sección de contraseñas de aplicaciones y genera una. Esa clave de 16 caracteres es la que usarás en el script, no tu contraseña habitual. Si intentas con la normal, el envío falla con un error de autenticación y te vuelves loco sin saber por qué. Este es el paso.
Enviar un correo de texto
import smtplib
from email.message import EmailMessage
remitente = "tucorreo@gmail.com"
clave_app = "xxxx xxxx xxxx xxxx" # la contraseña de aplicación
destinatario = "destino@ejemplo.com"
mensaje = EmailMessage()
mensaje["From"] = remitente
mensaje["To"] = destinatario
mensaje["Subject"] = "Correo de prueba desde Python"
mensaje.set_content("Hola, este correo lo envió un script de Python.")
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as servidor:
servidor.login(remitente, clave_app)
servidor.send_message(mensaje)
print("Correo enviado.")
La clase EmailMessage arma el correo con sus campos, y SMTP_SSL en el puerto 465 abre una conexión cifrada con Gmail. El with se encarga de cerrar la conexión sola al terminar.
Para otros proveedores solo cambia el servidor: Outlook usa smtp.office365.com, y cada servicio publica el suyo. La estructura del código es idéntica.
Enviar HTML
Si quieres un correo con formato (negritas, enlaces, colores) en vez de texto plano:
mensaje = EmailMessage()
mensaje["From"] = remitente
mensaje["To"] = destinatario
mensaje["Subject"] = "Reporte semanal"
# Versión texto (para clientes que no muestran HTML)
mensaje.set_content("Tu reporte está listo. Ábrelo en un cliente compatible con HTML.")
# Versión HTML
mensaje.add_alternative("""
<html>
<body>
<h2>Reporte semanal</h2>
<p>Todo funcionó <b>correctamente</b>.</p>
</body>
</html>
""", subtype="html")
El detalle importante: pones las dos versiones, texto y HTML. set_content da la de texto y add_alternative la de HTML. Los clientes de correo modernos muestran el HTML; los antiguos o los lectores de pantalla usan el texto. Enviar solo HTML es una mala práctica que además te puede mandar a spam.
Adjuntar un archivo
mensaje = EmailMessage()
mensaje["From"] = remitente
mensaje["To"] = destinatario
mensaje["Subject"] = "Reporte adjunto"
mensaje.set_content("Adjunto el reporte del mes.")
with open("reporte.pdf", "rb") as f:
mensaje.add_attachment(
f.read(),
maintype="application",
subtype="pdf",
filename="reporte.pdf",
)
add_attachment recibe los bytes del archivo (por eso open en modo "rb", binario) y necesita que le digas el tipo. Para un PDF es application/pdf; para una imagen PNG sería maintype="image", subtype="png". El filename es el nombre con que llegará al destinatario.
Un consejo de seguridad
Nunca escribas la contraseña de aplicación directamente en el código si vas a compartirlo o subirlo a GitHub. Cárgala desde una variable de entorno:
import os
clave_app = os.environ["CLAVE_APP_GMAIL"]
Así la clave vive fuera del código y no se filtra en el repositorio. Es la diferencia entre un script personal y uno que puedes compartir sin regalar el acceso a tu correo.
Con esto puedes automatizar cualquier envío: un reporte que sale cada lunes, un aviso cuando un proceso termina, una alerta cuando algo falla. Combínalo con el programador de tareas y tienes correos que se envían solos sin que toques nada.
¿Vas a enviar a muchos destinatarios o programar el envío automático? Escríbeme desde contacto y lo vemos.