Skip to main content
This guide covers advanced Python SDK features. If you’re new to the SDK, start with the Python Quickstart.

Advanced Features

Multiple Recipients

Add multiple To, CC, and BCC recipients:
BCC recipients are hidden from all other recipients. They receive the email but their addresses are not visible in the headers.

Reply-To Address

Specify a different reply-to address:

Attachments

Add file attachments to your emails:
Attach multiple files:
Attachments must be base64-encoded. The total size of all attachments should not exceed 10MB. Larger files should be hosted and linked instead.

Templates

Send emails using Lettr-managed templates:
Templates are managed in the Lettr dashboard. Use merge tags to personalize content without rebuilding HTML in your code.

Custom Headers

Add custom email headers:

Tracking

Enable open and click tracking:
Open tracking works by embedding a transparent pixel image. Click tracking rewrites links to go through Lettr’s tracking domain. Both features respect user privacy and comply with email regulations.

Metadata

Attach custom metadata for tracking and filtering:
Metadata is returned in webhook events and can be used to correlate emails with your application data.

Error Handling

The SDK provides structured exception types for different error scenarios:

Common Error Scenarios

Unverified domain:
  • Exception: ValidationError
  • Message: “The from address domain is not verified”
  • Solution: Verify your domain in the dashboard
Invalid API key:
  • Exception: AuthenticationError
  • Message: “Invalid API key”
  • Solution: Check your API key is correct and active
Rate limit exceeded:
  • Exception: RateLimitError
  • Message: “Too many requests”
  • Solution: Implement exponential backoff retry logic

Async Support

The SDK provides full async support for non-blocking operations:

With Semaphore for Rate Limiting

Limit concurrent requests using asyncio.Semaphore:
For large batches, consider using a task queue like Celery or RQ to manage concurrent requests and handle failures gracefully.

Django Integration

Settings Configuration

Add Lettr configuration to your Django settings:

Email Service

Create an email service module:

Using in Views

Use the email service in your views:

Best Practices

Use Environment Variables

Never hardcode API keys. Use environment variables or a secrets manager:

Validate Before Sending

Validate email addresses before making API calls:

Log Request IDs

Always log the request_id from successful sends for tracking and debugging:

Handle Errors Gracefully

Implement retry logic for transient errors:

Use Context Managers

Use context managers to ensure proper cleanup:

Reuse the Client

Create a single client instance and reuse it across requests:

Type Hints

The SDK includes full type hints for better IDE support:

Troubleshooting

If you see “The from address domain is not verified”:
  • Verify your domain in the Lettr dashboard
  • Ensure the from_email parameter uses the verified domain
  • Wait for DNS propagation (can take up to 48 hours)
  • See Domain Verification for help
If you see authentication errors:
  • Check your API key is correct and starts with lttr_
  • Verify the key is 68 characters total (prefix + 64 hex chars)
  • Ensure the key hasn’t been revoked in the dashboard
  • Confirm you’re reading from the correct environment variable
If requests timeout:
  • Increase the httpx client timeout
  • Check your network connectivity and firewall settings
  • Verify app.lettr.com is reachable
  • Use a custom httpx client with longer timeout settings
If you see “ModuleNotFoundError” or import errors:
  • Verify the package is installed: pip list | grep lettr
  • Reinstall the package: pip install --upgrade lettr
  • Check your Python version is 3.8 or later: python --version
  • Activate your virtual environment if using one
If you’re hitting rate limits:
  • Implement exponential backoff retry logic (see Best Practices)
  • Use asyncio.Semaphore for controlled concurrent sending
  • Consider upgrading your Lettr plan for higher limits
  • Spread requests over time instead of bursts
If you encounter async-related errors:
  • Use AsyncLettr for async code, not Lettr
  • Ensure you’re using await with async methods
  • Run async functions with asyncio.run() at the top level
  • Check that your async runtime is properly configured

What’s Next

Flask Integration

Use Lettr with Flask applications

FastAPI Integration

Use Lettr with FastAPI applications

API Reference

Complete API documentation

Templates

Use Lettr-managed templates