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.11.tar.gz (17.0 MB 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.11-py3-none-any.whl (48.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: bavimail-0.1.11.tar.gz
  • Upload date:
  • Size: 17.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bavimail-0.1.11.tar.gz
Algorithm Hash digest
SHA256 90eb7e7eec2f683bb567fc8a86366e1e9b7f0e86ce007429058a9bbd5131ad1e
MD5 219374288728672aa2d7a49f3afa3f93
BLAKE2b-256 84e9cbb5079c8b7bcdf5b420a47140cf5c2b2bc17a323f8f59ffd0c574351350

See more details on using hashes here.

File details

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

File metadata

  • Download URL: bavimail-0.1.11-py3-none-any.whl
  • Upload date:
  • Size: 48.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for bavimail-0.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 e0de8965e0be290ff2e7ad7249141a54e88dfda0cb8acc9ae7f206563ca27da1
MD5 3b7d926ca1fc0d73b23bdfff60f70a21
BLAKE2b-256 a2426e775a5307ee69c173421f8217a4ff68b7c5e69d9dcbf4bbc7bf3f691e80

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