Enviar Emails con Python: smtplib, MIME y Adjuntos
Python incluye smtplib y email para enviar correos desde cualquier proveedor SMTP: Gmail, Outlook, SendGrid, servidor propio. Compatible con texto plano, HTML y archivos adjuntos.
Email de Texto Simple con smtplib
import smtplib
from email.mime.text import MIMEText
def enviar_email_simple(destinatario, asunto, cuerpo,
remitente, password, smtp_host="smtp.gmail.com", smtp_port=587):
msg = MIMEText(cuerpo, "plain", "utf-8")
msg["Subject"] = asunto
msg["From"] = remitente
msg["To"] = destinatario
with smtplib.SMTP(smtp_host, smtp_port) as servidor:
servidor.ehlo()
servidor.starttls()
servidor.login(remitente, password)
servidor.sendmail(remitente, [destinatario], msg.as_string())
print(f"Email enviado a {destinatario}")
# Gmail: usa contraseña de aplicación (no la de tu cuenta)
enviar_email_simple(
destinatario="cliente@ejemplo.com",
asunto="Tu pedido está listo",
cuerpo="Hola,\n\nTu pedido ha sido procesado correctamente.\n\nSaludos.",
remitente="miempresa@gmail.com",
password="abcd efgh ijkl mnop" # contraseña de app de 16 caracteres
)
Email HTML con Fallback de Texto
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def enviar_email_html(destinatario, asunto, html, texto_plano,
remitente, password):
msg = MIMEMultipart("alternative")
msg["Subject"] = asunto
msg["From"] = remitente
msg["To"] = destinatario
msg.attach(MIMEText(texto_plano, "plain", "utf-8"))
msg.attach(MIMEText(html, "html", "utf-8"))
with smtplib.SMTP("smtp.gmail.com", 587) as s:
s.starttls()
s.login(remitente, password)
s.sendmail(remitente, [destinatario], msg.as_string())
print(f"Email HTML enviado a {destinatario}")
html = """
<html><body>
<h2 style="color:#4a9eff">Tu Pedido #1234</h2>
<p>Tu pedido ha sido <strong>confirmado</strong> y está en camino.</p>
<a href="https://mitienda.com/pedidos/1234" style="background:#4a9eff;color:white;padding:10px 20px;text-decoration:none;border-radius:4px">Ver Pedido</a>
</body></html>
"""
texto = "Tu pedido #1234 ha sido confirmado.\nVer: https://mitienda.com/pedidos/1234"
enviar_email_html("cliente@ejemplo.com", "Pedido Confirmado", html, texto,
"mitienda@gmail.com", "mi_password_de_app")
Enviar con Archivo Adjunto
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os
def enviar_con_adjunto(destinatario, asunto, cuerpo, archivos_adjuntos,
remitente, password):
msg = MIMEMultipart()
msg["Subject"] = asunto
msg["From"] = remitente
msg["To"] = destinatario
msg.attach(MIMEText(cuerpo, "plain", "utf-8"))
for ruta_archivo in archivos_adjuntos:
with open(ruta_archivo, "rb") as f:
parte = MIMEBase("application", "octet-stream")
parte.set_payload(f.read())
encoders.encode_base64(parte)
nombre = os.path.basename(ruta_archivo)
parte.add_header("Content-Disposition", f'attachment; filename="{nombre}"')
msg.attach(parte)
with smtplib.SMTP("smtp.gmail.com", 587) as s:
s.starttls()
s.login(remitente, password)
s.sendmail(remitente, [destinatario], msg.as_string())
print(f"Email con {len(archivos_adjuntos)} adjuntos enviado a {destinatario}")
enviar_con_adjunto(
"cliente@ejemplo.com",
"Tu Factura",
"Adjuntamos tu factura del mes.",
["factura_abril.pdf", "resumen.xlsx"],
"miempresa@gmail.com",
"password_de_app"
)
Envío Masivo con Plantilla (Mailing)
import smtplib
from email.mime.text import MIMEText
import csv
def mailing_masivo(csv_contactos, asunto_tpl, cuerpo_tpl, remitente, password):
with open(csv_contactos, encoding="utf-8") as f:
contactos = list(csv.DictReader(f)) # columnas: nombre, email
enviados = 0
with smtplib.SMTP("smtp.gmail.com", 587) as servidor:
servidor.starttls()
servidor.login(remitente, password)
for c in contactos:
asunto = asunto_tpl.replace("{nombre}", c["nombre"])
cuerpo = cuerpo_tpl.replace("{nombre}", c["nombre"])
msg = MIMEText(cuerpo, "plain", "utf-8")
msg["Subject"] = asunto
msg["From"] = remitente
msg["To"] = c["email"]
try:
servidor.sendmail(remitente, [c["email"]], msg.as_string())
enviados += 1
print(f" [{enviados}] Enviado a {c['email']}")
except Exception as e:
print(f" ERROR {c['email']}: {e}")
print(f"Total enviados: {enviados}/{len(contactos)}")
mailing_masivo(
"clientes.csv",
"Hola {nombre}, tenemos novedades",
"Hola {nombre},\n\nTe escribimos para informarte sobre nuestras novedades.\n\nSaludos.",
"newsletter@miempresa.com",
"password_de_app"
)
Configuración para Diferentes Proveedores
| Proveedor | Host SMTP | Puerto | TLS |
|---|---|---|---|
| Gmail | smtp.gmail.com | 587 | STARTTLS |
| Outlook/Hotmail | smtp.office365.com | 587 | STARTTLS |
| Yahoo | smtp.mail.yahoo.com | 587 | STARTTLS |
| Amazon SES | email-smtp.us-east-1.amazonaws.com | 587 | STARTTLS |
| SendGrid | smtp.sendgrid.net | 587 | STARTTLS |
Recurso Adicional
Para convertir archivos adjuntos entre PDF, DOCX, JPG y otros formatos sin instalar nada, usa KaijuConverter — gratis y sin registro.
Conversiones relacionadas
Conversiones frecuentes del catálogo: