Advanced features and patterns for the Lettr Rust SDK
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.
use lettr::{Lettr, CreateEmailOptions};let email = CreateEmailOptions::new( "notifications@yourdomain.com", ["primary@example.com"], "Team notification",).with_cc(["cc@example.com", "cc2@example.com"]).with_bcc(["bcc@example.com"]).with_html("<p>This email has CC and BCC recipients.</p>");client.emails.send(email).await?;
BCC recipients are hidden from all other recipients. They receive the email but their addresses are not visible in the headers.
let email = CreateEmailOptions::new( "notifications@yourdomain.com", ["user@example.com"], "Support notification",).with_reply_to("support@yourdomain.com").with_html("<p>Click reply to contact our support team.</p>");client.emails.send(email).await?;
let email = CreateEmailOptions::new( "marketing@yourdomain.com", ["user@example.com"], "Newsletter",).with_html("<p>Check out <a href='https://example.com'>our website</a>!</p>").with_click_tracking(true).with_open_tracking(true);client.emails.send(email).await?;
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.
Send multiple emails concurrently using Tokio’s join patterns:
Copy
use lettr::{Lettr, CreateEmailOptions};use tokio;#[tokio::main]async fn main() -> lettr::Result<()> { let client = Lettr::from_env(); let recipients = vec![ "user1@example.com", "user2@example.com", "user3@example.com", ]; let mut tasks = vec![]; for recipient in recipients { let client = client.clone(); let task = tokio::spawn(async move { let email = CreateEmailOptions::new( "notifications@yourdomain.com", [recipient], "Batch notification", ) .with_html("<p>This is a batch email.</p>"); match client.emails.send(email).await { Ok(response) => println!("Sent to {}: {}", recipient, response.request_id), Err(e) => eprintln!("Failed to send to {}: {}", recipient, e), } }); tasks.push(task); } // Wait for all tasks to complete for task in tasks { task.await?; } println!("All emails sent"); Ok(())}
use tokio::sync::Semaphore;use std::sync::Arc;async fn send_batch( client: &Lettr, recipients: Vec<&str>, max_concurrent: usize,) -> lettr::Result<()> { let semaphore = Arc::new(Semaphore::new(max_concurrent)); let mut tasks = vec![]; for recipient in recipients { let client = client.clone(); let permit = semaphore.clone().acquire_owned().await?; let task = tokio::spawn(async move { let email = CreateEmailOptions::new( "notifications@yourdomain.com", [recipient], "Batch email", ) .with_html("<p>Hello!</p>"); let result = client.emails.send(email).await; drop(permit); // Release semaphore result }); tasks.push(task); } for task in tasks { task.await??; } Ok(())}// Usagelet recipients = vec!["user1@example.com", "user2@example.com", "user3@example.com"];send_batch(&client, recipients, 10).await?; // Max 10 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.