De Amazon SES a Postal, con SES por debajo
Ya envías por SES. En Postal, la entrega sigue siendo de SES, y lo que antes quedaba a tu cargo pasa a venir listo: dominio guiado, eventos en webhooks, lista de supresión y cuidado de la reputación.
- Para comprobar el DNS
- Hasta 72 h
- Funcionan los dos
- API o SMTP
- Eventos ya en webhooks
- Sin SNS
- La región de envío
- Por dominio
Visión general
Lo que cambia cuando SES queda por debajo
Postal envía por su cuenta de Amazon SES, y no por la tuya. Eso cambia quién se encarga de cada cosa.
Hoy, directo en SES
- Tu sistemaEnvías con el SDK de AWS o por el SMTP de SES.
- Tú configuras y vigilasIdentidad y DKIM, configuration set, tema de SNS, lista de supresión, cuotas y salida del sandbox.
- Amazon SESEn tu cuenta de AWS.
Con Postal
- Tu sistemaEnvías por la API o por el SMTP de Postal.
- Postal se encargaDominio guiado, eventos en webhooks, supresión por equipo y reputación, con aviso antes de pausar.
- Amazon SESEn la cuenta de Postal, en la región que eliges para el dominio.
Lo que pasa a ser de Postal
La verificación del dominio, con diagnóstico en portugués, los eventos en webhooks firmados, la lista de supresión del equipo (los rebotes permanentes y las quejas entran solos) y el aviso antes de pausar el envío por reputación.
Ver entregabilidadLo que sigue siendo SES
La entrega en sí. Los correos electrónicos salen por la infraestructura de Amazon SES, y por eso los rebotes tienen el formato de SES y el Return-Path apunta a feedback-smtp.<região>.amazonses.com.
Lo que cambia en tu cuenta de AWS
La cuota y el sandbox de tu cuenta dejan de valer para Postal. Vale el plan: cuota por día y por mes, límite de solicitudes y pausa por reputación. Tu cuenta puede quedarse como está hasta que apagues el último envío.
Ver límitesLa documentación de Postal no trata las IPs dedicadas de SES. Si tu cuenta usa IPs dedicadas, habla con nosotros por el formulario de contacto antes de migrar.
Haz el inventario en SES
Antes de cambiar nada, enumera lo que tu sistema usa en SES. Cada elemento tiene un lugar en Postal. Las identidades de SES valen para una sola región, así que anota las regiones desde las que envías.
| En la consola de SES | Qué anotar | Dónde queda en Postal |
|---|---|---|
| Identities | Dominios y direcciones verificados, y la región de cada uno | Dominios (la región se elige por dominio) |
| Configuration sets | Nombres y destinos de evento | Webhooks, y el rastreo de apertura y clic en el dominio |
| Email templates | Nombre de la plantilla y las variables | Plantillas |
| Temas de SNS | Quién se suscribe y qué código recibe los eventos | Webhooks |
| Suppression list | Direcciones suprimidas, por región | Supresiones |
| SMTP settings | Quién usa las credenciales SMTP | Claves de API |
Verifica el dominio en Postal
Añade el dominio en Dominios (o con POST /domains), elige la región y publica los registros que muestra Postal. Ella comprueba el DNS sola durante hasta 72 horas, muestra el estado de cada registro y explica qué está mal. El dominio puede seguir verificado en SES al mismo tiempo: los nombres de los registros son diferentes.
| En SES | En Postal | |
|---|---|---|
| DKIM | 3 registros CNAME, <token>._domainkey, que apuntan a <token>.dkim.<região>.amazonses.com (Easy DKIM) | 1 registro TXT, postal._domainkey, con la clave pública de Postal |
| Return-Path (MAIL FROM) | Opcional. Un subdominio tuyo, con MX 10 feedback-smtp.<região>.amazonses.com y TXT "v=spf1 include:amazonses.com ~all" | El subdominio postal (cambia con custom_return_path): MX hacia feedback-smtp.<região>.amazonses.com y TXT v=spf1 include:_spf.postal.so ~all |
| SPF del dominio principal | Tuyo, si incluiste amazonses.com | No cambia: el SPF de Postal queda en el subdominio del Return-Path |
| DMARC | Tuyo | Sigue vigente. Postal no lo exige, pero los grandes proveedores lo piden a quien envía volumen |
| Región | Una identidad por región | Una región por dominio: São Paulo (predeterminada), Virginia del Norte, Ohio, Irlanda o Tokio |
| Plazo | Hasta 72 horas para que el DNS se propague | Hasta 72 horas, con diagnóstico en portugués por registro |
- Si tu Return-Path en SES ya se llama
postal, elige otro nombre en Postal concustom_return_path, para no mezclar los registros. - Para migrar poco a poco, usa un subdominio solo de correo, como
mail.exemplo.com.br. - Postal avisa por el webhook
domain.updatedcuando el dominio pasa averified. Consulta Dominios y DNS.
Cambia la llamada del SDK por la API
Crea una clave de API (acceso total, o solo de envío y restringida al dominio) y cambia el SendEmail del SDK de AWS por POST /emails. La respuesta trae el id del correo electrónico, en lugar del MessageId.
- import { SESv2Client, SendEmailCommand } from '@aws-sdk/client-sesv2'- - const ses = new SESv2Client({ region: 'us-east-1' })- await ses.send(new SendEmailCommand({- FromEmailAddress: 'Aurora Cosméticos <[email protected]>',- Destination: { ToAddresses: ['[email protected]'] },- Content: { Simple: {- Subject: { Data: 'Tu pedido salió para la entrega' },- Body: { Html: { Data: '<p>El pedido #10482 está en camino.</p>' } },- } },- EmailTags: [{ Name: 'category', Value: 'shipping' }],- }))+ await fetch('https://api.postal.so/emails', {+ method: 'POST',+ headers: {+ Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,+ 'Content-Type': 'application/json',+ },+ body: JSON.stringify({+ from: 'Aurora Cosméticos <[email protected]>',+ to: ['[email protected]'],+ subject: 'Tu pedido salió para la entrega',+ html: '<p>El pedido #10482 está en camino.</p>',+ tags: [{ name: 'category', value: 'shipping' }],+ }),+ })| Campo en SES (SendEmail, v2) | En Postal | Qué cambia |
|---|---|---|
FromEmailAddress | from | El dominio debe estar verificado en Postal. |
Destination.ToAddresses | to | Texto o lista, con hasta 50 destinatarios. |
CcAddresses, BccAddresses | cc, bcc | Iguais. |
ReplyToAddresses | reply_to | Texto o lista. |
Content.Simple (Subject, Body.Html, Body.Text) | subject, html, text | Sin los objetos Data y Charset: es el texto directo. |
Content.Simple.Headers | headers | Un objeto nombre → valor. Algunos nombres no se pueden cambiar (From, To, Subject...). |
Content.Simple.Attachments | attachments | filename y content en base64, o path con una URL. Hasta 40 MB en total. El content_id sirve para imágenes incrustadas. |
Content.Template (TemplateName, TemplateData) | template (id o alias, variables) | Las variables pasan de {{nome}} a {{{NOME}}}. Solo texto y números: las listas y los objetos anidados deben resolverse antes de enviar. |
Content.Raw | Sin campo en la API | Usa el SMTP de Postal, que entrega el mensaje tal como llegó. |
EmailTags (Name, Value) | tags (name, value) | Letras ASCII, números, _ y -. Hasta 50 por correo electrónico. |
ConfigurationSetName | No hace falta | Los eventos van a los webhooks. |
ConfigurationOverrides.Tracking | open_tracking, click_tracking | Quedan configurados en el dominio, no en cada mensaje. |
FeedbackForwardingEmailAddress | No hace falta | Los rebotes y las quejas se convierten en eventos y pasan a la supresión. El Return-Path es de Postal. |
SendBulkEmail | POST /emails/batch | Una lista de hasta 100 correos electrónicos (en SES, hasta 50 destinos). Sin adjuntos ni scheduled_at, y depende del plan. |
| No existe | scheduled_at, Idempotency-Key | Novedades: programar hasta 30 días (depende del plan) y repetir una llamada sin duplicar el envío, durante 24 horas. |
- Los errores llegan con el estado HTTP y un JSON
{statusCode, name, message}. La cuota responde429y la pausa por reputación,403 sending_paused. - ¿Prefieres un SDK? Los de Postal (Node.js, PHP y Laravel) y el de Resend, apuntando a Postal, usan la misma API. Consulta SDKs y CLI y la referencia de correos.
Si envías por SMTP, cambia solo el servidor
Los sistemas que hablan SMTP, como WordPress, los ERP y las plataformas de tienda, cambian cuatro campos: servidor, puerto, usuario y contraseña. La contraseña deja de ser la contraseña SMTP derivada de una clave de IAM y pasa a ser una clave de API de Postal.
- MAIL_HOST=email-smtp.us-east-1.amazonaws.com- MAIL_PORT=587- MAIL_USERNAME=<usuario SMTP de SES>- MAIL_PASSWORD=<contraseña SMTP de SES>+ MAIL_HOST=smtp.postal.so+ MAIL_PORT=587+ MAIL_USERNAME=postal+ MAIL_PASSWORD=ps_sua_chave| SMTP de SES | SMTP de Postal | |
|---|---|---|
| Servidor | email-smtp.<região>.amazonaws.com | smtp.postal.so |
| Puertos con STARTTLS | 25, 587 o 2587 | 587 o 2587 |
| Puertos con TLS directo | 465 o 2465 | 465 (recomendado) o 2465 |
| Usuario | El usuario SMTP generado en SES, un par por región | postal |
| Contraseña | La contraseña SMTP, que no es la clave secreta de AWS | Una clave de API (ps_…). Basta una clave de solo envío |
| Remitente | Una identidad verificada en SES | Un dominio verificado en Postal |
- TLS es obligatorio en ambos. En Postal, la autenticación (
AUTH PLAINoAUTH LOGIN) viene siempre después de TLS. - El SMTP de Postal no tiene etiquetas, programación ni plantillas: para eso, usa la API. Si tu sistema manda los encabezados
X-SES-CONFIGURATION-SEToX-SES-MESSAGE-TAGS, quítalos, porque son de SES. - Los envíos por SMTP siguen las mismas reglas de la API (dominio verificado, cuotas y supresión) y aparecen en Correos y Registros. Cada mensaje aceptado puede tener hasta 40 MB y 50 destinatarios. Consulta la guía de SMTP.
Cambia SNS por los webhooks
En SES, el camino de los eventos es tuyo: configuration set, destino de evento, tema de SNS y una suscripción que tu código debe recibir. En Postal registras una URL HTTPS en Webhooks y eliges los eventos. Cada entrega se firma con el signing_secret del endpoint y se repite si falla.
- const message = JSON.parse(body.Message)- if (message.eventType === 'Bounce') {- const kind = message.bounce.bounceType- const id = message.mail.messageId- }+ const event = resend.webhooks.verify({ payload: rawBody, headers, webhookSecret })+ if (event.type === 'email.bounced') {+ const kind = event.data.bounce.type+ const id = event.data.email_id+ }| Evento en SES (eventType) | Evento en Postal | Observación |
|---|---|---|
Send | email.sent | Postal entregó el correo al proveedor de envío. |
Delivery | email.delivered | El servidor del destinatario aceptó el mensaje. |
DeliveryDelay | email.delivery_delayed | Los reintentos ocurren solos. |
Rebote | email.bounced | data.bounce trae type (Permanent, Transient o Undetermined), subType y diagnosticCode. Un rebote permanente pone la dirección en la supresión. |
Complaint | email.complained | La dirección entra en la lista de supresión. |
Open, Click | email.opened, email.clicked | Activa open_tracking y click_tracking en el dominio. |
Rendering Failure | No existe | Una variable de plantilla sin valor devuelve 422 al momento del envío. |
Subscription (listas de contactos de SES) | contact.updated | Corresponde a la audiencia y las campañas de Postal. |
- El identificador que guardas pasa a ser el
iddevuelto porPOST /emails(data.email_iden el webhook), y no elMessageIdde SES. - Las etiquetas vuelven en
data.tagscomo objeto, por ejemplo{"category": "shipping"}. - Postal tiene además eventos que SES no tiene, como
email.scheduled,email.suppressed,email.receivedydomain.updated. - Cualquier respuesta 2xx confirma la entrega. Quita el tema de SNS solo después de pasar todo el tráfico, porque los correos electrónicos que aún salen por SES siguen generando eventos allí. Consulta Webhooks.
Lleva la lista de supresión de SES
Quien ya tuvo un rebote permanente o se quejó en SES no debe recibir de nuevo. Exporta la lista de supresión de tu cuenta e impórtala en Postal antes del primer envío y antes de importar contactos, porque una dirección suprimida nunca se convierte en contacto.
aws sesv2 list-suppressed-destinations --region us-east-1 > supressoes-ses.json
# se a resposta trouxer "NextToken", repita com --next-token "<valor>"
jq -r '.SuppressedDestinationSummaries[].EmailAddress' supressoes-ses.json \
| tr 'A-Z' 'a-z' | sort -u > emails.txtimport { readFileSync } from 'node:fs'
const emails = readFileSync('emails.txt', 'utf8').split('\n').filter(Boolean)
const headers = {
Authorization: `Bearer ${process.env.POSTAL_API_KEY}`,
'Content-Type': 'application/json',
}
for (let i = 0; i < emails.length; i += 100) {
const res = await fetch('https://api.postal.so/suppressions/batch/add', {
method: 'POST',
headers,
body: JSON.stringify({ emails: emails.slice(i, i + 100) }),
})
if (!res.ok) throw new Error(await res.text())
await new Promise((resolve) => setTimeout(resolve, 250)) // respeita o limite do plano
}- La lista de SES vale para la cuenta y para la región. Expórtala una vez por cada región en la que enviabas. En la consola, está en Configuration > Suppression list.
- SES guarda la dirección exactamente como entró, con mayúsculas y minúsculas. Postal compara sin distinguir, así que el comando de arriba pasa todo a minúsculas y quita los repetidos.
- En Postal, las direcciones entran con el origen
manual: la diferencia entreBOUNCEyCOMPLAINTde SES no se guarda. - Necesita una clave de acceso total. Para pocas direcciones, el panel acepta una por vez en Supresiones. Consulta la referencia de supresiones.
Revisa las cuotas y pasa el tráfico
Pasa un flujo a la vez. Empieza por las direcciones de prueba y por ti mismo, sigue en Correos y Registros y solo entonces pasa el resto. Mantén SES activo hasta que lleguen los eventos de los últimos correos electrónicos antiguos.
| En SES | En Postal | |
|---|---|---|
| Tasa de envío | El límite de envío de tu cuenta, por región | Solicitudes por segundo, por equipo: Gratis 5, Profesional 10, Escala 20, Empresarial 50. En el lote, 100 correos electrónicos cuentan como una solicitud |
| Cuota de envío | La de tu cuenta, por región | Por plan. Gratis: 100 por día y 3.000 por mes. Profesional: 50.000 por mes. Escala: 100.000 por mes. Empresarial: a medida. El límite por día también sigue la reputación de la cuenta: las cuentas nuevas empiezan con 500 |
| Sandbox | Hasta pedir acceso de producción: 200 mensajes por 24 horas, 1 por segundo, solo a direcciones verificadas | En AWS pides salir del sandbox; aquí no. El límite es la cuota del plan |
| Reputación | De tu cuenta | Del equipo, de 0 a 100 puntos, empezando en 0. El envío se pausa cuando los rebotes permanentes superan el límite del nivel (del 3% al 5%) o las quejas el 0,3%. Antes, propietarios y administradores reciben un aviso |
- Las direcciones de prueba (
delivered@,bounced@,complained@,suppressed@y[email protected]) no usan la cuota ni pesan en la reputación. Dependen del plan. - Consulta los valores actuales en Precios y en Límites.
Antes de cambiar la clave
- El dominio está
verifieden Postal y DMARC está en orden. - La clave de API está creada (solo envío y restringida al dominio, en los sistemas que solo envían).
- Un correo electrónico de prueba llegó y los encabezados muestran DKIM y SPF de tu dominio.
- El webhook está registrado y tu código verifica la firma.
- La lista de supresión de SES, de todas las regiones, ya se importó.
- Los encabezados
X-SES-*y los temas de SNS que ya no sirven fueron identificados. - La cuota del plan y el límite de solicitudes cubren tu volumen diario.
- Los propietarios y administradores del equipo saben qué hacer si el envío se pausa por reputación.
Preguntas frecuentes
¿Necesito mantener mi cuenta de AWS?
Para enviar por Postal, no: usa su propia cuenta en SES. Mantén la tuya mientras algún sistema aún envíe por allí y hasta que lleguen los eventos de los últimos correos electrónicos. Después, si quieres, borra las identidades y los registros de DNS de SES que ya no uses.
Mi dominio ya está verificado en SES. ¿Puedo verificarlo también en Postal?
Sí. El DKIM de Postal usa el selector postal y el Return-Path queda en un subdominio propio, así que los registros no chocan con los de SES, y el SPF del dominio principal no cambia. La excepción es un Return-Path tuyo que ya se llame postal: usa otro nombre con custom_return_path.
¿Qué pasa con la reputación de envío?
Pasa a medirse por equipo, con la reputación de la cuenta: una puntuación que empieza en 0 y sube con cada día de envíos sin problemas. Las cuentas nuevas empiezan con un tope de 500 correos por día, que crece con el nivel. Postal pausa el envío si los rebotes permanentes superan el límite del nivel (del 3% al 5%) o las quejas el 0,3%. Importar la lista de supresión de SES ayuda a no repetir rebotes ya conocidos.
¿Puedo usar IP dedicadas?
La documentación de Postal no trata este tema. Si tu cuenta de SES usa IP dedicadas, habla con nosotros por el formulario de contacto antes de migrar.
Sigue por aquí
Correo transaccional
API, SMTP, webhooks e inboxes para el correo electrónico que sale de tu sistema.
Más informaciónWebhooks y eventos
Cada evento de correo electrónico en tu servidor, con firma y reintentos.
Más informaciónLista de supresión
Quien no debe recibir queda protegido, por equipo.
Más informaciónOtras guías de migración