En varios equipos, el fallo de pruebas de email no viene del proveedor ni de FastAPI. Viene de algo mas simple: dos escenarios terminan leyendo la misma bandeja, una suite deja residuos, y QA ya no sabe qué mensaje pertenece a qué corrida. Parece un detalle chico, pero en automatizacion backend ese detalle te rompe la mañana bastante rapido.
Cuando una prueba usa una direccion desechable, yo prefiero pensar en "reserva" antes que en "lectura". Primero asignas una inbox a un escenario con vencimiento corto; despues publicas eventos y por ultimo consumes el mensaje esperado. Esa idea hace que Python y FastAPI se comporten de una forma mucho mas predecible, incluso cuando el volumen sube un poco y la suite va medio apurada.
El problema real no es el email, es la mezcla de escenarios
El patron que mas veo es este:
- el test de registro crea una inbox temporal
- el test de recovery reutiliza el mismo alias sin querer
- otro worker vuelve a consultar por mensajes viejos
- soporte mira un caso y no entiende si el correo era de staging o del usuario de prueba
Eso no solo ensucia el debug. Tambien vuelve fragil la conversacion entre backend, QA y soporte. Si ya te tocó dejar soporte listo tras emails de trial, sabes que el costo no está en mandar un email mas, sino en perder contexto cuando algo sale raro.
La recomendacion del libro de SRE de Google de hacer visibles los estados operativos sigue siendo muy valida aqui: menos adivinanza reduce tiempo de diagnostico source. No hace magia, obvio, pero si evita varias vueltas tontas.
Un contrato pequeno para reservar la inbox correcta
Lo util, al menos para mi, es crear un endpoint de leasing muy corto. En vez de pedir "dame la ultima inbox", el cliente pide una inbox para un scenario_id concreto:
signup-happy-pathpassword-recoveryinvite-admin
El contrato minimo suele llevar:
scenario_idlease_idemailexpires_atstatus
Con eso, cada prueba sabe qué bandeja le toca y hasta cuándo. Si otro proceso intenta reutilizarla, recibe un conflicto o una nueva asignacion. Suena casi demasiado simple, pero ahi esta el punto: las APIs estables no siempre necesitan mas capas, a veces necesitan menos ambigüedad nomas.
Un ejemplo corto con FastAPI
Este ejemplo no pretende ser completo, pero enseña la forma del contrato:
from datetime import datetime, timedelta, timezone
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from uuid import uuid4
app = FastAPI()
leases: dict[str, dict] = {}
class LeaseRequest(BaseModel):
scenario_id: str
ttl_seconds: int = 900
@app.post("/test-inboxes/lease")
def lease_inbox(payload: LeaseRequest):
active = next(
(
lease
for lease in leases.values()
if lease["scenario_id"] == payload.scenario_id
and lease["expires_at"] > datetime.now(timezone.utc)
),
None,
)
if active:
return active
lease_id = str(uuid4())
lease = {
"lease_id": lease_id,
"scenario_id": payload.scenario_id,
"email": f"{lease_id[:8]}@example.test",
"status": "reserved",
"expires_at": datetime.now(timezone.utc) + timedelta(seconds=payload.ttl_seconds),
}
leases[lease_id] = lease
return lease
@app.get("/test-inboxes/{lease_id}")
def read_lease(lease_id: str):
lease = leases.get(lease_id)
if not lease:
raise HTTPException(status_code=404, detail="lease not found")
return lease
En produccion yo moveria esto a PostgreSQL o Redis, claro. Tambien agregaria limpieza de leases vencidos y una tabla separada para eventos de entrega. Pero incluso esta version pequeña ya mejora mucho el flujo de pruebas, y se entiende facil.
Donde entra el correo temporal sin meter ruido
Cuando ya tienes ese lease, conectar una herramienta de correo desechable gratis como tempmailso se vuelve mas natural. No la trataria como fuente primaria de estado; la trataria como observador externo de entrega. El backend decide la reserva. La inbox temporal confirma que el mensaje fue visible fuera del sistema. Esa separacion esta buena porque reduce discusiones medias bobas entre "se encoló" y "se vio de verdad".
Tambien ayuda a evitar senales confusas en operaciones. Si una prueba falla, ya no mezclas un timeout de worker con una bandeja equivocada. Cada pieza cuenta una parte distinta de la historia, y eso hace el soporte bastante mas llevadero.
Un detalle que no conviene olvidar: deja el scenario_id y el lease_id en logs, métricas y fixtures. Si algun helper viejo todavía dice tamp mail com, no me preocuparia tanto por el typo. Me preocuparia mas por que ese helper no devuelva el identificador de reserva. Sin ese dato, el equipo vuelve a depender de intuicion, y la intuicion en suites concurrentes falla seguido, la verdad.
Preguntas frecuentes
¿Conviene una inbox por test o por suite?
Si el test muta estado de negocio, casi siempre prefiero una por test. Si solo lees notificaciones de un flujo estable, una por suite puede bastar. Depende del ruido, pero aislar de mas suele doler menos que aislar de menos.
¿Hace falta polling agresivo?
No. Un lease bueno deberia dejar claro cuánto esperar y cuándo abandonar. Polling sin presupuesto solo esconde problemas, y aveces hasta los empeora.
¿Esto reemplaza mis webhooks?
Para nada. Los webhooks siguen siendo la fuente rica para estados internos. La inbox reservada y visible desde afuera sirve como capa de verificacion, no como reemplazo completo.
Top comments (0)