Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bavimail-0.1.5.tar.gz (74.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bavimail-0.1.5-py3-none-any.whl (45.7 kB view details)

Uploaded Python 3

File details

Details for the file bavimail-0.1.5.tar.gz.

File metadata

  • Download URL: bavimail-0.1.5.tar.gz
  • Upload date:
  • Size: 74.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.23

File hashes

Hashes for bavimail-0.1.5.tar.gz
Algorithm Hash digest
SHA256 857cc32bc7a8ae92e18499f600fa35d2762074a02fece16632b0a847140a82ad
MD5 870110c2a3508fe07347e94c70d66295
BLAKE2b-256 be9d11c75b0b4735329815b5f20c94ded2e005079e5b424d44eb5bc66682d2ef

See more details on using hashes here.

File details

Details for the file bavimail-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: bavimail-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 45.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.23

File hashes

Hashes for bavimail-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 3233424993e7936c1240b9a8d01a6087991a358fa11d9a39922afac20a7e3495
MD5 6b057e5a83c96d05a1885829141aaf0a
BLAKE2b-256 e80d607ae768510ca7520741510d7068685bf119cd43d19d1779e8527a2ed1ee

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page