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.10.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.10-py3-none-any.whl (46.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for bavimail-0.1.10.tar.gz
Algorithm Hash digest
SHA256 020c2e2109523014534f9c8f63aed514a8aa19177f8f61c92d3984da07a843cd
MD5 c8bfca3d172c61735554676c9f085bdd
BLAKE2b-256 8d10d1e909dd82cdb82159eee89dddae9418548145924dac1e26634f425688ed

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for bavimail-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 b9b2d47a2ff81e66a29ef4a7cae60e64806b6256d1dc8df95d80cddf0ae51fd5
MD5 d3cef61d386ce7396ca45b88eb82ee82
BLAKE2b-256 bfdd887a8ba5ca2b96572861db673dce73a1dd19909d38f512cc3d516a277b2a

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