Skip to main content
This guide covers advanced features of the Lettr Rust SDK including attachments, templates, batch sending, error handling, and best practices for production applications.
New to the Rust SDK? Start with the Rust Quickstart to learn the basics first.

Advanced Features

CC and BCC Recipients

Add 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 idiomatic Rust error handling with the Result type:

Common Error Scenarios

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

Batch Sending

Send multiple emails concurrently using Tokio’s join patterns:

With Concurrency Limiting

Use a semaphore to limit concurrent requests:
For large batches, consider using a task queue or stream-based approach with futures::stream::StreamExt to manage concurrency and handle failures gracefully.

Async Patterns

Using with Tokio Runtime

The SDK is built on Tokio and works with any Tokio-based application:

Using with Actix Web

Integrate with Actix Web handlers:

Using with Axum

Integrate with Axum handlers:

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:

Clone the Client

The Lettr client is cheap to clone and can be shared across tasks:

Use Structured Logging

Use the tracing crate for structured logging:

Troubleshooting

If you see “The from address domain is not verified”:
  • Verify your domain in the Lettr dashboard
  • Ensure the from address 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 client timeout (default may be too short)
  • Check your network connectivity and firewall settings
  • Verify app.lettr.com is reachable
  • Use a custom reqwest client with longer timeout settings
If you see compilation errors:
  • Run cargo update to update dependencies
  • Check your Rust version is 1.70 or later: rustc --version
  • Verify the crate name is correct: lettr
  • Clear build artifacts: cargo clean
If you’re hitting rate limits:
  • Implement exponential backoff retry logic (see Best Practices)
  • Use async batch sending with controlled concurrency via semaphore
  • Consider upgrading your Lettr plan for higher limits
  • Spread requests over time instead of bursts
If you encounter Rust-specific type errors:
  • Ensure your async runtime (Tokio) is properly configured
  • Check that you’re using .await on async functions
  • Use .clone() when sharing the client across tasks
  • Verify all required fields are provided to the builder

What’s Next

API Reference

Complete API documentation

Templates

Use Lettr-managed templates

Webhooks

Track delivery events

Best Practices

Email deliverability tips