Conversation
Add a MailKite (mailkite.dev) backend. MailKite is an inbound-first developer email platform: it sends transactional mail via POST /v1/send (a JSON API) and also *receives* email, delivering the parsed body plus an SPF/DKIM/DMARC auth verdict to a signed webhook. The backend implements the send side, modeled on the existing Resend backend (MailKite's send API is JSON/shape-compatible), and supports the Anymail features MailKite's API exposes that Resend's does not: - per-message trackOpens / trackClicks overrides - server-side templates: templateId + templateData (merge_global_data) - batch sending (POST /v1/send/batch) with per-recipient merge_metadata and merge_headers; per-recipient failures surface as "rejected" - metadata and tags via X-Metadata / X-Tags headers - scheduled sending (scheduledAt) Not wired up (documented as limitations on the ESP page): - outbound tracking webhooks (MailKite does not emit them) - inbound signals (MailKite delivers inbound mail directly to the user's own webhook URL, in its own payload format) - inline attachments (MailKite's send API has no Content-ID field) - multiple reply_to (MailKite takes a single replyTo string) Includes: - anymail/backends/mailkite.py - tests/test_mailkite_backend.py (45 mocked tests) - tests/test_mailkite_integration.py (live tests, skipped without keys) - docs/esps/mailkite.rst - README, pyproject, feature matrix, and changelog entries All backend tests pass; pre-commit (black/isort/flake8/doc8/pygrep) clean.
Author
|
Apologies — this duplicates #481, which is the maintained MailKite backend PR and the only one going forward (as promised there). This one was opened in error by our tooling; we've fixed the process so it can't happen again. Closing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
A new MailKite (mailkite.dev) backend, modeled closely on the existing Resend backend — MailKite's send API is JSON/shape-compatible with Resend's (
POSTJSON,Authorization: Bearer,{from,to,subject,html,text,…}), so the contribution follows the same structure you already accept and maintain.MailKite is an inbound-first developer email platform: it sends transactional mail, and also receives email (parsed body + SPF/DKIM/DMARC verdict) delivered to a signed webhook. This PR implements the send side.
Anymail features supported
MailKite's API actually exposes a few things Resend's doesn't, so the backend supports more Anymail features than the Resend one:
template_id+merge_global_data(server-side templates,{{merge_tags}})track_opens/track_clicks(per-message override)send_at(scheduledAt)merge_metadata/merge_headers(batch send,POST /v1/send/batch)metadata,tags(viaX-Metadata/X-Tagsheaders)content/filename/contentType)Documented limitations (on the ESP page, raised as
AnymailUnsupportedFeature)AnymailTrackingEventsignals are not available. (Open/click tracking still works in MailKite's own dashboard, and per-messagetrack_opens/track_clicksare supported.)AnymailInboundEvent.cidfield, so inline images raise rather than silently degrading to regular attachments.replyToonly — MailKite takes one reply-to string; multiplereply_toaddresses raise.envelope_sender.How to configure
No extra install — MailKite uses only Anymail's existing
requestsdependency (hencemailkite = []in optional-dependencies, no[mailkite]extra).How I tested it
tests/test_mailkite_backend.py— 45 mocked tests covering standard Django email features and all the Anymail additions above, including the batch path (emptymerge_data,merge_metadata,merge_headers) and a per-recipient rejection (MailKite reports batch failures per-recipient; verified they surface as"rejected").tests/test_mailkite_integration.py— live tests against the real API, guarded byANYMAIL_TEST_MAILKITE_API_KEY/ANYMAIL_TEST_MAILKITE_DOMAIN(skip cleanly without them).python runtests.py tests.test_mailkite_backend tests.test_mailkite_integration→ 49 passed (4 skipped). The Resend backend tests still pass unchanged.pre-commit(black, isort, flake8, doc8, pygrep-hooks) is clean on every file in this PR.I did not run the live integration tests (I don't want to charge a real MailKite account from a PR). If you'd like, I can run them against a MailKite test domain before merge, or you can run them in CI with credentials.
Files
anymail/backends/mailkite.pytests/test_mailkite_backend.py,tests/test_mailkite_integration.pydocs/esps/mailkite.rst(+ toctree, README, feature-matrix column,pyprojectkeywords/extra, changelog)Maintenance
Happy to maintain this backend going forward — keeping it in step with MailKite's send API as it evolves, and adding outbound tracking webhook support (→
AnymailTrackingEvent) and Anymail inbound signal support if/when MailKite exposes the corresponding surfaces. I've readCONTRIBUTINGand followed the existing ESP-backend pattern; happy to rework anything that doesn't match your conventions.(Heads-up on the feature-matrix support-status row: I marked MailKite
Unsupportedper the footnote — Anymail doesn't have a MailKite account for live integration tests yet. Adjust toLimited/Fullas you see fit once you have access.)