guía · API de correo electrónico

¿Cómo debería implementar un equipo de producto una API de correo de forma segura?

Implemente una API de correo como un flujo asíncrono y con permisos, en lugar de una llamada directa del formulario al proveedor. Autentique a quien llama, confirme que el inquilino es propietario de un dominio From verificado, valide el mensaje y su tamaño, asigne un ID de trabajo estable en la aplicación, póngalo en cola una sola vez y envíelo desde un worker. Registre el ID de mensaje del proveedor cuando se acepte, incorpore los eventos de entrega de forma idempotente y suprima los rebotes permanentes y las quejas. Use reintentos acotados solo cuando el riesgo de duplicados esté controlado. Mantenga las credenciales en el servidor, minimice los datos de los mensajes en los registros y distinga entre la aceptación por la API, la entrega al servidor de correo y la llegada a la bandeja de entrada.

Defina el límite de la API antes de elegir un proveedor

Una API de correo debería expresar la intención de la aplicación sin filtrar todos los detalles del proveedor al código del producto. Defina recursos para los mensajes, los dominios de envío, las claves de API, los eventos y las supresiones. Decida qué campos pueden controlar quienes llaman, incluidos From, To, Reply-To, el asunto, el texto, el HTML y una pequeña lista de encabezados permitidos. Rechace los encabezados de transporte proporcionados por quien llama que puedan entrar en conflicto con la firma o el enrutamiento del proveedor. Trate el envío como una escritura con consecuencias: la respuesta debería identificar un recurso de mensaje de la aplicación y su estado actual, no dar a entender un resultado en el buzón. Mantenga la cuenta del proveedor, la región, el configuration set y los identificadores de transporte detrás de un adaptador. Este límite hace posible la migración de proveedor y ofrece un lugar estable para los controles de autorización, retención y abuso.

Autentique a quien llama y autorice cada dominio remitente

Guarde las claves de API solo como hashes unidireccionales y muestre el secreto completo una sola vez. Asigne a cada clave un espacio de trabajo propietario, un estado, una fecha de creación y una forma de revocarla; agregue alcances más estrechos cuando una integración solo deba enviar o solo leer eventos. La autenticación responde quién presentó una credencial, mientras que la autorización decide si ese principal puede usar el dominio From y el recurso de mensaje solicitados. Compruebe la propiedad del dominio en cada envío, incluidos los endpoints de lotes, en lugar de confiar en un identificador de dominio proporcionado por el cliente. Exija la verificación del proveedor antes de habilitar el tráfico de producción. Nunca ponga credenciales del proveedor ni claves de API del espacio de trabajo en JavaScript del navegador, cadenas de consulta, analíticas o mensajes de error. La autorización a nivel de objeto es especialmente importante para los identificadores de mensajes, eventos, supresiones, bandejas de entrada y dominios en una API multiinquilino.

Verifique el dominio y alinee la autenticación

Un dominio de envío necesita algo más que un indicador en la base de datos. Complete la comprobación de propiedad del proveedor y publique los registros DKIM requeridos. SPF autoriza hosts para la identidad SMTP MAIL FROM o HELO, mientras que DKIM asocia un dominio de firma con una firma criptográfica del mensaje. DMARC evalúa si un identificador SPF o DKIM validado está alineado con el dominio From visible de RFC 5322 y permite que el propietario del dominio publique una política de tratamiento e informes. Si un dominio ya tiene SPF, integre el mecanismo requerido en el registro existente; RFC 7208 establece que un dominio no debe publicar varios registros que provoquen la selección de más de un registro SPF. Implemente una política DMARC más estricta solo después de que los mensajes controlados y los informes agregados muestren que todos los remitentes legítimos están alineados. La autenticación reduce el uso no autorizado del dominio, pero no garantiza la llegada a la bandeja de entrada.

Valide la estructura del mensaje y minimice la entrada aceptada

RFC 5322 define un mensaje de Internet como campos de encabezado seguidos de un cuerpo opcional, y las especificaciones MIME amplían el contenido más allá del texto básico. Una API puede ocultar la mayoría de los detalles del formato de transmisión y, aun así, hacerlos cumplir. Normalice los arrays de destinatarios, limite el número de destinatarios y el tamaño codificado total, exija al menos un cuerpo de texto o HTML y valide las direcciones sin pretender que la sintaxis demuestre que el buzón existe. Elimine los caracteres de retorno de carro y salto de línea de los campos que se convierten en encabezados. Genere el Message-ID o deje que lo haga el proveedor; no lo reutilice como ID de trabajo de la aplicación, porque una nueva versión del mensaje puede recibir legítimamente un nuevo identificador. Permita solo los encabezados personalizados documentados, rechace los duplicados de campos protegidos y renderice las plantillas antes de enviarlas al proveedor, para que las variables faltantes fallen en un estado controlado de la aplicación.

Ponga en cola una sola vez y use identificadores de aplicación estables

Una solicitud del usuario debería crear un único trabajo de mensaje duradero dentro de una transacción, y luego un worker debería hacer la llamada al proveedor. Asigne al trabajo un identificador estable y registre una huella de la solicitud o una clave de idempotencia proporcionada por quien llama cuando el contrato lo admita. HTTP define POST como no idempotente de forma predeterminada y desaconseja el reintento automático, salvo que el cliente sepa que la operación es efectivamente idempotente o que la solicitud original no se aplicó. Esto importa en el correo, porque puede producirse un tiempo de espera agotado después de que el proveedor haya aceptado el mensaje pero antes de que el worker reciba la respuesta. Ante un fallo ambiguo, concilie primero el trabajo guardado y el estado del proveedor en lugar de crear un envío nuevo. Use un patrón outbox cuando el estado de la aplicación y la publicación en la cola deban avanzar juntos, y ponga una restricción de unicidad en el límite de idempotencia.

Diseñe los reintentos según las clases de fallo

Separe la validación, la autorización, la limitación de frecuencia, el rechazo del proveedor, los fallos de transporte transitorios y los fallos de entrega al destinatario. Una entrada no válida o un dominio From no autorizado deben fallar sin reintento. Los límites de frecuencia del proveedor y los errores temporales del servicio se pueden reintentar con backoff exponencial acotado, jitter, un máximo de intentos y un tiempo de visibilidad de la cola mayor que el plazo de solicitud del worker. Un tiempo de espera de red ambiguo requiere una conciliación que tenga en cuenta los duplicados, no una nueva solicitud incondicional. SMTP distingue por sí mismo las respuestas transitorias 4xx de las permanentes 5xx, pero una aplicación que usa la API de un proveedor debe seguir la semántica de errores documentada por ese proveedor. Mueva los trabajos que agotaron sus intentos a un estado de dead-letter revisable y conserve el motivo depurado. No reintente un rebote permanente de un destinatario como si fuera una caída de la API, ni convierta una queja en otro intento de envío.

Registre la aceptación e incorpore los eventos de entrega

Conserve el identificador de mensaje del proveedor inmediatamente después de la aceptación y asígnelo al ID de mensaje de la aplicación. Los eventos del proveedor podrán entonces actualizar el recurso correcto incluso cuando un informe de queja oculte detalles del destinatario. Amazon SES, por ejemplo, distingue un envío correcto de la entrega al servidor de correo del destinatario y puede publicar eventos de entrega, rebote, queja, rechazo, retraso de entrega, fallo de renderizado, apertura y clic. Verifique la autenticidad del webhook mediante el mecanismo documentado por el proveedor, valide el esquema de eventos, elimine duplicados mediante un identificador de evento del proveedor o una huella digital determinista y permita la entrega repetida del mismo evento sin repetir efectos secundarios. Almacene payloads sin procesar solo cuando sea necesario, cifrados, con control de acceso y retención limitada. El estado normalizado debe distinguir los resultados aceptado, entregado al servidor, rebotado, con queja, retrasado, rechazado y suprimido.

Convierta la supresión en un control en el momento del envío

Un registro de supresión debe comprobarse antes de cada envío al proveedor, no solo mostrarse en un panel. Las direcciones con rebote permanente y las quejas normalmente requieren supresión; las demoras temporales de entrega necesitan otra política. Defina el alcance de la supresión de forma deliberada. Una lista para toda la cuenta puede proteger la reputación compartida, pero puede permitir que el resultado de un destinatario de un inquilino bloquee a otro inquilino. Una lista con alcance por inquilino reduce ese acoplamiento, pero sigue necesitando una capa de protección contra el abuso y de seguridad de la plataforma. Registre el motivo, el evento de origen, el inquilino, la fecha de creación y una vía controlada de eliminación. Eliminar una supresión por queja o por rebote permanente tiene consecuencias y debería requerir una revisión deliberada y evidencia de que la dirección es válida y de que el destinatario espera el mensaje. Evite copiar direcciones de destinatarios sin procesar en registros generales o experimentos; el almacenamiento operativo puede aplicar la política de envío mientras las analíticas usan recuentos agregados.

Proteja los envíos por lotes y los flujos de negocio sensibles

Un endpoint de lotes multiplica el impacto de un error de autorización o de validación. Aplique a cada elemento las mismas comprobaciones de propiedad del dominio, supresión, tamaño y contenido, imponga una longitud máxima de lote estricta y devuelva resultados por elemento sin filtrar datos de otro inquilino. Debe haber límites de frecuencia a nivel de credencial, espacio de trabajo, dominio y proveedor, con controles separados para las ráfagas y el volumen acumulado. Un único límite global de solicitudes por segundo no basta, porque una sola solicitud puede contener muchos destinatarios. Exija una confirmación deliberada en las herramientas controladas por agentes antes de enviar un lote de alto impacto. Separe los permisos transaccionales y de marketing cuando sus reglas de consentimiento y operación sean distintas. Monitoree el crecimiento inusual de destinatarios, los dominios rechazados de forma repetida, los cambios bruscos en rebotes o quejas y la creación rápida de claves. La limitación de frecuencia contribuye a la seguridad, pero no sustituye la autenticación, la autorización de objetos, el consentimiento verificado ni la respuesta ante el abuso.

Pruebe las rutas de fallo antes de pasar a producción

Use los simuladores del proveedor o buzones controlados para probar la aceptación, la entrega al servidor receptor, el rebote permanente, la queja, la demora, el dominio no válido, la clave revocada, la limitación de frecuencia, el tiempo de espera del proveedor, el webhook duplicado y la reentrega desde la cola. Confirme que una misma clave de idempotencia crea un único mensaje en la aplicación, que un evento repetido no produce efectos secundarios duplicados y que un inquilino no puede leer ni enviar con el dominio o el ID de mensaje de otro inquilino. Inspeccione un mensaje real recibido para comprobar From, Return-Path, DKIM, SPF, la alineación DMARC, el renderizado del texto y del HTML, el comportamiento de baja cuando corresponda y los enlaces. Haga pruebas de carga de la cola por debajo de los límites aprobados por el proveedor y verifique la contrapresión en lugar de eludirla. Agregue alarmas para la antigüedad de la cola, los reintentos agotados, los fallos de incorporación de eventos, el margen de cuota, los cambios en rebotes y quejas y las devoluciones de llamada del proveedor que falten. Una lista de verificación de lanzamiento debería nombrar un responsable para cada alerta y cada acción de recuperación.

Aplique el patrón con SendHQ con cuidado

SendHQ proporciona claves bearer con alcance por espacio de trabajo, comprobaciones de dominio From verificado, creación de mensajes individuales y por lotes, buzones de entrada, eventos de mensajes y recursos de supresión. Estas funcionalidades respaldan la arquitectura de esta guía: mantenga la clave en el servidor, cree un recurso de mensaje, conserve su ID y lea los eventos posteriores en lugar de tratar la respuesta inicial como entrega final. Independientemente de la plataforma, quienes realizan llamadas siguen siendo responsables de los destinatarios previstos, del correo legal y esperado, de la precisión del contenido y de la aprobación cuidadosa de envíos importantes.

Preguntas frecuentes

¿Debe una API de correo enviar de forma síncrona desde la solicitud web?

Por lo general, no. Cree un mensaje duradero en la aplicación, póngalo en cola y deje que un worker llame al proveedor. Esto aísla la latencia, permite reintentos acotados y facilita la conciliación de los resultados ambiguos del proveedor.

¿Cómo evito correos duplicados cuando una solicitud agota el tiempo de espera?

Use un ID de trabajo de aplicación estable y un límite de idempotencia con una restricción de unicidad. Ante un tiempo de espera ambiguo, concilie el trabajo existente antes de hacer otro envío al proveedor con una identidad nueva.

¿Una respuesta exitosa de la API de correo significa que el mensaje se entregó?

No. Normalmente indica que la API o el proveedor aceptaron la solicitud. Use los eventos posteriores para distinguir la entrega al servidor receptor, el rebote, la queja, la demora, el rechazo y la supresión de la aceptación inicial.

¿Qué registros DNS necesita una API de correo?

Los registros exactos dependen del proveedor, pero el envío en producción suele requerir la verificación del dominio y DKIM, además de una estrategia SPF correcta y una política DMARC alineada con los flujos de envío legítimos.

¿Se deben guardar las claves de API en el código del navegador?

No. Mantenga las credenciales del espacio de trabajo y del proveedor en un almacén de secretos del lado del servidor, guarde las claves de API de la aplicación como hash en reposo siempre que sea posible, muestre los secretos completos una sola vez y ofrezca vías rápidas de revocación y rotación.

¿Cómo debería gestionar una API de correo los rebotes permanentes?

Normalice el evento del proveedor, asócielo al mensaje de la aplicación y suprima los envíos rutinarios futuros a ese destinatario dentro del alcance previsto. La eliminación debe ser deliberada y estar respaldada por evidencia.

Fuentes