# Migrar desde Mailgun

> Pasa de Mailgun a Emailit. Equivalencias de dominios, claves y rutas, conversión de las llamadas a la API con formularios a JSON, y traslado de SMTP, webhooks, direcciones bloqueadas y plantillas.

Esta guía relaciona los conceptos, las llamadas a la API, los webhooks, las direcciones bloqueadas y las plantillas de Mailgun con sus equivalentes en Emailit. Lee primero [Migrar a Emailit](/es/docs/migrate/) para conocer el orden general y cómo usar los dos proveedores en paralelo.

## Conceptos

| Mailgun | Emailit |
| --- | --- |
| Cuenta y subcuentas | Cuenta y [espacios de trabajo](/es/docs/workspaces/). Cada espacio de trabajo tiene sus propios dominios, claves, miembros y créditos. |
| Dominio, con su propia ruta de API `/v3/<domain>/…` | [Dominio de envío](/es/docs/domains/). Hay un único endpoint de envío, y Emailit elige el dominio a partir de la dirección `from`. |
| Private API key | [Clave de API](/es/docs/developers/api-keys/) con **Full Access** |
| Domain sending key | Clave de API **Sending Only** limitada a un dominio |
| Credenciales SMTP por dominio | Tu clave de API, usada como contraseña SMTP |
| Plantillas por dominio, con versiones | [Plantillas](/es/docs/templates/) por espacio de trabajo, con un alias y versiones |
| Webhooks por dominio | [Webhooks](/es/docs/webhooks/) por espacio de trabajo |
| Routes | [Emails entrantes](/es/docs/inbound/) con el webhook `email.received`, o la [automatización](/es/docs/inbound/forward-with-automations/) **Forward received email** |
| Suppressions por dominio: bounces, unsubscribes, complaints | Una [lista de direcciones bloqueadas](/es/docs/suppressions/) por espacio de trabajo |
| Mailing lists | [Listas de contactos](/es/docs/audiences/) |
| Etiquetas y variables personalizadas | `meta` |
| Logs y eventos | **Email API → Emails**, **Email API → Events** y **Email API → Logs** |
| Email validation | [Verificación de emails](/es/docs/email-verification/) |

## Actualizar las llamadas a la API

`POST /v3/<domain>/messages` de Mailgun recibe campos de formulario con autenticación básica. `POST /v2/emails` de Emailit recibe JSON con un token bearer:

```bash title="Antes: Mailgun"
curl -s --user "api:$MAILGUN_API_KEY" \
  https://api.mailgun.net/v3/mg.acme.com/messages \
  -F from='Acme <hello@mg.acme.com>' \
  -F to='ada@example.com' \
  -F subject='Your receipt' \
  -F text='Thanks for your order.' \
  --form-string html='<p>Thanks for your order.</p>'
```

```bash title="Después: Emailit"
curl https://api.emailit.com/v2/emails \
  -H "Authorization: Bearer $EMAILIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <hello@mg.acme.com>",
    "to": "ada@example.com",
    "subject": "Your receipt",
    "text": "Thanks for your order.",
    "html": "<p>Thanks for your order.</p>"
  }'
```

| Mailgun | Emailit |
| --- | --- |
| Autenticación básica `api:<key>` | `Authorization: Bearer secret_…` |
| Campos `multipart/form-data` | Un cuerpo JSON |
| `from`, `subject`, `text`, `html` | Los mismos nombres |
| `to`, `cc`, `bcc` (repetidos o separados por comas) | `to`, `cc`, `bcc` como cadena o como array de hasta 50 cada uno |
| `h:Reply-To` | `reply_to` |
| `h:X-My-Header` | `headers: { "X-My-Header": "…" }` |
| `v:order-id`, `h:X-Mailgun-Variables` | `meta: { "order-id": "…" }`, que se devuelve en los eventos de webhook |
| `template` y `t:variables` | `template` (un ID o alias) y `variables` |
| `attachment`, `inline` (subida de archivos) | `attachments[]` con `content` en base64 o una `url`, más `content_type`. Añade `content_id` para las imágenes en línea. |
| `o:deliverytime` (fecha RFC 2822) | `scheduled_at` (ISO 8601, tiempo Unix o lenguaje natural en inglés) |
| `o:tracking`, `o:tracking-opens`, `o:tracking-clicks` | `tracking: { "loads": true, "clicks": true }` |
| `o:tag` | `meta` |
| `o:testmode` | No disponible |
| `recipient-variables` (envío por lotes) | No disponible. Envía una petición por destinatario con sus propias `variables`. |
| Respuesta `{ "id": "<…>", "message": "Queued. Thank you." }` | `200` con `id` (`em_…`), `message_id`, `status: "accepted"` e `ids` por destinatario |

Si enviabas desde un subdominio como `mg.acme.com`, añade exactamente ese subdominio en Emailit. Los subdominios se verifican por separado del dominio principal. Los hosts de la API de Mailgun para la UE y para EE. UU. corresponden al mismo endpoint único de Emailit. Consulta [Enviar un email](/es/docs/email-api/send-email/).

## Cambiar la configuración SMTP

| Ajuste | Mailgun | Emailit |
| --- | --- | --- |
| Host | `smtp.mailgun.org` o el host de la UE | `smtp.emailit.com` |
| Puerto | `587`, `465`, `2525` o `25` | `587` (STARTTLS), `465` (TLS), `2525`, `2587` o `25` |
| Usuario | Tu usuario SMTP, como `postmaster@mg.acme.com` | `emailit` |
| Contraseña | Tu contraseña SMTP | Tu clave de API de Emailit |

Emailit no lee las cabeceras `X-Mailgun-*`. Elimínalas y configura el seguimiento en el dominio. Consulta [Configuración SMTP](/es/docs/smtp/settings/).

## Equivalencias de los eventos de webhook

| Evento de Mailgun | Evento de Emailit |
| --- | --- |
| `accepted` | `email.accepted` (solo API) |
| `delivered` | `email.delivered` |
| `failed` con gravedad `temporary` | `email.attempted` |
| `failed` con gravedad `permanent` | `email.bounced` |
| `opened` | `email.loaded` |
| `clicked` | `email.clicked` |
| `complained` | `email.complained` |
| `unsubscribed` | `email.unsubscribed`, solo para los emails de campaña |
| Ruta que reenvía a una URL | `email.received`; después, obtén el contenido con [`GET /emails/{id}`](/es/docs/api-reference/emails/get/) |

El formato de las peticiones cambia:

- Mailgun envía un evento por petición, con los detalles en `event-data`. Emailit envía un array JSON de hasta 100 eventos. Recorre el array.
- El nombre del evento está en `type` y el email, en `data.object`. Usa `data.object.id`, el ID `em_` de la respuesta de envío, para asociar los eventos con los mensajes. Tus valores de `meta` están en `data.object.meta`.
- Mailgun firma una marca de tiempo y un token dentro del cuerpo. Emailit firma todo el cuerpo en bruto: verifica `X-Emailit-Signature` con `X-Emailit-Timestamp` y tu secreto `whsec_`. Consulta [Verificar las firmas de los webhooks](/es/docs/webhooks/request-signature/).

```javascript
for (const event of req.body) {
  const email = event.data.object;
  if (event.type === 'email.bounced') markBounced(email.to, email.id);
  if (event.type === 'email.complained') unsubscribe(email.to);
}
```

## Trasladar las direcciones bloqueadas

1. Exporta las listas **Bounces**, **Complaints** y **Unsubscribes** de cada dominio de Mailgun desde el que envías, desde el panel de control o con la API de suppressions (`/v3/<domain>/bounces`, `/complaints` y `/unsubscribes`).

2. Crea un único CSV con las columnas `email,type,reason`:

```csv
email,type,reason
old-address@example.com,recipient,mailgun bounce
angry@example.com,recipient,mailgun complaint
```

   Usa el tipo `recipient` para las direcciones que nunca deben recibir emails. Bloquea los envíos por API, por SMTP y de campañas. Los tipos `bounce`, `complaint` y `unsubscribe` solo detienen las campañas.

3. En **Email API → Suppressions**, selecciona **Import** y sube el archivo. Cada archivo puede tener hasta 10.000 filas y ocupar como máximo 8 MB. Los duplicados se omiten.

Emailit tiene una lista de direcciones bloqueadas por espacio de trabajo, así que las direcciones de todos tus dominios de Mailgun van a la misma lista. No hay lista de direcciones permitidas. Consulta [Gestionar las direcciones bloqueadas](/es/docs/suppressions/manage/).

## Trasladar las plantillas

Copia el HTML de cada plantilla de Mailgun y después impórtalo en **Email Marketing → Templates** o crea la plantilla con la [API de plantillas](/es/docs/api-reference/templates/create/). Asígnale un alias y envíala con `"template": "<alias>"` y `variables`.

Las plantillas de Mailgun usan Handlebars. Temple cubre lo más habitual:

| Mailgun (Handlebars) | Emailit (Temple) |
| --- | --- |
| `{{first_name}}` | `{{first_name}}` |
| `{{{html_block}}}` | `{{html_block}}`. Temple nunca escapa el HTML, así que escapa tú los datos que introducen los usuarios. |
| `{{#if plan}}…{{else}}…{{/if}}` | Igual |
| `{{#unless plan}}…{{/unless}}` | `{{#if plan}}{{else}}…{{/if}}` |
| `{{#each items}}…{{/each}}` | No compatible. Genera la lista en tu código y pásala como una sola variable. |
| `{{#equal plan "pro"}}…{{/equal}}` | No compatible. Pasa un booleano como `is_pro` y usa `{{#if is_pro}}`. |
| Sin valor por defecto integrado | `{{first_name\|"there"}}` añade un valor alternativo |

Consulta [Lenguaje de plantillas Temple](/es/docs/templates/temple/) e [Importar, exportar y duplicar plantillas](/es/docs/templates/import-export/).

## Cambiar los DNS

Añade cada dominio en **Email API → Domains** y publica los registros de Emailit. Usan sus propios nombres (`emailit._domainkey`, `emailit.<domain>` y, opcionalmente, `go` e `inbound`), así que no entran en conflicto con el registro DKIM de Mailgun ni con su CNAME de seguimiento `email.<domain>`. No necesitas cambiar el registro SPF de tu dominio raíz para Emailit. Conserva tu registro DMARC. Consulta [Registros DNS de los dominios de envío](/es/docs/domains/dns-records/).

Después del cambio definitivo, elimina los registros DKIM y de seguimiento de Mailgun, y quita `include:mailgun.org` de tu registro SPF. Si recibes correo a través de las rutas de Mailgun, conserva sus registros MX hasta que hayas trasladado ese tráfico a los [emails entrantes de Emailit](/es/docs/inbound/set-up/), que reciben en un subdominio como `inbound.acme.com`.

## Próximos pasos

- [Lista de comprobación para pasar a producción](/es/docs/get-started/go-live/)
- [Configurar un webhook](/es/docs/webhooks/set-up/)
- [Migración prioritaria](/es/docs/programs/priority-migration/): deja que los ingenieros de Emailit hagan la migración contigo

---
Fuente: https://emailit.com/es/docs/migrate/mailgun/
