Docs / mailbridge / Quick Start

Quick Start

From install to sent email in under two minutes. This page covers the core patterns — basic sending, templates, attachments, bulk, and FastAPI integration.

Your First Email

Initialize MailBridge with your provider, then call send(). The examples below use SendGrid and SMTP — pick whichever you have credentials for:

python
from mailbridge import MailBridge

mailer = MailBridge(
    provider='sendgrid',
    api_key='SG.xxxxx',
    from_email='noreply@yourdomain.com'
)

response = mailer.send(
    to='user@example.com',
    subject='Hello from MailBridge!',
    body='

It works!

Your first email via SendGrid.

' ) print(f"Sent! Message ID: {response.message_id}")
python
from mailbridge import MailBridge

mailer = MailBridge(
    provider='smtp',
    host='smtp.gmail.com',
    port=587,
    username='you@gmail.com',
    password='your-app-password',   # Gmail App Password, not your login password
    use_tls=True,
    from_email='you@gmail.com'
)

response = mailer.send(
    to='user@example.com',
    subject='Hello from MailBridge!',
    body='

It works!

Your first email via Gmail SMTP.

' ) print(f"Sent! Message ID: {response.message_id}")

Gmail requires an App Password — not your regular Google password. Enable 2FA on your account, then generate an App Password under Account Settings → Security.

python
from mailbridge import MailBridge

mailer = MailBridge(
    provider='postmark',
    server_token='xxxxx-xxxxx',
    from_email='verified@yourdomain.com'   # Must be verified in Postmark
)

response = mailer.send(
    to='user@example.com',
    subject='Hello from MailBridge!',
    body='

It works!

Your first email via Postmark.

' ) print(f"Sent! Message ID: {response.message_id}")
python
from mailbridge import MailBridge

mailer = MailBridge(
    provider='ses',
    aws_access_key_id='AKIAXXXX',
    aws_secret_access_key='xxxxx',
    region_name='us-east-1',
    from_email='verified@yourdomain.com'   # Must be verified in SES
)

response = mailer.send(
    to='user@example.com',
    subject='Hello from MailBridge!',
    body='

It works!

Your first email via Amazon SES.

' ) print(f"Sent! Message ID: {response.message_id}")

Response Object

Every send() call returns an EmailResponse — a normalized response regardless of which provider was used:

python
response = mailer.send(
    to='user@example.com',
    subject='Test',
    body='

Hello

' ) print(response.message_id) # Provider-assigned message ID print(response.success) # True / False print(response.status_code) # HTTP status from the provider API

For send_bulk(), you get a BulkEmailResult:

python
result = mailer.send_bulk(messages)

print(result.total)       # Total messages attempted
print(result.successful)  # Successfully sent
print(result.failed)      # Failed count
print(result.failures)    # List of failures with details

Template Emails

All providers except SMTP support dynamic templates created in their dashboards. Pass template_id and template_data — subject and body come from the template:

python
# SendGrid template IDs start with 'd-'
response = mailer.send(
    to='user@example.com',
    subject='',          # comes from the template
    body='',             # comes from the template
    template_id='d-1234567890abcdef',
    template_data={
        'user_name':        'Alice Smith',
        'activation_link':  'https://yourapp.com/activate/abc123',
        'support_email':    'support@yourdomain.com'
    }
)
print(f"Sent! Message ID: {response.message_id}")
python
# SES template IDs are names you define in the SES console
response = mailer.send(
    to='user@example.com',
    subject='',
    body='',
    template_id='WelcomeTemplate',
    template_data={
        'firstName':     'Alice',
        'companyName':   'Acme Corp',
        'activationUrl': 'https://yourapp.com/activate/abc123'
    }
)
print(f"Sent! Message ID: {response.message_id}")
python
# Postmark template alias or numeric ID
response = mailer.send(
    to='user@example.com',
    subject='',
    body='',
    template_id='welcome-email',
    template_data={
        'product_name': 'My App',
        'name':         'Alice Smith',
        'action_url':   'https://yourapp.com/activate/abc123'
    }
)
print(f"Sent! Message ID: {response.message_id}")

Common transactional email patterns using templates:

python
# Welcome email
mailer.send(
    to=new_user.email,
    subject='', body='',
    template_id='welcome-email',
    template_data={'name': new_user.name, 'activation_link': generate_link(new_user)}
)

# Password reset
mailer.send(
    to=user.email,
    subject='', body='',
    template_id='password-reset',
    template_data={'reset_link': generate_reset_link(user), 'expiry_hours': 24}
)

# Order confirmation
mailer.send(
    to=order.customer_email,
    subject='', body='',
    template_id='order-confirmation',
    template_data={
        'order_number': order.id,
        'total':        order.total,
        'items':        order.items,
        'tracking_url': order.tracking_url
    }
)

Attachments

Pass a list of pathlib.Path objects to attachments — works on all providers:

python
from pathlib import Path

# Single attachment
response = mailer.send(
    to='customer@example.com',
    subject='Your Invoice',
    body='

Please find your invoice attached.

', attachments=[Path('invoice.pdf')] ) # Multiple attachments response = mailer.send( to='customer@example.com', subject='Your Documents', body='

Please find your documents attached.

', attachments=[ Path('invoice.pdf'), Path('receipt.pdf'), Path('terms.pdf') ] )

CC, BCC, Reply-To & Headers

All standard email fields are supported with the same syntax across all providers:

python
# CC and BCC
response = mailer.send(
    to='client@example.com',
    subject='Project Update',
    body='

Here is the latest update...

', cc=['manager@company.com', 'team@company.com'], bcc=['archive@company.com'] ) # Multiple recipients response = mailer.send( to=['alice@example.com', 'bob@example.com', 'charlie@example.com'], subject='Team Announcement', body='

Important update for everyone.

' ) # Reply-To response = mailer.send( to='customer@example.com', subject='Support Ticket Opened', body='

We received your inquiry. Reply to this email for updates.

', reply_to='support@yourdomain.com' ) # Custom headers and tags (for tracking/analytics) response = mailer.send( to='user@example.com', subject='Summer Campaign', body='

Special offer just for you!

', headers={'X-Campaign-ID': 'summer-2025', 'X-Priority': '1'}, tags=['marketing', 'summer-campaign'] )

Bulk Sending

Use send_bulk() to send to many recipients. Each provider uses its native batch API automatically — you don't need to manage batching yourself:

python
from mailbridge import MailBridge, EmailMessageDto

mailer = MailBridge(provider='sendgrid', api_key='SG.xxxxx', from_email='news@example.com')

# Build a message list — each recipient can have unique content
messages = [
    EmailMessageDto(
        to='alice@example.com',
        subject='Your monthly report',
        body='

Hello Alice, here is your report.

' ), EmailMessageDto( to='bob@example.com', subject='Your monthly report', body='

Hello Bob, here is your report.

' ), ] result = mailer.send_bulk(messages) print(f"Sent {result.successful}/{result.total}")

Bulk with personalized templates

python
# Personalized template for each subscriber
subscribers = [
    {'email': 'alice@example.com', 'name': 'Alice', 'plan': 'Pro'},
    {'email': 'bob@example.com',   'name': 'Bob',   'plan': 'Basic'},
    # ... thousands more
]

messages = [
    EmailMessageDto(
        to=sub['email'],
        subject='', body='',
        template_id='d-newsletter-template',
        template_data={'name': sub['name'], 'plan': sub['plan']}
    )
    for sub in subscribers
]

result = mailer.send_bulk(messages)
print(f"Sent: {result.successful}/{result.total}")

Bulk provider limits

ProviderBatch sizeStrategy
SendGrid1,000 / callNative batch API
Amazon SES50 / callAuto-batched by MailBridge
Postmark500 / callNative batch API
MailgunNativeNative batch API
BrevoNativeNative batch API
SMTPSends individually, reuses connection

Context Manager

Use MailBridge as a context manager to ensure connections are properly closed — especially useful with SMTP where an open connection is maintained:

python
with MailBridge(
    provider='smtp',
    host='smtp.gmail.com',
    port=587,
    username='you@gmail.com',
    password='your-app-password',
    use_tls=True,
    from_email='you@gmail.com'
) as mailer:
    mailer.send(to='alice@example.com', subject='Hi Alice', body='

Hello!

') mailer.send(to='bob@example.com', subject='Hi Bob', body='

Hello!

') # Connection closed automatically here

FastAPI Integration

The recommended pattern for FastAPI is to initialize MailBridge once at app startup and inject it as a dependency:

python
# mail.py — configure once
from mailbridge import MailBridge
import os

mailer = MailBridge(
    provider=os.getenv('MAIL_PROVIDER', 'smtp'),
    api_key=os.getenv('MAIL_API_KEY'),
    from_email=os.getenv('MAIL_FROM', 'noreply@yourdomain.com')
)

def get_mailer() -> MailBridge:
    return mailer
python
# main.py — use in routes
from fastapi import FastAPI, Depends, BackgroundTasks
from mailbridge import MailBridge
from mail import get_mailer

app = FastAPI()

@app.post("/register")
async def register(data: UserCreate, mailer: MailBridge = Depends(get_mailer)):
    user = create_user(data)

    # Send welcome email
    mailer.send(
        to=user.email,
        subject='', body='',
        template_id='welcome-email',
        template_data={'name': user.name}
    )

    return {"id": user.id}

@app.post("/register/bg")
async def register_with_background(
    data: UserCreate,
    background_tasks: BackgroundTasks,
    mailer: MailBridge = Depends(get_mailer)
):
    user = create_user(data)

    # Send in background — don't block the response
    background_tasks.add_task(
        mailer.send,
        to=user.email,
        subject='', body='',
        template_id='welcome-email',
        template_data={'name': user.name}
    )

    return {"id": user.id}   # Returns immediately

Use BackgroundTasks for welcome and notification emails — they shouldn't block the API response. Only block when confirmation of delivery is critical (e.g. password reset — user expects to see "email sent" before the page resolves).