Configuración del backend de email
# settings.py
# Desarrollo: imprime en consola (no envía emails reales)
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# Desarrollo: guarda emails como archivos
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = BASE_DIR / 'emails'
# Producción con SMTP (Gmail como ejemplo)
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
DEFAULT_FROM_EMAIL = 'CertiTienda <noreply@certitienda.com>'
SERVER_EMAIL = 'errors@certitienda.com' # Para errores del servidor

send_mail() para emails simples
from django.core.mail import send_mail, send_mass_mail
# Email de texto plano
send_mail(
subject='Bienvenido a CertiTienda',
message='Gracias por registrarte. Tu cuenta ha sido creada correctamente.',
from_email='noreply@certitienda.com',
recipient_list=['usuario@ejemplo.com'],
fail_silently=False, # Lanzar excepción si falla
)
# Envío masivo eficiente (una sola conexión SMTP)
mensajes = [
('Confirmación de pedido #001', 'Tu pedido ha sido confirmado.', None, ['cliente1@ejemplo.com']),
('Confirmación de pedido #002', 'Tu pedido ha sido confirmado.', None, ['cliente2@ejemplo.com']),
]
send_mass_mail(mensajes, fail_silently=False)
EmailMessage para emails avanzados
from django.core.mail import EmailMessage, EmailMultiAlternatives
# Email con adjunto
def enviar_factura(pedido):
email = EmailMessage(
subject=f'Factura del pedido #{pedido.id}',
body='Adjuntamos la factura de tu pedido reciente.',
from_email='facturacion@certitienda.com',
to=[pedido.cliente.email],
cc=['contabilidad@certitienda.com'],
reply_to=['soporte@certitienda.com'],
)
# Añadir adjunto desde archivo
with open(f'/facturas/pedido_{pedido.id}.pdf', 'rb') as f:
email.attach(f'factura_{pedido.id}.pdf', f.read(), 'application/pdf')
email.send(fail_silently=False)
Email HTML con alternativa de texto
from django.template.loader import render_to_string
from django.utils.html import strip_tags
def enviar_bienvenida(usuario):
"""Envía email de bienvenida con versión HTML y texto plano."""
contexto = {
'nombre': usuario.get_full_name() or usuario.username,
'username': usuario.username,
'url_activacion': f'https://certitienda.com/activar/{usuario.profile.token}',
}
# Renderizar plantillas
html_content = render_to_string('emails/bienvenida.html', contexto)
text_content = strip_tags(html_content) # Versión texto plano automática
email = EmailMultiAlternatives(
subject='Bienvenido a CertiTienda 🎉',
body=text_content, # Versión texto plano
from_email=None, # Usa DEFAULT_FROM_EMAIL
to=[usuario.email],
)
email.attach_alternative(html_content, 'text/html') # Versión HTML
email.send()
# Plantilla HTML del email
# templates/emails/bienvenida.html
<!-- templates/emails/bienvenida.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; }
.header { background: #0b4b33; color: white; padding: 20px; }
.content { padding: 20px; }
.button { background: #0b4b33; color: white; padding: 12px 24px; text-decoration: none; }
</style>
</head>
<body>
<div class="header">
<h1>Bienvenido a CertiTienda</h1>
</div>
<div class="content">
<p>Hola {{ nombre }},</p>
<p>Tu cuenta con el usuario <strong>{{ username }}</strong> ha sido creada correctamente.</p>
<p>Por favor, activa tu cuenta haciendo clic en el siguiente enlace:</p>
<a class="button" href="{{ url_activacion }}">Activar cuenta</a>
<p>Si no solicitaste este registro, ignora este correo.</p>
</div>
</body>
</html>
Envío asíncrono con Celery
Para no bloquear la respuesta de la vista mientras se envía el email:
# tasks.py (Celery)
from celery import shared_task
from django.core.mail import send_mail
@shared_task(bind=True, max_retries=3)
def enviar_email_async(self, asunto, mensaje, destinatarios):
try:
send_mail(asunto, mensaje, None, destinatarios)
except Exception as exc:
raise self.retry(exc=exc, countdown=60)
# En la vista
def registro(request):
# ... guardar usuario ...
enviar_email_async.delay(
'Bienvenido',
f'Hola {usuario.username}!',
[usuario.email]
)
return redirect('dashboard')
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Configurar el backend de email en settings.py para desarrollo y producción. Enviar emails simples con send_mail() y send_mass_mail(). Usar EmailMessage para emails con archivos adjuntos y cabeceras personalizadas. Crear plantillas HTML de email con Django Template Language. Enviar emails con contenido HTML y texto plano como alternativa.