Mailtrap
Added in version 14.0.
Anymail integrates with Mailtrap’s Email API/SMTP (transactional) and Email Sandbox (test) email services, using the Mailtrap API v2. (Anymail uses Mailtrap’s REST-oriented HTTP API, not the SMTP protocol.)
Anymail should also work correctly with Mailtrap’s Bulk Sending service (which uses an identical API), but this scenario is not tested separately.
Note
Troubleshooting: If your Mailtrap transactional or bulk messages aren’t being delivered as expected, check the Email Logs in Mailtrap’s dashboard. The “Event History” tab for an individual message is often helpful.
Settings
To use Anymail’s Mailtrap backend, set:
EMAIL_BACKEND = "anymail.backends.mailtrap.EmailBackend" ANYMAIL = { "MAILTRAP_API_TOKEN": "<your API token>", # Only to use the Email Sandbox service: "MAILTRAP_SANDBOX_ID": <your test inbox id>, }
in your settings.py.
When MAILTRAP_SANDBOX_ID is set,
Anymail uses Mailtrap’s Email Sandbox service. If it is not set, Anymail
uses Mailtrap’s transactional Email API/SMTP service.
MAILTRAP_API_TOKEN
Required for sending:
ANYMAIL = { ... "MAILTRAP_API_TOKEN": "<your API token>", }
Anymail will also look for MAILTRAP_API_TOKEN at the
root of the settings file if neither ANYMAIL["MAILTRAP_API_TOKEN"]
nor ANYMAIL_MAILTRAP_API_TOKEN is set.
MAILTRAP_SANDBOX_ID
Required to use Mailtrap’s Email Sandbox test inbox. (And must not be set to use Mailtrap’s Email API/SMTP transactional service.)
ANYMAIL = { ... "MAILTRAP_SANDBOX_ID": 12345, }
The sandbox id can be found in Mailtrap’s dashboard: click into the desired
sandbox and look for the number in the dashboard url. For example,
https://mailtrap.io/inboxes/12345/messages would be sandbox id 12345.
The value can be a string or number. For convenience when using env files,
Anymail treats an empty string or None (or any falsy value) as “not set.”
MAILTRAP_API_URL
The base url for calling the Mailtrap API.
The default is MAILTRAP_API_URL = "https://send.api.mailtrap.io/api/"
(Mailtrap’s Email API/SMTP transactional service)
if MAILTRAP_SANDBOX_ID is not set,
or "https://sandbox.api.mailtrap.io/api/" (Mailbox’s Email Sandbox testing
service) when a sandbox id is provided.
Most users should not need to change this setting. However, you could set it to use Mailtrap’s bulk send service:
ANYMAIL = { ... "MAILTRAP_API_URL": "https://bulk.api.mailtrap.io/api/", }
(Note that Anymail is not specifically tested with Mailtrap’s bulk API.)
The value must be only the API base URL: do not include the "/send" endpoint.
(When provided, this is used as the base URL always. If you are also setting
a sandbox id, the base URL must be compatible with Mailtrap’s sandbox API.)
esp_extra support
To use Mailtrap features not directly supported by Anymail, you can
set a message’s esp_extra to
a dict of Mailtraps’s Send email API body parameters.
Your esp_extra dict will be deeply merged into the Mailtrap
API payload, with esp_extra having precedence in conflicts.
(For batch sends, the esp_extra values are merged into the "base"
payload shared by all recipients.)
Example:
message.esp_extra = { "future_mailtrap_feature": "value" }
(You can also set "esp_extra" in Anymail’s global send defaults
to apply it to all messages.)
Limitations and quirks
- Single tag
Anymail uses Mailtrap’s
"category"option for tags, and Mailtrap allows only a single category per message. If your message has two or moretags, you’ll get anAnymailUnsupportedFeatureerror—or if you’ve enabledANYMAIL_IGNORE_UNSUPPORTED_FEATURES, Anymail will use only the first tag.- Tag not compatible with template
Trying to send with both
tagsand atemplate_idwill result in a Mailtrap API error that “‘category’ is not allowed with ‘template_uuid’.”- No delayed sending
Mailtrap does not support
send_at.- Attachments require filenames
Mailtrap requires that all attachments and inline images have filenames. If you don’t supply a filename, Anymail will use
"attachment"as the filename.- Non-ASCII attachment filenames will be garbled
Mailtrap’s API does not properly encode Unicode characters in attachment filenames. Some email clients will display those characters incorrectly.
- No click-tracking or open-tracking options
Mailtrap does not provide a way to control open or click tracking for individual messages. Anymail’s
track_clicksandtrack_openssettings are unsupported. (You can exclude specific links from tracking using Mailtrap-proprietary attributes in your HTML.)- No envelope sender overrides
Mailtrap does not support overriding
envelope_sender.- Non-ASCII mailboxes (EAI)
Mailtrap partially supports Unicode mailboxes (the user part of user@domain—see EAI). EAI recipient addresses (to, cc, bcc) are delivered correctly, but Mailtrap generates invalid header fields that may display as empty or garbled, depending on the email app.
Trying to use an EAI
from_emailresults in a Mailtrap API error that the “‘From’ header does not match the sender’s domain.”EAI in
reply_tois supported (though may generate an invalid header field) for a single address. Using EAI with multiple reply addresses will cause anAnymailUnsupportedFeatureerror because Anymail cannot accurately communicate that to Mailtrap’s API.
Batch sending/merge and ESP templates
Mailtrap offers both ESP stored templates and batch sending with per-recipient merge data.
When you send a message with multiple to addresses, the
merge_data,
merge_metadata
and merge_headers properties
determine how many distinct messages are sent:
If the
merge_...properties are not set (the default), Anymail will tell Mailtrap to send a single message, and all recipients will see the complete list of To addresses.If any of the
merge_...properties are set—even to an empty{}dict, Anymail will tell Mailtrap to send a separate message for eachtoaddress, and the recipients won’t see the other To addresses.
You can use a Mailtrap stored template by setting a message’s
template_id to the template’s
“Template UUID.” Find the template UUID in the Templates section of Mailtrap’s
dashboard, under the template’s details. When a Mailtrap template is used,
your Django code must not provide a message subject or text or html body.
Supply the template merge data values with Anymail’s
normalized merge_data
and merge_global_data
message attributes.
message = EmailMessage( from_email="[email protected]", to=["[email protected]", "Bob <[email protected]>"], # omit subject and body (or set to None) to use template content ... ) message.template_id = "11111111-abcd-1234-0000-0123456789ab" # Template UUID message.merge_data = { '[email protected]': {'name': "Alice", 'order_no': "12345"}, '[email protected]': {'name': "Bob", 'order_no': "54321"}, } message.merge_global_data = { 'ship_date': "May 15", } message.send()
Status tracking webhooks
If you are using Anymail’s normalized status tracking, create a webhook in the Settings section of the Mailtrap dashboard under Webhooks. See their Webhooks help article for more information.
(Note that Mailtrap’s Email Sandbox service does not trigger webhook events.)
In Mailtrap’s “Add new webhook” screen, enter:
Webhook URL:
https://random:random@yoursite.example.com/anymail/mailtrap/tracking/random:random is an
ANYMAIL_WEBHOOK_SECRETshared secretyoursite.example.com is your Django site
Payload format: JSON (not JSON Lines)
Select area: Email Sending
Select stream: Transactional (unless you have overridden Anymail’s
MAILTRAP_API_URLto use Mailtrap’s bulk sending API).Select domain: the desired sending domain(s)
Select events to listen to: check all you want to receive
Mailtrap will report these Anymail event_types:
rejected, bounced, deferred, delivered, opened, clicked, complained, unsubscribed.
Inbound webhook
Mailtrap’s inbound service is currently under development, and APIs are not yet publicly available.