Skip to main content
Send transactional emails from your Rust applications using the official Lettr Rust SDK. The SDK provides a type-safe, async-first interface for the Lettr API with full Tokio support and zero-copy deserialization. Using Cursor? Jump straight in using this prompt

Why Use the Rust SDK?

Rather than making raw HTTP requests, the SDK provides:
  • Type-safe API — Full type safety with serde-powered serialization
  • Async-first design — Built on Tokio for non-blocking operations
  • Zero-copy — Efficient deserialization with minimal allocations
  • Builder pattern — Fluent API for constructing complex emails
  • Result types — Idiomatic error handling with Rust’s Result<T, E>
If you prefer not to use the SDK, you can also send emails via SMTP or make direct HTTP API calls.

Prerequisites

Before you begin, make sure you have:

API Key

Create an API key in the Lettr dashboard

Verified Domain

Add and verify your sending domain
You’ll also need:
  • Rust 1.70 or later installed (via rustup)
  • A verified sending domain in your Lettr dashboard

Quick Setup

Get started in three quick steps: install, configure, and send.
1

Install the SDK

cargo add lettr
cargo add tokio --features macros,rt-multi-thread
The SDK requires Tokio as an async runtime. The macros feature provides #[tokio::main] and the rt-multi-thread feature enables the multi-threaded runtime.
2

Create a client

use lettr::Lettr;

#[tokio::main]
async fn main() -> lettr::Result<()> {
    let client = Lettr::new("your-api-key");

    // Verify the client is configured correctly
    let auth = client.auth_check().await?;
    println!("Connected to Lettr (Team ID: {})", auth.data.team_id);

    Ok(())
}
Store your API key in environment variables, never hardcode it. API keys use the lttr_ prefix followed by 64 hexadecimal characters.
3

Send your first email

use lettr::{Lettr, CreateEmailOptions};

#[tokio::main]
async fn main() -> lettr::Result<()> {
    let client = Lettr::new("your-api-key");

    let email = CreateEmailOptions::new(
        "[email protected]",
        ["[email protected]"],
        "Hello from Lettr",
    )
    .with_html("<h1>Hello!</h1><p>This is a test email.</p>");

    let response = client.emails.send(email).await?;
    println!("Email sent! Request ID: {}, Accepted: {}",
        response.request_id, response.accepted);

    Ok(())
}
The response includes a request_id for tracking and the number of accepted recipients.
The sender domain must be verified in your Lettr dashboard before you can send emails. Sending from an unverified domain returns a validation error.

Configuration

Environment Variables

Read your API key from an environment variable:
use std::env;
use lettr::Lettr;

#[tokio::main]
async fn main() -> lettr::Result<()> {
    let api_key = env::var("LETTR_API_KEY")
        .expect("LETTR_API_KEY environment variable is required");

    let client = Lettr::new(&api_key);

    Ok(())
}

Using dotenvy

Load environment variables from a .env file using the dotenvy crate:
cargo add dotenvy
Create a .env file:
LETTR_API_KEY=lttr_your_api_key_here
Load it in your application:
use dotenvy::dotenv;
use lettr::Lettr;

#[tokio::main]
async fn main() -> lettr::Result<()> {
    // Load .env file
    dotenv().ok();

    // Read from environment variable
    let api_key = std::env::var("LETTR_API_KEY")
        .expect("LETTR_API_KEY is required");

    let client = Lettr::new(&api_key);

    Ok(())
}
Add .env to your .gitignore file to prevent accidentally committing your API key to version control.

Custom HTTP Client

Use a custom reqwest client with custom timeouts or settings:
use lettr::Lettr;
use reqwest::Client;
use std::time::Duration;

#[tokio::main]
async fn main() -> lettr::Result<()> {
    let http_client = Client::builder()
        .timeout(Duration::from_secs(30))
        .build()?;

    let client = Lettr::with_client("your-api-key", http_client);

    Ok(())
}

Sending Emails

Basic HTML Email

Send a simple HTML email:
use lettr::{Lettr, CreateEmailOptions};

let email = CreateEmailOptions::new(
    "[email protected]",
    ["[email protected]"],
    "Welcome to our service",
)
.with_html("<h1>Welcome!</h1><p>Thanks for signing up.</p>");

let response = client.emails.send(email).await?;
println!("Email sent successfully (Request ID: {})", response.request_id);

With Display Name

Add a friendly display name to the sender address:
let email = CreateEmailOptions::new(
    "[email protected]",
    ["[email protected]"],
    "Welcome to Acme",
)
.with_from_name("Acme Corp")
.with_html("<h1>Hello!</h1>");

client.emails.send(email).await?;

Plain Text Email

Send a plain text email without HTML:
let email = CreateEmailOptions::new(
    "[email protected]",
    ["[email protected]"],
    "Plain text email",
)
.with_text("This is a plain text email.\n\nIt has no HTML formatting.");

client.emails.send(email).await?;

Multipart Emails (HTML + Text)

Send both HTML and plain text versions for maximum compatibility:
let email = CreateEmailOptions::new(
    "[email protected]",
    ["[email protected]"],
    "Multipart email",
)
.with_html("<h1>Hello!</h1><p>This is the HTML version.</p>")
.with_text("Hello!\n\nThis is the plain text version.");

client.emails.send(email).await?;
Providing both HTML and plain text ensures your emails are readable in all email clients, including text-only clients and accessibility tools.

Explore the SDK

Beyond sending, the SDK manages every Lettr resource:

Templates

Manage Lettr templates and merge tags

Domains

Add, verify, and manage sending domains

Webhooks

Manage webhook endpoints for delivery and engagement events

Audience

Lists, contacts, topics, properties, and segments

Campaigns

List, send, and schedule campaigns

What’s Next

Advanced Features

Learn about attachments, templates, tracking, and more

API Reference

Complete API documentation

Best Practices

Email deliverability tips