DEV Community

Silviu Technology
Silviu Technology

Posted on

FastAPI: pruebas limpias para email de Facebook

Cuando un flujo de registro ofrece continuar con Facebook, el backend suele mandar un correo de verificación, bienvenida o recuperación de contexto. En papel se ve simple. En la suite real, no tanto. La prueba dispara el signup, espera un mensaje, abre el link y listo. Pero si dos escenarios comparten la misma bandeja, aparece el caos: correos cruzados, enlaces viejos y builds verdes que no deberian ser verdes.

He visto equipos backend muy ordenados caer en esto por una razón casi aburrida: el correo se trata como un efecto secundario y no como parte del contrato de la API. Ahí entran búsquedas raras como facebook temp email o notas sueltas con tempail, cuando el problema real no es el proveedor sino la falta de correlación entre request, worker y bandeja.

Qué se rompe en un signup con email de Facebook

El caso comun tiene tres piezas:

  • un endpoint de signup
  • un job async que envía el mensaje
  • una prueba que revisa la bandeja

El fallo aparece cuando la prueba solo busca "el último correo para este usuario". Si hay reintentos, ramas preview o varios jobs corriendo a la vez, ese criterio ya no alcanza. Un estudio de Microsoft Research sobre flaky tests explica que la asincronía y la dependencia de recursos compartidos son causas muy repetidas de inestabilidad. En correo transaccional eso se nota enseguida.

En FastAPI prefiero pensar el email como evidencia del request. Si el signup inició con Facebook, la respuesta HTTP debería devolver un identificador que luego aparezca en logs, tarea async y mensaje final. Suena pequeño, pero cambia bastante la depuración.

Un contrato simple entre FastAPI y la prueba

La versión mas util que he encontrado usa tres campos estables:

  • signup_id para seguir el intento
  • provider para diferenciar Facebook de otros accesos
  • mailbox_scope para aislar la lectura en tests

Un ejemplo corto:

from fastapi import BackgroundTasks, FastAPI
from pydantic import BaseModel
from uuid import uuid4

app = FastAPI()


class SignupPayload(BaseModel):
    email: str


def queue_signup_email(signup_id: str, provider: str, mailbox_scope: str, email: str) -> None:
    print(
        {
            "signup_id": signup_id,
            "provider": provider,
            "mailbox_scope": mailbox_scope,
            "email": email,
        }
    )


@app.post("/auth/facebook/signup")
def facebook_signup(payload: SignupPayload, background_tasks: BackgroundTasks):
    signup_id = f"fb-{uuid4()}"
    mailbox_scope = f"signup-{payload.email.split('@')[0]}"
    background_tasks.add_task(
        queue_signup_email,
        signup_id,
        "facebook",
        mailbox_scope,
        payload.email,
    )
    return {"ok": True, "signup_id": signup_id, "mailbox_scope": mailbox_scope}
Enter fullscreen mode Exit fullscreen mode

La idea no es el snippet en sí. Lo importante es que la prueba ya puede pedir "el correo del signup_id actual dentro del mailbox_scope esperado". Eso baja mucho los falsos positivos y hace mas facil revisar casos donde el usuario intentó registrarse, canceló, y volvió a probar unos segundos despues.

Si además trabajas con bandejas temporales durante QA, conviene usar un proveedor estable y documentado. Un ejemplo practico es temp mail so, pero el valor real sigue estando en el contrato que tu API expone, no en cambiar de servicio cada semana.

Cómo aislar bandejas sin volver frágil la suite

Aquí es donde varias suites se complican solas. Quieren una bandeja por test, un borrado total entre corridas y una capa de polling muy lista. A veces funciona, a veces parese una app aparte.

Yo intentaría algo más sobrio:

  1. crear un mailbox_scope por suite o por rama
  2. guardar signup_id en la respuesta inicial
  3. filtrar por scope antes de mirar asunto o destinatario
  4. validar que el link final corresponda al intento actual

Ese mismo principio ayuda cuando luego necesitas validar emails por entorno preview o diseñar reenvios de verificación sin ansiedad. El patrón no cambia demasiado: menos adivinanza, más señales estables para leer lo correcto.

También vale la pena registrar el instante en que el worker arma el mensaje y el instante en que la prueba lo observa. Si la diferencia sube de manera rara, ya tienes una pista para ver colas lentas, webhooks trabados o rate limits que antes pasaban medio ocultos.

Checklist corto antes de publicar el endpoint

Antes de dar por sano el flujo, esta lista suele ahorrar horas:

  • la respuesta de FastAPI devuelve signup_id
  • el worker conserva ese mismo identificador sin renombrarlo
  • la bandeja de test usa un mailbox_scope visible
  • la prueba valida el enlace y no solo la llegada
  • los mensajes viejos se ignoran por id y no por "último recibido"
  • los logs muestran proveedor, scope y estado final

No es una receta magica, pero sí una base honesta. Muchas veces el problema del facebook temp email no es acceso externo ni autenticación rara, sino una suite que lee demasiado poco contexto cuando revisa el inbox.

Preguntas frecuentes

¿Hace falta una bandeja nueva para cada test?

No siempre. Si tu volumen es bajo, una bandeja por suite o rama puede ser suficiente. Lo importante es que el filtro sea estable y que el signup_id viaje hasta el correo.

¿Qué conviene validar además del link?

El destinatario, el proveedor esperado, la expiración del token y alguna referencia visible dentro del cuerpo. Si el enlace sirve pero pertenece a otro intento, la prueba sigue mal aunque pase.

¿Este patrón solo aplica a Facebook?

Para nada. Sirve igual con Google, magic links o invitaciones B2B. Facebook solo hace más visible el problema porque muchas pruebas de onboarding mezclan varios caminos y el correo queda en el medio.

Top comments (0)