mxRaven Python SDK
A Python SDK for the mxRaven mail-facing runtime surfaces:
- SMTP submission — the root package (
mxraven). - Webhook verification and decoding —
mxraven.webhook. - Inbound MIME parsing —
mxraven.mimeandmxraven.aio.mime. - Recipient feedback and RFC 8058 one-click unsubscribe —
mxraven.feedback. - Client notification events over NATS JetStream —
mxraven.notifyandmxraven.aio.notify.
It is the Python counterpart of the Go SDK at
github.com/synqronlabs/mxraven-go/mail
and the TypeScript SDK
@mxraven/mail, and exposes the
same capabilities behind an idiomatic Python API.
Status: early development. The public API is not yet stable.
Control-plane administration — tenants, domains, suppression lists, deliverability reporting, mail analytics — is out of scope. It lives in the separate control-plane SDK.
Requirements
Python 3.11 or later. The SDK has zero runtime dependencies; it uses only
the standard library. Client notifications are the one exception and need the
optional notify extra.
Install
uv add mxraven
# or
pip install mxraven
For client notifications, install the extra:
uv add "mxraven[notify]"
# or
pip install "mxraven[notify]"
Quick start
import os
from mxraven import Client, Message
client = Client(
host="smtp.mxraven.com",
username="mxr_tx_ab12cd34ef56",
secret=os.environ["MXRAVEN_SECRET"],
)
try:
result = client.send(
Message()
.from_("Acme <noreply@acme.example>")
.to("customer@example.com")
.subject("Your receipt")
.text("Thanks for your order.")
.html("<p>Thanks for your order.</p>")
)
print("accepted as", result.message_ref)
finally:
client.close()
The submission service requires STARTTLS and SMTP AUTH, so both are always used. The SDK does not read environment variables itself. Load secrets from a secret manager in production.
Sending raw messages
Use send_raw to stream an already serialized RFC 5322 message with an explicit
envelope. The caller is responsible for RFC 5322 correctness.
client.send_raw(
{"from": "bounce@acme.example", "to": ["customer@example.com"]},
raw_message_bytes,
)
Errors
Rejected commands raise SMTPError; when every recipient is rejected,
SMTPTransactionError is raised with the per-recipient result.
from mxraven import SMTPError
try:
client.send(message)
except SMTPError as error:
if error.permanent:
... # 5xx: do not retry the same message.
Webhooks
Verification and decoding use the webhook signing secret, not the submission API key.
from mxraven.webhook import Verifier, event_type
verifier = Verifier(secret=os.environ["MXRAVEN_WEBHOOK_SECRET"])
event = verifier.verify_and_decode(request) # any adapter or raw primitives
if event.type is event_type.inbound_email:
raw = event.inbound_email.raw_email.fetch()
The signature is HMAC-SHA256 over a canonical request string and is sent in the
X-MxRaven-* headers. The signing secret is used as literal key bytes; do not
base64-decode it.
Parsing inbound email
Turn the raw message behind an inbound-email payload into headers, addresses, bodies, and decoded attachments.
from mxraven.mime import fetch_and_parse_raw_email
email = fetch_and_parse_raw_email(event.inbound_email.raw_email)
print(email.subject, len(email.attachments))
parse_email(raw_bytes) parses bytes you already hold. The asyncio counterpart
is mxraven.aio.mime. See
MIME parsing for the full
surface.
Feedback
Teach the spam filter with the exact raw message bytes mxRaven processed, or perform a one-click unsubscribe. Learning uses the same submission API key as SMTP submission, over HTTP Basic auth.
from mxraven.feedback import Client as FeedbackClient
feedback = FeedbackClient(
base_url="https://feedback.mxraven.com",
username="mxr_tx_ab12cd34ef56",
secret=os.environ["MXRAVEN_SECRET"],
)
feedback.learn_spam(raw_message_bytes)
Notifications
Consume the durable mail events a listener publishes over NATS JetStream. This
needs the notify extra and the same API key as SMTP submission.
from mxraven.notify import NotificationClient, NotificationKind
with NotificationClient.connect(
url="wss://nats.mxraven.com",
username="mxr_tx_ab12cd34ef56",
secret=os.environ["MXRAVEN_SECRET"],
listener=listener_id,
) as client:
for delivery in client.events():
if delivery.event.kind is NotificationKind.ACCEPTED:
handle(delivery.event.accepted)
delivery.ack()
The asyncio counterpart is mxraven.aio.notify. See
Notifications for
the full surface.
Development
Requires Python 3.11+ and uv.
make install # uv sync: create .venv and install dev dependencies
make format # ruff format + safe fixes
make lint # ruff format --check + ruff check
make typecheck # mypy
make test # pytest
make check # every quality gate, including build
make docs # mkdocs build --strict
make check mirrors the CI job and must pass before a change is considered
complete.
Toolchain
| Concern | Tool |
|---|---|
| Environment / deps | uv |
| Build backend | hatchling + hatch-vcs |
| Lint / format | Ruff (ruff check + ruff format) |
| Type checking | mypy (strict) |
| Testing | pytest + pytest-cov, trustme |
| API docs | MkDocs Material + mkdocstrings |
| Versioning / changelog | hatch-vcs + towncrier |
| Release | GitHub Actions with PyPI Trusted Publishing and attestations |
Releases
Releases are cut from vMAJOR.MINOR.PATCH git tags. The version is derived from
the tag by hatch-vcs, and CHANGELOG.md is assembled from the fragments in
changelog.d/. Publishing runs from GitHub Actions via PyPI Trusted Publishing
(OIDC) with build attestations; do not publish manually.
License
Metadata
Release files for mxraven 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mxraven-0.5.0.tar.gz | 121.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mxraven-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 222.5 kB
Release files / mxraven-0.5.0.tar.gz
| Download URL | mxraven-0.5.0.tar.gz |
|---|---|
| Size | 121.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a0dcaffc7117f64b111c9a29881584b582a1fddbb99c4b89f0049b5fe0ca444a
|
|
BLAKE2b-256 checksum How to use checksums |
d282169a0f7d0bc806becc1d6488703baba022a9af0089e16a56a7e2cc6fb298
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / mxraven-0.5.0-py3-none-any.whl
| Download URL | mxraven-0.5.0-py3-none-any.whl |
|---|---|
| Size | 101.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8aab06438576169d423023414f8e9ffd63b0c4ae7dad752d5acf0a2d06188246
|
|
BLAKE2b-256 checksum How to use checksums |
8c586a792d9d76df0eb1a0b71ddd9544fede757dc452bc3cfd0f6da622b29dee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for mxraven 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for mxraven-0.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.