# Migrare da MailerSend

Questa pagina mappa il payload di invio, le liste di soppressione e i webhook di MailerSend su Bird. Segui la [guida principale alla migrazione](/docs/guides/email/migrate) nell'ordine indicato e usa queste corrispondenze per i passaggi 1, 3 e 4.

MailerSend mantiene cinque liste di soppressione e una di queste è temporanea per design. Leggi [Esportare le soppressioni](#esportare-le-soppressioni) prima del passaggio 3: importarla trasforma una sospensione di 72 ore in un blocco permanente.

## Passa questa pagina al tuo agente

Incolla questo testo in Claude Code, Cursor o Codex. L'agente lavora su questa pagina rispetto al tuo repository, usando qualsiasi superficie Bird già disponibile: il server MCP se è connesso, la CLI se è installata e autenticata.

```text
I am moving an email integration from MailerSend to Bird. Route through it with me.
1. Check what you already have before setting anything up. If Bird's MCP server is connected, use its tools. If the Bird CLI is installed and signed in, use that. Either one is enough, and every step below is an action you take with whichever you have. Only if neither is present, follow https://bird.com/docs/ai/set-up-your-agent.md to set one up and sign me in. Every Bird docs page serves Markdown at its own URL with `.md` appended, so fetch that rather than the HTML.
2. Read https://bird.com/docs/guides/email/migrate/mailersend.md for the payload, suppression and webhook mapping, and https://bird.com/docs/guides/email/migrate.md for the order the steps go in.
3. Find and list my MailerSend usage in this repository before you change anything: calls to /v1/email and any SDK wrappers around them, whether I send with template_id and personalization or with html, the webhook handler and the URL it is registered at, and every domain I send from. Tell me the list before you edit anything.
4. Register each of those sending domains with Bird and give me the DNS records to publish, following https://bird.com/docs/guides/email/sending-domains.md. Leave every DNS record MailerSend uses exactly as it is: Bird's records are published alongside them and both providers authenticate side by side until I switch traffic. Publishing DNS affects mail for the whole domain, so show me the records and let me publish them.
5. Export my suppressions and import them into Bird before any production traffic goes through Bird, so my first sends do not reach addresses that already bounced or complained. MailerSend keeps five lists under /v1/suppressions: hard bounces, spam complaints, unsubscribes and the blocklist are the four to carry over. Do NOT import the On Hold list: it is a temporary 72-hour hold that MailerSend clears by itself, and importing it would suppress those addresses permanently. The Bird import takes one address per request and is idempotent, so a partial re-run is safe. https://bird.com/docs/guides/email/suppressions.md has the reason taxonomy.
6. Port the send call and the webhook handler using the mapping tables on the provider page. Both providers sign with HMAC-SHA256, so this is a re-implementation rather than new code: MailerSend sends one Signature header, Bird follows the Standard Webhooks scheme with webhook-id, webhook-timestamp and webhook-signature, and the signed string is constructed differently. Keep the constant-time comparison. https://bird.com/docs/guides/webhooks.md and https://bird.com/docs/guides/email/events.md.
7. Run my whole integration against Bird's mail sandbox before any production traffic, following https://bird.com/docs/guides/email/testing-sandbox.md. Sandbox sends run the real pipeline without reaching an inbox or touching my sending reputation.
8. Stop and ask me wherever a step needs a decision. Do not point production traffic at Bird until I have seen the sandbox results and replied with the words cut over to Bird. Retiring the MailerSend path is a separate step that comes later: ask me again and wait for me to reply with the words retire the MailerSend path. A reply that agrees without naming what it is authorising is not authorisation. Finish by telling me what is left that only a person can do.
```

## Mappare la chiamata di invio

`POST /v1/email` di MailerSend e il nostro [`POST /v1/email/messages`](/docs/api/reference/create-email-message) condividono la stessa struttura. Le differenze che richiedono codice sono il limite dei tag e il modo in cui i dati per destinatario vengono trasportati.

| Funzione              | MailerSend                                                 | Bird                                                    |
| --------------------- | ---------------------------------------------------------- | ------------------------------------------------------- |
| Mittente              | `from` (`{email, name}`)                                   | `from`                                                  |
| Destinatari           | `to` (max 50), `cc` / `bcc` (max 10 ciascuno)              | `to` / `cc` / `bcc` (array)                             |
| Oggetto               | `subject` (max 998 caratteri)                              | `subject`                                               |
| Corpo                 | `html` / `text`                                            | `html` / `text` (almeno uno)                            |
| Reply-to              | `reply_to` (`{email, name}`)                               | `reply_to` (array)                                      |
| Header personalizzati | `headers` (`{name, value}`, piani superiori)               | `headers` (oggetto stringa → stringa)                   |
| Etichette filtrabili  | `tags` (array di stringhe, max 5)                          | coppie `tags`: `{name, value}`                          |
| Template salvato      | `template_id` + `personalization`                          | `template` + `template.parameters` (vedi sotto)         |
| Allegati              | `attachments` (`content`, `filename`, `disposition`, `id`) | `attachments`                                           |
| Pianificazione        | `send_at` (fino a 72 ore in anticipo)                      | `scheduled_at`                                          |
| Precedenza bulk       | `precedence_bulk`                                          | (nessun equivalente, vedi sotto)                        |
| Categoria             | (nessuna)                                                  | `category`: `marketing` (predefinito) o `transactional` |
| Threading             | `in_reply_to`                                              | `headers`                                               |

I limiti e i valori predefiniti dei campi (conteggio destinatari, limiti di tag e metadati) si trovano in [Invio email](/docs/guides/email/sending-email).

Note di porting:

- **Gli indirizzi sono oggetti in MailerSend e stringhe qui.** `{"email": "a@x.com", "name": "A"}` diventa `"A <a@x.com>"` o semplicemente `"a@x.com"`, per `from`, `to`, `cc`, `bcc` e `reply_to` allo stesso modo.
- **`tags` sono stringhe semplici con un massimo di cinque. I nostri tag sono coppie.** Un tag come `"welcome"` diventa `{"name": "category", "value": "welcome"}`. Scegli un `name` stabile in modo che le tue dashboard filtrino come facevano le statistiche dei tag di MailerSend.
- **`personalization` contiene dati di template per destinatario.** È un array indicizzato per email del destinatario. Il nostro `template.parameters` si applica all'intero invio, quindi un messaggio il cui contenuto differisce realmente per destinatario diventa un invio per destinatario o una voce [batch](/docs/guides/email/sending-bulk) ciascuno. Se il tuo array `personalization` contiene gli stessi valori per ogni destinatario, si riduce a un singolo oggetto `template.parameters`.
- **Il contesto di round-trip non ha un equivalente MailerSend da copiare.** Se ricostruivi il contesto a partire da `tags`, usa invece [`metadata`](/docs/guides/email/sending-email): lo restituiamo in ogni evento webhook insieme a `email_id`/`recipient_id`, e non ha un limite di cinque voci.
- **`precedence_bulk` non ha un equivalente, e `category` non lo è.** `precedence_bulk` imposta un header `Precedence: bulk`, che chiede agli autoresponder e agli agenti di out-of-office di non rispondere. Il nostro `category` decide quali record di soppressione e preferenze di disiscrizione possono bloccare un messaggio, e nient'altro. Impostare `category` al suo posto cambia il comportamento di soppressione e non ha alcun effetto sugli autoresponder. Se hai bisogno dell'header, nota che `headers` rifiuta indirizzi e nomi di piattaforme, ma non questo.
- **Gli header personalizzati e `list_unsubscribe` sono vincolati al piano in MailerSend.** Se il tuo piano non li includeva, qui sono disponibili; consulta [invio email](/docs/guides/email/sending-email) e [categorie](/docs/guides/email/categories) per come gestiamo list-unsubscribe sulla posta di marketing.

## Esportare le soppressioni

MailerSend mantiene cinque liste sotto `/v1/suppressions`, un endpoint per lista. Quattro sono permanenti e vanno migrate; la quinta no.

Esporta e processa con il [ciclo di importazione](/docs/guides/email/migrate#3-import-suppressions):

- **Hard bounce**, ad esempio `GET https://api.mailersend.com/v1/suppressions/hard-bounces`
- **Segnalazioni di spam**
- **Disiscrizioni**
- **Blocklist**, gli indirizzi e i pattern che hai aggiunto manualmente

**Non importare la lista On Hold.** La descrizione stessa di MailerSend dice che contiene indirizzi che "have soft bounced 5 times within 30 days", che "these emails will be blocked for 72 hours", e che vengono poi "automatically removed from the list". È un periodo di raffreddamento che il provider cancella da solo, quindi importarla converte una sospensione temporanea in una soppressione permanente e interrompe silenziosamente l'invio verso indirizzi che stavano per essere rilasciati. Il nostro equivalente di questo comportamento è il [deferral](/docs/guides/email/events), che gestiamo a partire dagli esiti di consegna in tempo reale e non da una lista importata.

I tipi di lista di MailerSend corrispondono ai nostri motivi `hard_bounce`, `complaint` e `manual`; [Soppressioni](/docs/guides/email/suppressions) contiene la tassonomia completa.

## Tradurre gli eventi webhook

| Esito                  | MailerSend                                     | Bird                                             |
| ---------------------- | ---------------------------------------------- | ------------------------------------------------ |
| Accettato/elaborato    | `activity.sent`                                | `email.accepted` → `email.processed`             |
| Consegnato             | `activity.delivered`                           | `email.delivered`                                |
| Errore temporaneo      | `activity.soft_bounced` / `activity.deferred`  | `email.deferred`                                 |
| Bounce permanente      | `activity.hard_bounced`                        | `email.bounced` / `email.out_of_band_bounce`     |
| Segnalazione di spam   | `activity.spam_complaint`                      | `email.complained`                               |
| Apertura               | `activity.opened` / `activity.opened_unique`   | `email.opened`                                   |
| Click                  | `activity.clicked` / `activity.clicked_unique` | `email.clicked`                                  |
| Disiscrizione          | `activity.unsubscribed`                        | `email.unsubscribed` / `email.list_unsubscribed` |
| Sospensione temporanea | `recipient.on_hold_added` / `..._removed`      | (nessun equivalente; vedi sopra)                 |

Due differenze determinano quanto cambia il tuo handler.

**Entrambi i lati firmano con HMAC-SHA256, quindi si tratta di una reimplementazione, non di codice nuovo.** MailerSend invia un singolo header `Signature` contenente un hash del payload calcolato con il signing secret di quel webhook. Noi seguiamo lo schema [Standard Webhooks](https://www.standardwebhooks.com), che usa `webhook-id`, `webhook-timestamp` e `webhook-signature` e firma una stringa costruita dall'id, dal timestamp e dal body, così il timestamp ti offre anche protezione contro il replay. Mantieni il confronto in tempo costante che hai già e sostituisci la costruzione; la procedura è in [Webhook ed eventi](/docs/guides/webhooks).

**MailerSend distingue aperture e click dalle rispettive varianti uniche. Noi no.** `activity.opened` e `activity.opened_unique` arrivano entrambi come `email.opened`, quindi un handler che contava solo la variante unica deve deduplicare su `recipient_id` direttamente. I nostri eventi di consegna sono a livello di destinatario, quindi un invio a tre destinatari produce tre esiti di consegna anziché uno.

## Passaggio in produzione

Segui [domini e DNS](/docs/guides/email/migrate#2-re-point-domains-and-dns) e lo [smoke test in sandbox](/docs/guides/email/migrate#5-verify-in-the-sandbox-before-cutover) nella guida principale. Entrambi sono indipendenti dal provider.

## Passi successivi

- [Domini di invio](/docs/guides/email/sending-domains): registrazione, ciclo di vita della verifica e i record DNS che stai pubblicando
- [Webhook ed eventi](/docs/guides/webhooks): configurazione dell'endpoint e verifica Standard Webhooks
- [Sandbox di test](/docs/guides/email/testing-sandbox): testa la nuova integrazione prima del passaggio in produzione
- [Soppressioni](/docs/guides/email/suppressions): verifica la lista importata e come la manteniamo da qui in poi

## Related resources

- [Getting started with email](/learn/email/getting-started-with-email) (video)
- [Email](/email-api) (product)
- [Build your first integration](/learn/paths/integration) (course)
- [Send your first email](/docs/get-started/send-your-first-email) (docs)

[Get an implementation brief](/learn/workspace?topic=email)
