D/ DJANGO CON CRITERIO

UNIDAD 9 · OPERACIÓN Y DEVSECOPS

Correo SMTP nativo después del commit

EmailMultiAlternatives, secretos, destinatarios autorizados y límites de entrega.

Ilustración: El correo sale después de confirmar
El correo sale después de confirmar

CAPÍTULO 6 · Los datos empiezan a llegar

No anunciar un resultado antes de que exista

El correo puede comunicar una alarma, un resultado o una acción terminada. Sin embargo, enviarlo demasiado pronto introduce una contradicción: el destinatario podría recibir una confirmación aunque la transacción que la originó termine revirtiéndose. El mensaje debe corresponder al estado confirmado del sistema, no a una intención que todavía puede fallar.

Integramos SMTP cuidando cuándo se solicita el envío. Después del commit sabemos que el cambio se confirmó; si necesitamos recuperar entregas fallidas, conectamos este punto con las tareas y la outbox ya estudiadas. Las credenciales del proveedor pertenecen a la configuración del entorno, y el resultado del envío necesita observación.

La plataforma ya reúne datos, interfaces, controles y comunicaciones. Cada nueva pieza ha resuelto una necesidad, pero también ha aumentado el número de relaciones que pueden romperse al modificar algo. Antes de preparar la entrega necesitamos una forma de comprobar que esa red de decisiones sigue comportándose como acordamos.

Leer esta parte dentro del relato completo →

DEL RELATO A LA PRÁCTICA

Vamos a desarrollar esta decisión con su mapa, explicación, código y ejercicio.

MIRA · CONECTA · COMPRENDE

El correo sale después de confirmar

El correo sale después de confirmar1. Evento de negocio: Cambio dentro de transacción; 2. Commit: Confirma o descarta callback; 3. on_commit: Envía sin garantía de reintento; 4. Outbox opcional: Entrega durable si es necesaria01Evento de negocioCambio dentro de transacción02CommitConfirma o descarta callback03on_commitEnvía sin garantía de reintento04Outbox opcionalEntrega durable si es necesaria

on_commit se usa después del commit. Outbox es una alternativa para entrega durable, no un paso automático que siga a cada correo.

Selecciona una pieza para destacar su responsabilidad.

Leer la explicación del mapa
  1. Evento de negocio. Cambio dentro de transacción
  2. Commit. Confirma o descarta callback
  3. on_commit. Envía sin garantía de reintento
  4. Outbox opcional. Entrega durable si es necesaria
Descargar gráfico SVG ↓

¿Para qué sirve?

Enviar una notificación antes de confirmar una transacción puede anunciar un cambio que después se revierte. Un fallo SMTP tampoco debe deshacer un negocio ya confirmado.

El concepto, explicado

Django ofrece backend SMTP y EmailMultiAlternatives para texto y HTML. En desarrollo usa consola y en tests locmem para no realizar envíos externos.

transaction.on_commit ejecuta el callback después de confirmar; rollback lo descarta. Es útil para bajo volumen, pero no garantiza entrega: un proceso puede morir después del commit y antes del envío.

Resuelve destinatarios desde relaciones autorizadas del dominio. El navegador no elige el destinatario de una alarma ni aporta una plantilla sin restricciones.

TLS explícito y SSL implícito son opciones excluyentes. Usa el método y credenciales que permita el proveedor vigente; una contraseña de aplicación no es una solución universal. Para entrega fiable usa outbox, worker y política de reintento.

Implementación paso a paso

  1. Selecciona proveedor y verifica requisitos de autenticación/cifrado.
  2. Carga settings desde secretos, define timeout y valida configuración.
  3. Construye texto y HTML con autoescape y enlaces canónicos de configuración.
  4. Registra on_commit dentro del servicio transaccional con ID del objeto.
  5. Después del commit vuelve a consultar estado y relación del destinatario.
  6. Prueba rollback, callback, destinatario inválido y fallo SMTP sin conexiones reales.

Ejemplo en SensorHub

# Esquema: Alarm y render_to_string requieren modelos/templates propios.
import logging
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.db import transaction
from django.template.loader import render_to_string
logger = logging.getLogger(__name__)

def notify_alarm(alarm_id):
    alarm = Alarm.objects.select_related("recipient").get(pk=alarm_id)
    recipient = alarm.recipient  # relación validada por la política de dominio
    if not recipient.is_active or not recipient.email:
        return
    html = render_to_string("emails/alarm.html", {"alarm": alarm})
    mail = EmailMultiAlternatives("Alarma SensorHub", "Revisa la alarma.",
                                 settings.DEFAULT_FROM_EMAIL, [recipient.email])
    mail.attach_alternative(html, "text/html")
    mail.send(fail_silently=False)

# Dentro de la transacción del servicio, después de guardar alarm:
# transaction.on_commit(lambda pk=alarm.pk: notify_alarm(pk), robust=True)

Cómo leer el ejemplo

  • robust=True permite registrar excepciones del callback sin propagarlas; no añade reintentos ni durabilidad.
  • EMAIL_TIMEOUT evita esperas indefinidas; revisa logs sin cuerpos ni credenciales.
  • El esquema necesita el modelo Alarm y una relación autorizada implementada en tu proyecto.
  • En tests usa captureOnCommitCallbacks(execute=True); un TestCase normal no confirma como producción.

Error habitual

Suponer que on_commit garantiza entrega, usar TLS y SSL a la vez o usar el Host del cliente para enlaces del correo.

05 / PRACTICAR

Tu turno

Una alarma se confirma pero SMTP cae. ¿Qué cambia con on_commit frente a outbox?

Ver solución orientativa

on_commit conserva la alarma y puede registrar el fallo, pero se pierde el envío. Outbox persiste el trabajo en la misma transacción; un worker reintenta y registra estado, con deduplicación según la garantía elegida.

Cómo sabes que funciona

  • Rollback no dispara el mensaje.
  • Los tests no llaman un SMTP real.
  • El destinatario no viene del cliente.
  • Para entrega crítica existe outbox y reintentos.

Para profundizar

Documentación oficial para comprobar configuración, permisos y condiciones vigentes. Revisión del tema: 2026-10-11.

CONTINUAR LA EXPERIENCIA

El siguiente paso del recorrido:

Pruebas de comportamiento →Continuar en modo relato