Python SDK for the Bavimail email service API
Project description
bavimail-python
Python SDK for the Bavimail email service API.
Installation
pip install bavimail
Quick Start
Synchronous
from bavimail import Bavimail
client = Bavimail(
api_key="bvm_your_api_key",
base_url="https://mail.yourdomain.com",
)
# List domains
domains = client.domains.list()
for d in domains:
print(f"{d.domain} ({d.status})")
# Send an email
email = client.emails.send(
alias_id="your-alias-id",
to_email="recipient@example.com",
subject="Hello!",
body="<p>Welcome!</p>",
)
print(f"Sent: {email.id} (status: {email.status})")
client.close()
Asynchronous
Every method has an _async variant. Use async with for automatic cleanup:
import asyncio
from bavimail import Bavimail
async def main():
async with Bavimail(
api_key="bvm_your_api_key",
base_url="https://mail.yourdomain.com",
) as client:
domains = await client.domains.list_async()
email = await client.emails.send_async(
alias_id="your-alias-id",
to_email="recipient@example.com",
subject="Hello!",
body="<p>Welcome!</p>",
)
asyncio.run(main())
Resources
Domains
# Create a domain
domain = client.domains.create("example.com", "AWS")
# Get setup instructions (DNS records)
setup = client.domains.get_setup(domain.id)
for record in setup.dns_records:
print(f"{record.type} {record.name} -> {record.value}")
# Check DNS verification status
dns = client.domains.get_dns_status(domain.id)
print(f"Verified: {dns.overall_progress.verified}/{dns.overall_progress.total_records}")
# Trigger verification
domain = client.domains.verify(domain.id)
# Update domain settings
domain = client.domains.update(domain.id, is_active=False)
# Delete
client.domains.delete(domain.id)
Aliases
alias = client.aliases.create(domain.id, "support")
aliases = client.aliases.list(domain_id=domain.id)
client.aliases.update(alias.id, "info")
client.aliases.delete(alias.id)
Emails (Outbound)
email = client.emails.send(
alias_id=alias.id,
to_email="user@example.com",
subject="Welcome",
body="<h1>Hello!</h1>",
track_opens=True,
attachments=[{
"filename": "doc.pdf",
"content": "<base64-encoded-content>",
"mime_type": "application/pdf",
}],
)
emails = client.emails.list(alias_id=alias.id, limit=50)
email = client.emails.get(email.id)
Inbound Emails
# List with filters
emails = client.inbound_emails.list(alias_id=alias.id, limit=25)
# Get full detail
detail = client.inbound_emails.get(email_id)
# Download raw RFC822 email
raw = client.inbound_emails.download_raw(email_id)
# Download attachment by index
attachment = client.inbound_emails.download_attachment(email_id, 0)
# Tag management
client.inbound_emails.add_tags(email_id, ["tag-id-1", "tag-id-2"])
tags = client.inbound_emails.get_tags(email_id)
client.inbound_emails.replace_tags(email_id, ["tag-id-3"])
client.inbound_emails.remove_tag(email_id, "tag-id-3")
# Delete
client.inbound_emails.delete(email_id)
Conversations
conversations = client.conversations.list(limit=20)
detail = client.conversations.get(conversation_id)
for msg in detail.messages:
print(f"[{msg.direction}] {msg.from_email}: {msg.subject}")
Tags
tag = client.tags.create("important", color="#ff0000", is_pinned=True)
tags = client.tags.list()
tag = client.tags.update(tag.id, name="critical")
client.tags.delete(tag.id)
Webhooks
# Create (returns secret, shown once!)
wh = client.webhooks.create(
url="https://hooks.example.com/bavimail",
event_types=["email.inbound.received", "domain.verified"],
)
print(f"Secret: {wh.secret}") # Store this!
# Verify
wh = client.webhooks.verify(wh.id, "verification-code-from-endpoint")
# Manage
webhooks = client.webhooks.list()
client.webhooks.update(wh.id, is_active=True)
client.webhooks.test(wh.id)
secret = client.webhooks.rotate_secret(wh.id)
client.webhooks.delete(wh.id)
Pagination
Use iter_pages / iter_pages_async to iterate through all results:
from bavimail import iter_pages, iter_pages_async
# Sync
for email in iter_pages(client.inbound_emails.list, alias_id="...", page_size=25):
print(email.subject)
# Async
async for email in iter_pages_async(client.inbound_emails.list_async, page_size=25):
print(email.subject)
Webhook Signature Verification
Verify incoming webhook signatures in your handler:
from bavimail import verify_webhook_signature, WebhookVerificationError
try:
verify_webhook_signature(
payload=request.body,
signature=request.headers["x-webhook-signature"],
timestamp=request.headers["x-webhook-timestamp"],
secret="your-hex-secret",
)
except WebhookVerificationError as e:
print(f"Invalid webhook: {e}")
Error Handling
All API errors raise typed exceptions:
from bavimail import (
NotFoundError,
ValidationError,
ConflictError,
AuthenticationError,
RateLimitError,
APIError,
)
try:
client.domains.get("nonexistent")
except NotFoundError as e:
print(f"Not found: {e.message}")
print(f"Error code: {e.code}") # e.g. "DOMAIN_NOT_FOUND"
print(f"Category: {e.category}") # e.g. "not_found"
print(f"Request ID: {e.request_id}") # For debugging
print(f"Context: {e.context}") # e.g. {"field": "domain_id", "value": "nonexistent"}
except APIError as e:
print(f"API error ({e.status_code}): {e.message}")
Custom HTTP Client
Pass a custom httpx.Client for advanced configuration (proxies, custom TLS, retries):
import httpx
custom = httpx.Client(
transport=httpx.HTTPTransport(retries=3),
timeout=60.0,
)
client = Bavimail(
api_key="bvm_...",
base_url="https://mail.yourdomain.com",
http_client=custom,
)
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Type check
mypy src/bavimail --strict
# Lint
ruff check src/ tests/
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bavimail-0.1.6.tar.gz.
File metadata
- Download URL: bavimail-0.1.6.tar.gz
- Upload date:
- Size: 75.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.23
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da4404739cd0caa5d3c8a39014aec3cee305d9ab4bb5ca03770abd8950f47f5e
|
|
| MD5 |
be7c66c9a20faafe8c57806a573badef
|
|
| BLAKE2b-256 |
6470bcd4f3accb8ed3a61a58aa492d9f7a4d507ce497785a3c79673d8e45b444
|
File details
Details for the file bavimail-0.1.6-py3-none-any.whl.
File metadata
- Download URL: bavimail-0.1.6-py3-none-any.whl
- Upload date:
- Size: 46.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.23
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52412413bf5d59a1c01e799d53b44d704668ece4988cb72083812fb5fbd20c87
|
|
| MD5 |
220e46699c61c079351466d88719c2fa
|
|
| BLAKE2b-256 |
dc0548f44f1a5124ec25bc54d384dc5ee714b8c2b780f27bf38100a10d151a52
|