Migreren vanaf Mandrill
Deze pagina vertaalt Mandrills (Mailchimp Transactional) messages/send-payload, rejection blacklist en webhooks naar Bird. Volg de hoofdmigratiegids op volgorde en gebruik deze mappings voor stap 1, 3 en 4.
Twee structuurwijzigingen domineren de port. Mandrill nest alles onder een message-object en authenticeert met een key in de request body. Wij gebruiken een platte top-level payload en een standaard Authorization: Bearer-header. En Mandrills type voor ontvangers (to/cc/bcc als veld op elk adres) wordt bij ons drie aparte to/cc/bcc-arrays.
Geef dit aan je agent
Plak dit in Claude Code, Cursor of Codex. De agent werkt deze pagina door tegen je eigen repository, met het Bird-oppervlak dat hij al heeft: de MCP-server als er een is verbonden, de CLI als die is geïnstalleerd en ingelogd.
Codevoorbeeld
I am moving an email integration from Mandrill 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/mandrill.md for the payload, suppression and event mapping, and https://bird.com/docs/guides/email/migrate.md for the order the steps go in.
3. Find and list my Mandrill usage in this repository before you change anything: the messages/send and messages/send-template call sites and any SDK wrappers around them, the webhook handler and the URL it is registered at, and every domain I send from. Mandrill authenticates with an API key passed in the request body rather than a header, so tell me every place that key appears in my code: the port changes how I authenticate, not just what I send, and that key is a secret currently sitting in a payload.
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 my current provider 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 rejects from Mandrill 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. Read the list through rejects/list, and skip the soft-bounce rows: those are transient failures rather than suppressions, and importing them would suppress addresses that are fine. Show me how many rows you skipped. 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. Move the API key out of the request body and into the Authorization header as a bearer token while you are there. Bird signs deliveries per Standard Webhooks rather than Mandrill's scheme, so treat verification as a rewrite rather than a URL change: 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 Mandrill path is a separate step that comes later: ask me again and wait for me to reply with the words retire the Mandrill 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.Vertaal de send-call
| Wat het doet | Mandrill (messages/send) | Bird |
|---|---|---|
| Auth | key in request body | Authorization: Bearer bk_...-header |
| Afzender | message.from_email / from_name | from: string of { "email", "name" } |
| Ontvangers | message.to: [{ email, name, type }] | to / cc / bcc: gesplitst op het type-veld |
| Onderwerp | message.subject | subject |
| Body | message.html / message.text | html / text (minstens één) |
| Reply-to | message.headers["Reply-To"] | reply_to: array |
| Aangepaste headers | message.headers | headers: string → string object |
| Filterbare labels | message.tags: kale strings | tags: { name, value }-paren |
| Round-trip context | message.metadata | metadata: willekeurig JSON |
| Opgeslagen template | messages/send-template + merge_vars | template + template.parameters |
| Inplannen | send_at | scheduled_at |
| Open-/kliktracking | message.track_opens / track_clicks | track_opens / track_clicks (standaard true) |
| Bijlagen | message.attachments: { type, name, content } | attachments: { content_type, filename, content } |
| Inline afbeeldingen | message.images: { type, name, content } | attachments met content_id |
| Categorie | subaccount / tags-conventie | category: marketing (standaard) of transactional |
Onze veldlimieten en standaardwaarden (aantallen ontvangers, tag- en metadatalimieten) staan in E-mail verzenden.
Opmerkingen bij het porten:
- Maak plat en herauthenticeer. Verwijder de message-wrapper (de velden gaan naar het toplevel) en verplaats de API-key van de body naar de Authorization-header. Het key-veld heeft hier geen equivalent.
- Splits ontvangers op type. Mandrill markeert elke ontvanger als to, cc of bcc op het adresobject. Wij gebruiken drie aparte arrays. Verdeel de to-lijst op het type-veld terwijl je port.
- Tags worden naam/waarde-paren. Mandrill-tags zijn kale strings ("welcome"). Onze tags zijn { name, value }-paren. Kies een vaste name, bijvoorbeeld { "name": "category", "value": "welcome" }, zodat je filters en analytics op dezelfde manier groeperen als je Mandrill-statistieken deden. metadata port direct over als JSON.
- Opgeslagen templates porten, met één kanttekening. Mandrills messages/send-template wordt ons template-veld (gerefereerd op ID of slug) met waarden in template.parameters. Zie verzenden met een template. Onze templatevariabelen zijn per bericht in plaats van per ontvanger, dus per-ontvanger merge_vars worden één batch-entry per ontvanger, elk met een eigen parameters.
- Bijlagen porten direct. Mandrills base64 content is onze content, en inline images (gerefereerd als cid: in de HTML) worden attachments-entries met content_id. Zie bijlagen.
Exporteer suppressions
Mandrill bewaart ongewenste adressen op zijn rejection blacklist. Haal die op met de rejects/list API (of exporteer vanuit de Rejection Blacklist-weergave). Elke entry heeft een reden (hard-bounce, soft-bounce, spam, unsub, custom). Sla de soft-bounce-rijen over omdat die tijdelijke fouten beschrijven in plaats van echte suppressions. Voer de rest door de importlus.
Vertaal webhook-events
Mandrill post gebatchte event-arrays; vertaal de event-waarde naar de eventvocabulaire van Bird:
| Resultaat | Mandrill | Bird |
|---|---|---|
| Verzonden / geaccepteerd | send | email.accepted → email.processed |
| Afgeleverd | delivered | email.delivered |
| Tijdelijke fout | deferral | email.deferred |
| Permanente bounce | hard_bounce | email.bounced / email.out_of_band_bounce |
| Soft bounce | soft_bounce | email.deferred (daarna email.bounced als het opgeeft) |
| Spamklacht | spam | email.complained |
| Uitschrijving | unsub | email.unsubscribed / email.list_unsubscribed |
| Geweigerd/geblokkeerd | reject | email.rejected |
| Open | open | email.opened |
| Klik | click | email.clicked |
Twee verschillen om rekening mee te houden in je code:
- Acceptatie splitst hier in twee events. Mandrills send betekent dat het bericht is ingevoerd en delivered betekent dat de ontvangende server het heeft aangenomen; dat is hetzelfde onderscheid dat wij maken. Het verschil zit alleen aan onze kant: wij scheiden acceptatie (email.accepted) van verwerking (email.processed) vóór email.delivered, dus een handler die alleen op send keyde heeft nu twee events om uit te kiezen.
- Events zijn per ontvanger en anders ondertekend. Onze delivery-events hebben recipient_id naast email_id, met één stream per ontvanger. We leveren één event per request en ondertekenen het volgens de Standard Webhooks-specificatie. Mandrill ondertekent in plaats daarvan gebatchte arrays met een X-Mandrill-Signature HMAC. Zie Webhooks & events voor verificatie.
Overschakelen
Doorloop domeinen & DNS en de sandbox-rooktest in de hoofdgids. Beide zijn provideronafhankelijk.
Vervolgstappen
- Verzenddomeinen: registratie, verificatielevenscyclus en de DNS-records die je opnieuw richt
- Webhooks & events: endpoint-setup en Standard Webhooks-verificatie
- Testsandbox: rooktest de nieuwe integratie vóór de overschakeling
- Suppressions: controleer je geïmporteerde lijst en hoe we die vanaf hier onderhouden
Gerelateerde bronnen
Ga verder met de documentatie, gidsen en voorbeelden voor dit onderwerp. De bronnen zijn in het Engels.
Bekijk de gidsGetting started with emailOntdek de mogelijkheidEmailVolg het leerpadBuild your first integrationImplementatiegidsSend your first email
Probeer de oefening en ontvang een implementatieoverzicht