# Migrar do Mailgun

> Guia para sair do Mailgun e ir para o Couryo. Mapeamento do envio por formulário (from, to, o:tag, v:, h:, o:deliverytime, template e recipient-variables) para JSON, dos eventos dos webhooks, das supressões, das routes de recebimento e a troca de DNS.

Fonte: https://couryo.com/docs/migrate-mailgun

O Mailgun recebe o envio como formulário (`multipart/form-data`), com opções em prefixos como `o:`, `h:` e `v:`. O Couryo recebe JSON, com um campo para cada coisa. Siga a [ordem segura da migração](https://couryo.com/docs/migration.md) e use este guia para traduzir cada parte.

## A chamada de envio

```bash title="Mailgun: POST https://api.mailgun.net/v3/exemplo.com.br/messages"
curl -s --user "api:$MAILGUN_API_KEY" \
  https://api.mailgun.net/v3/exemplo.com.br/messages \
  -F from="Loja <pedidos@exemplo.com.br>" \
  -F to="ana@exemplo.com.br" \
  -F subject="Pedido 1042 confirmado" \
  -F text="Obrigado, Ana!" \
  -F html="<p>Obrigado, Ana!</p>" \
  -F o:tag="pedido" \
  -F v:pedido_id="1042"
```

```bash title="Couryo: POST https://api.couryo.com/v1/emails"
curl https://api.couryo.com/v1/emails \
  -H "Authorization: Bearer $COURYO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-1042-confirmacao" \
  -d '{
    "from": "Loja <pedidos@exemplo.com.br>",
    "to": "ana@exemplo.com.br",
    "subject": "Pedido 1042 confirmado",
    "text": "Obrigado, Ana!",
    "html": "<p>Obrigado, Ana!</p>",
    "tags": { "categoria": "pedido" },
    "metadata": { "pedido_id": "1042" }
  }'
```

No Mailgun, o domínio vai no endereço e a autenticação é `api:` + a chave. No Couryo, o endereço é sempre o mesmo, a chave vai em `Authorization: Bearer` e o domínio sai do `from`. A resposta é `202 { "id": "msg_...", "status": "queued" }`.

## Campos

| Mailgun | Couryo | Observação |
|---|---|---|
| `from`, `to`, `cc`, `bcc`, `subject`, `text`, `html` | os mesmos nomes | em JSON; `to` aceita texto ou lista, até 50 destinatários somando `cc` e `bcc` |
| `h:Reply-To` | `reply_to` | |
| `h:X-Qualquer` | `headers: { "X-Qualquer": "..." }` | |
| `o:tag` (vários) | `tags` | chave e valor, por exemplo `{ "categoria": "pedido" }` |
| `v:chave` ou `h:X-Mailgun-Variables` | `metadata` | volta em todo webhook (no Mailgun, `user-variables`) |
| `o:deliverytime` (RFC 2822) | `scheduled_at` (ISO 8601, até 30 dias) | dá para [reagendar e cancelar](https://couryo.com/docs/sending.md#reagendar-ou-cancelar) |
| `o:testmode` | chave `ck_test_` | captura sem entregar, com eventos simulados |
| `o:tracking`, `o:tracking-opens`, `o:tracking-clicks` | [rastreio do projeto](https://couryo.com/docs/tracking.md) | ligado no marketing, desligado no transacional por padrão |
| `attachment`, `inline` (arquivos) | `attachments[]` com `content` em Base64; imagem no corpo com `content_id` | |
| `template` + `t:variables` | `template` + `variables` | recrie o template no Couryo (veja abaixo) |
| `recipient-variables` (envio em lote) | `POST /v1/emails/batch` | um item por destinatário, até 100 por chamada |
| `o:require-tls`, `o:dkim` | sempre | TLS e DKIM do seu domínio em todo envio |

## Templates

Os templates do Mailgun usam Handlebars. No Couryo, as variáveis são `{{nome}}` e `{{pedido.total}}`, com valor padrão opcional (`{{nome|cliente}}`); blocos como `{{#if}}` e `{{#each}}` não existem. Recrie cada template em **Templates** (HTML, MJML ou o editor visual) e mande `template` com o nome ou o id e `variables`.

## Eventos e webhooks

| Mailgun | Couryo |
|---|---|
| `accepted` | `accepted` e `queued` |
| `delivered` | `delivered` |
| `failed` com `severity: temporary` | `deferred` |
| `failed` com `severity: permanent` | `bounced` (ou `suppressed`, quando o endereço já estava suprimido) |
| `complained` | `complained` |
| `opened` | `opened` |
| `clicked` | `clicked` |
| `unsubscribed` | não vira evento: o endereço entra na supressão de marketing (`GET /v1/suppressions?reason=unsubscribe`) |

O Mailgun assina com `timestamp`, `token` e `signature` dentro do corpo. O Couryo assina no padrão [Standard Webhooks](https://couryo.com/docs/webhooks.md), nos cabeçalhos `webhook-id`, `webhook-timestamp` e `webhook-signature` (HMAC-SHA256), e tenta de novo por até 3 dias. Um webhook do Couryo assina os eventos que você escolher, para todos os domínios do projeto.

## Supressões, listas e recebimento

- Exporte do Mailgun as listas **Bounces** e **Complaints** e cadastre no Couryo com `stream: "all"`; **Unsubscribes** entram com `stream: "marketing"`. O laço está em [copiar as supressões](https://couryo.com/docs/migration.md#copiar-as-supressoes).
- Mailing lists: exporte os membros em CSV e [importe como contatos](https://couryo.com/docs/contacts.md#importar-por-csv), com a confirmação de consentimento. Cada lista vira uma tag ou um [tópico](https://couryo.com/docs/contacts.md#topicos-e-preferencias).
- Routes de recebimento: no Couryo, o [inbound](https://couryo.com/docs/inbound.md) (planos Pro e acima) recebe num subdomínio, como `reply.exemplo.com.br`, e entrega cada mensagem no webhook `email.received`.

## DNS

O Mailgun pede um `include:` no SPF do domínio, uma chave DKIM com seletor próprio, o CNAME de rastreio (`email.`) e, para receber, MX apontando para ele. O Couryo usa `couryo1._domainkey`, `couryo2._domainkey` e `bounces`, e não pede nada no SPF do domínio principal, então os dois ficam publicados juntos durante a migração.

1. Publique os registros do Couryo e espere o domínio ficar verificado.
2. Mantenha o DMARC que você já tem; para receber os relatórios no [agente de entregabilidade](https://couryo.com/docs/deliverability.md), acrescente `mailto:reports@dmarc.couryo.com` ao `rua`.
3. Se você recebe e-mail pelo Mailgun (routes), **não troque o MX do domínio principal** sem antes ter para onde as mensagens irem. O inbound do Couryo usa um subdomínio próprio.
4. Depois que todo o tráfego estiver no Couryo e se passarem 7 dias, apague a chave DKIM do Mailgun, o CNAME de rastreio e o `include:` dele no SPF (se nada mais usar).
