Official Python client for the RaviMail REST API v1.
Type-hinted, minimal dependencies (requests only).
Why this exists. RaviMail is a Brazilian email infrastructure platform with 155 documented REST endpoints. This SDK gives you Pythonic access to all of them, with proper exceptions and a familiar
Session-based HTTP layer.
pip install ravimailRequirements: Python 3.9+.
from ravimail import Client
rm = Client("rvm_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
resp = rm.transactional.send(
to="recipient@example.com",
from_="you@yourdomain.com", # `from` is reserved in Python — use from_
subject="Welcome to the show",
html="<h1>Glad you're here</h1>",
)
print(resp["data"]["message_id"]) # msg_xxxxxxxxxxxxAny token prefixed with rvm_test_* enables sandbox mode automatically.
test = Client("rvm_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
test.transactional.send(to="bounce@simulator.ravimail.com.br", from_="...", subject="...", html="...")See the Mailbox Simulator for deterministic test scenarios.
All 23 resources mirror the REST API exactly.
| Resource | Coverage |
|---|---|
rm.me |
Token info + quotas |
rm.transactional |
send / batch / list / get |
rm.contacts |
CRUD + add_tags / remove_tags / suppress / import_ |
rm.lists |
CRUD |
rm.templates |
CRUD + render + versioning |
rm.campaigns |
CRUD + start / pause / resume / cancel / duplicate + A/B |
rm.domains |
Add / verify / dns_check / upgrade_to_panel |
rm.files |
Upload (path or file handle) / list / get / delete |
rm.webhooks |
Endpoints + deliveries + rotate_secret |
rm.suppression |
list / suppress / unsuppress |
rm.analytics |
summary / timeseries / by_domain/ip/node/isp/device/country / heatmap |
rm.events |
list + stream_url() |
rm.verification |
email + batch |
rm.segments |
CRUD + compute |
rm.exports |
Async CSV jobs |
rm.inbound_routes |
Inbound parsing → forward webhook |
rm.drips |
CRUD + steps + subscribe / unsubscribe |
rm.subaccounts |
Multi-tenant CRUD + tokens |
rm.reputation |
summary / domains / ips / nodes |
rm.custom_fields |
List / create / delete |
rm.reports |
Scheduled reports CRUD |
rm.account |
Balance / usage / packages / top_up / payments |
rm.smtp_relay |
SMTP credentials + log |
For any write you want to retry safely:
rm.transactional.send(
to="user@example.com",
from_="you@yourdomain.com",
subject="Order confirmation",
html="<p>...</p>",
idempotency_key="order-1024-confirmation",
)The API guarantees the second call with the same key returns the original response, byte for byte.
Standalone function — no Client instance needed:
from ravimail import verify_signature
def handle_webhook(request):
signature = request.headers.get("X-Ravimail-Signature", "")
raw_body = request.get_data() # Flask: raw bytes; Django: request.body
secret = os.environ["RAVIMAIL_WEBHOOK_SECRET"]
if not verify_signature(signature, raw_body, secret):
return "", 401
# ... process payload
return "", 200Uses hmac.compare_digest — constant-time comparison.
from ravimail import (
Client,
ApiError,
AuthenticationError,
ValidationError,
RateLimitError,
)
try:
rm.transactional.send(to="...", from_="...", subject="...", html="...")
except ValidationError as e:
# 422 — bad payload; e.detail has the field-level info
print(e.detail)
except RateLimitError as e:
# 429 — back off
time.sleep(e.retry_after_seconds or 5)
except AuthenticationError:
# 401 — token invalid/revoked
...
except ApiError as e:
# any other 4xx/5xx; e.status has the HTTP code
...import requests
rm = Client(
"rvm_live_...",
base_url="https://api.ravimail.com.br", # override for staging
timeout=30.0, # seconds
session=requests.Session(), # reuse for connection pooling
)Install sseclient-py:
pip install sseclient-pyimport requests
from sseclient import SSEClient
res = requests.get(
rm.events.stream_url(),
headers={"Authorization": f"Bearer {token}", "Accept": "text/event-stream"},
stream=True,
)
for event in SSEClient(res).events():
print(event.data)MIT © Ravi Systems LTDA