Migration illustration Migration guide

Migrate to Mailtrap from Mailgun

A complete technical guide to switching from Mailgun to Mailtrap. Most teams complete the migration in under an hour.

Migration Checklist

  1. Authenticate your domain
    Add and verify your domain before sending. Follow the Domain Setup article at docs.mailtrap.io.

Need some help?

Contact our support and our developers will help you with it.

Need some help?
  1. Get your API token
    Mailtrap auto-generates a token when you add a domain. Find it under Settings → API Tokens. Read more on API tokens.
  2. Update your integration
    Swap your Mailgun endpoints and credentials for Mailtrap’s (API or SMTP). See the migration sections below.
  3. Migrate templates
    Both platforms use Handlebars, so content migrates directly. Update t:variablestemplate_variables and string names → template_uuid.
  4. Migrate suppressions
    Export Mailgun suppressions and import them into Mailtrap via CSV or manually. Click here for more information.
  5. Migrate users
    Add users from the User Management tab. Mailgun’s 5 role types don’t map 1:1 to Mailtrap roles, so review permissions during migration.
  6. Set up webhooks
    Follow the Mailtrap Webhooks step-by-step guide.
  7. Security and compliance
    Visit the Trust Center page to review Mailtrap’s security practices and compliance standards.

Mailtrap tip

You can use ActionMailer Balancer Ruby gem to proportionally distribute the email sending load between two different sending services (e.g. 70% Mailgun and 30% Mailtrap) to mitigate the sending risks.

 

Mailtrap tip

Concepts

Before going over the technical details, it’s important to clear up some key concepts.

Sending domains

Mailgun equivalent: Domain Verification (with Automatic Sender Security for managed DKIM)

Before being able to send emails with Mailtrap, you first need to add and verify your sending domain. For domain verification, Mailtrap provides DNS records, which are the same standards Mailgun relies on. 

DKIM records can be added alongside Mailgun’s (different selectors, no conflict), and one DMARC record covers both. For SPF, however, you must merge Mailtrap’s include into your existing SPF record rather than adding a separate one.

To learn how to verify your domain, you can read our step-by-step Knowledge base article, or watch the video we prepared for you. The whole process takes ~15 minutes.

Note: Even if your domain is already authenticated in Mailgun, you’ll need to add it to Mailtrap separately. Existing DNS records may need to be replaced or consolidated; you can’t use them as-is.  

Separate sending streams

Mailgun equivalent: N/A

Mailtrap provides two separate email infrastructures, or sending streams:

  • Transactional Stream – For sending user-triggered emails like welcome emails and password resets.
  • Bulk Stream – For sending promotional, marketing emails like newsletters and product updates.

By keeping the sending infrastructures separate, you are able to:

  • Protect your transactional email reputation from the performance of your bulk campaigns
  • Ensure each stream routes through the right IP pools
  • Give mailbox providers the signals they need to categorize and deliver your emails correctly
Image

Email categories

Mailgun equivalent: Tags (o:tag parameter)

Like Mailgun’s Tags, Mailtrap offers an Email Categories feature that lets you track the performance of different types of emails (e.g., welcome emails, password resets, etc.).

  • Using Email Categories with Mailtrap: Insert a category name into the X-MT-Category header (SMTP) or pass the category name in the category field (API).
  • Using Tags with Mailgun: Pass tags via the o:tag form parameter (API), or use the X-Mailgun-Tag header (SMTP). Mailgun supports multiple tags per message.
Image

Organization & sub-accounts

Mailgun equivalent: Subaccounts + Multi-User Access with Roles

Mailtrap offers its Organization & Sub-accounts feature from Business plan onwards. It lets you manage complex setups involving multiple teams, clients, environments, or products under a single Organization. To start using the feature, you first need to enable it under the Organization tab.

Image

Notes

  • Mailgun provides Subaccounts (Enterprise-only) for fully isolated child environments with separate domains, IP pools, and API keys. Multi-user access uses Role-Based Access Control with 4 role types – Admin, Developer, Analyst, and Support – also available on Enterprise and select Business plans.
  • With Mailtrap the feature is available to from Business plan onward.

Terminology comparison

*Mailgun’s Events API has been deprecated. 
**Mailgun’s old Tags API has been deprecated.

API migration

Authentication

Both Mailtrap and Mailgun authenticate API requests using an API key passed in the Authorization header. The key difference is the method:

MailgunMailtrap
MethodHTTP Basic AuthAPI token (Bearer token)
Header formatAuthorization: Basic base64(“api:YOUR\_API\_KEY”)Authorization: Bearer YOUR\_MAILTRAP\_API\_KEY

When migrating, change your authentication from Basic Auth to Bearer token format.

Note: Mailtrap automatically creates a token when you add a domain. By default, the token has Domain Admin access permission. Add or remove token permissions in the API Tokens menu under Settings.

API mapping

API typeMailgunMailtrapNotes
Transactional emailPOST /v3/{domain}/messages(api.mailgun.net)/api/send(send.api.mailtrap.io)Mailtrap uses JSON body; Mailgun uses multipart/form-data.
Bulk emailPOST /v3/{domain}/messages(with recipient-variables)/api/send(bulk.api.mailtrap.io)Mailtrap uses a separate bulk endpoint; Mailgun uses batch sending.
TemplatesTemplates API (template string name)POST https\://send.api.mailtrap.io/api/send (with template\_uuid)Mailgun identifies templates by name; Mailtrap uses UUID.
SuppressionsThree separate APIs: Bounces, Complaints, UnsubscribesGET https\://mailtrap.io/api/accounts/{account\_id}/suppressionsMailtrap consolidates; Mailgun splits into three endpoint groups.
StatsMetrics API POST /v1/analytics/metrics |GET /api/accounts/{account_id}/stats,/stats/domains,/stats/categories,/stats/email_service_providers, and/stats/date`Mailgun deprecated its legacy Stats API in favor of Metrics API.
Email logsEvents API GET /v3/{domain}/eventsGET https\://mailtrap.io/api/accounts/{account\_id}/email\_logsMailgun retains data for 30 days on paid plans, 2 days on free.

Outbound Sending API JSON Field Mapping

Mailgun: POST /v3/{domain}/messages with multipart/form-data

Mailtrap: POST /api/send with application/json

FieldMailgun (form parameter)Mailtrap (JSON field)
Senderfromfrom (object: email, name)
Recipientstoto (array of objects: email, name)
CCcccc (array of objects: email, name)
BCCbccbcc (array of objects: email, name)
Reply-Toh:Reply-Toreply\_to (object: email, name)
Subjectsubjectsubject
Plain text bodytexttext
HTML bodyhtmlhtml
AMP HTML bodyamp-html
Tag / Categoryo:tag (multiple allowed)category (single string)
Custom variablesv:my-var (prefix-based)custom\_variables (object)
Custom headersh:X-My-Header (prefix-based)headers (object)
Recipient variables (batch)recipient-variables (JSON string)
Template name / IDtemplate (name string)template\_uuid (UUID string)
Template variablest:variables (JSON string)template\_variables (object)
Template versiont:version
Template render textt:text (yes/no)
File attachmentattachment (file upload, multiple)attachments (array: content, filename, type, disposition, content_id)
Inline / embedded imageinline (file upload)attachments with disposition: “inline” and content_id
Enable trackingo:tracking (yes/no)
Track clickso:tracking-clicks (yes/no/htmlonly)
Track openso:tracking-opens (yes/no)
Require TLSo:require-tls (yes/no)
Skip TLS verificationo:skip-verification (yes/no)
DKIM toggleo:dkim (yes/no)
Secondary DKIMo:secondary-dkim
Scheduled deliveryo:deliverytime (RFC 2822 / Unix)
Send time optimizationo:deliverytime-optimize-period
Timezone localizeo:time-zone-localize
Test modeo:testmode (yes/no)
Sending IPo:sending-ip
Sending IP poolo:sending-ip-pool
Tracking pixel positiono:tracking-pixel-location-top
Suppress headerso:suppress-headers
Sending streamsend.api.mailtrap.io (transactional) or bulk.api.mailtrap.io (bulk)
Batch sendPOST /api/batch (up to 500 emails)

Code snippets

  • Mailtrap cURL SDK code snippet cURL
Mailgun Mailgun
curl -s --user 'api:YOUR_API_KEY' \
  https://api.mailgun.net/v3/YOUR_DOMAIN/messages \
  -F from='Sender <sender@YOUR_DOMAIN>' \
  -F to='recipient@example.com' \
  -F subject='Hello from Mailgun' \
  -F text='Welcome to Mailgun!'
Mailtrap Mailtrap

Copy

curl -X POST https://send.api.mailtrap.io/api/send \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "from": {"email": "sender@example.com"},
    "to": [{"email": "recipient@example.com"}],
    "subject": "Hello from Mailtrap",
    "text": "Welcome to Mailtrap!"
  }'

Note:

  • Content type: Mailtrap accepts application/json; Mailgun uses multipart/form-data.
  • Auth method: Mailtrap uses Bearer token; Mailgun uses Basic Auth (–user).
  • Domain in URL: Mailgun requires the sending domain in the API path (/v3/{domain}/messages); Mailtrap does not.
  • Regional endpoints: Mailgun has separate API hosts for US and EU. Mailtrap uses a single global endpoint.

SMTP migration

SettingMailgunMailtrap (Transactional)Mailtrap (Bulk)
Hostsmtp.mailgun.orglive.smtp.mailtrap.iobulk.smtp.mailtrap.io
Port587 (recommended), 465, 25, 2525587 (recommended), 25, 2525587 (recommended), 25, 2525
TLSSTARTTLS on 587/25/2525; implicit SSL on 465RequiredRequired
AuthenticationPLAIN, LOGINPLAIN, LOGINPLAIN, LOGIN
UsernameFull email addressapi stringapi string
PasswordSMTP-specific passwordAPI tokenAPI token

Migration notes:

  • Mailtrap uses separate SMTP hosts for transactional (live.smtp.mailtrap.io) and bulk (bulk.smtp.mailtrap.io) streams. Mailgun uses a single host (smtp.mailgun.org) for all sending.
  • The SMTP username differs: Mailtrap uses the literal string api, while Mailgun uses a full email address credential (e.g., postmaster@yourdomain.com).
  • Mailgun’s SMTP credentials are managed per-domain and are separate from API keys. Mailtrap uses the same API token for both API and SMTP authentication.
Image

For more information on migrating your SMTP configuration, click this link. ⬅️

Rate limits & quotas

LimitMailgunMailtrap
API rate limit (mail send endpoint)~500 requests per 10 seconds150 requests per 10 seconds per API token
Batch size1,000 recipients per API call500 emails per batch call
Message size limit (incl. attachments)25 MB10 MB default (extendable to 30 MB on request)
Max recipients per send1,000 (via batch sending)Single send ( /api/send ) → 1 email, up to 1,000 recipients per field ( to / cc / bcc )
Batch send ( /api/batch ) → up to 500 separate emails per API call

Email templates

Both Mailtrap and Mailgun use Handlebars syntax, so variable insertion ({{variable}}), conditionals, loops, and nested objects work identically and require no changes when migrating.

The differences only appear in a few specific cases:

Syntax comparison

PatternMailgunMailtrap
Default/fallback valueSame approach – no built-in default helper{{#if firstName}}{{firstName}}{{else}}there{{/if}}
Date formattingNot supported – format before passingNot supported – format before passing
Pass variables via APIt:variables (form parameter, JSON string)template_variables
Template identifiertemplate (string name, e.g., my-template)template_uuid
Template versioningSupported via t:version parameterN/A

Migration notes: Mailgun has a separate variable system for batch sending that uses %recipient.varname% syntax (percent-delimited), distinct from its Handlebars template engine. When migrating batch sends, convert these to Mailtrap’s approach.

Question icon

Frequently Asked Questions

  • Do I need to re-verify my domain if I’ve already set it up in Mailgun?

    Yes, you’ll need to re-verify your domain. See the Mailtrap Knowledge Base for up-to-date guidance.

  • Mailgun uses Basic Auth. Does Mailtrap work the same way?

    No. Mailgun authenticates with HTTP Basic Auth (api:YOUR_API_KEY). Mailtrap uses a Bearer token: Authorization: Bearer YOUR_API_KEY. You’ll need to update the auth header, not just swap the key.

  • Mailgun’s send API uses form data. Does Mailtrap accept the same format?

    Mailtrap expects a JSON request body (Content-Type: application/json), not multipart/form-data. You’ll need to restructure the request – but the field names are close. Mailgun’s html, text, subject, to, cc, and bcc all have direct Mailtrap equivalents at the root of the JSON body. The from field changes from a flat string ("Name <email>") to a {"email": "...", "name": "..."} object.

  • Why does Mailtrap have two separate SMTP hosts?

    Mailtrap separates transactional and bulk streams to protect your sender reputation and ensure proper delivery routing for each email type.

  • My Mailgun SMTP username is “postmaster@mydomain.com”. What do I use in Mailtrap?

    Mailtrap uses the literal string api as the SMTP username for both transactional and bulk streams, with your API token as the password. No per-domain SMTP credentials to manage.

  • I use multiple Mailgun “o:tag” values per email. How do I handle that in Mailtrap?

    Mailgun allows up to 3 tags per message via repeated o:tag fields. Mailtrap accepts a single category string. Pick your primary tag for the category field and move secondary tags into custom_variables as key-value metadata.

  • How do I migrate Mailgun’s “v:” custom variables?

    Mailgun’s v:my-var form fields map to Mailtrap’s custom_variables JSON object. Instead of -F v:campaign-id="abc123", pass "custom_variables": {"campaign-id": "abc123"} in the JSON body. These will appear in webhook payloads the same way Mailgun’s user-variables do.

  • Does Mailtrap support Mailgun’s Recipient Variables for batch sending?

    Not with the same %recipient.var% syntax. Mailgun lets you send to up to 1,000 recipients in one call, personalizing each with recipient-variables and %recipient.name% placeholders. In Mailtrap, use the bulk endpoint (bulk.api.mailtrap.io/api/send) and send up to 500 emails per batch call, each as a separate object with its own recipients and template_variables.

  • Does Mailtrap offer migration assistance?

    Yes, Mailtrap offers migration assistance from Business plan onwards.

  • How do I migrate templates?

    Both platforms use Handlebars syntax, so template content migrates directly. Update API calls to use template_uuid instead of string names, and pass variables via template_variables instead of t:variables.