Use the official Lettermint Rust SDK to send email from a Rust application. The SDK also supports the Team API and webhook signature verification. See SDKs and integrations for other packages.
Requirements
Rust 1.98 or newer
Tokio or another async runtime that is compatible with reqwest
[dependencies]lettermint = "1"tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
Run cargo build to install the dependencies. The package is also available on crates.io, and its API reference is on docs.rs.
Send your first email
Store your Project API token in LETTERMINT_TOKEN. Then, create an email client and send a message:
Code
use lettermint::Lettermint;#[tokio::main]async fn main() -> lettermint::Result<()> { let email = Lettermint::email(std::env::var("LETTERMINT_TOKEN").unwrap())?; let response = email .email() .from("John Doe <john@yourdomain.com>") .to("recipient@example.com") .subject("Hello from Lettermint") .text("This is a test email sent with the Lettermint Rust SDK.") .html("<p>This is a test email sent with the Lettermint Rust SDK.</p>") .send() .await?; println!("Email sent with ID: {}", response.message_id); Ok(())}
API acceptance does not confirm delivery. Use webhooks to receive delivery and bounce events.
Add email options
Each call to email.email() starts a new message. Options from one message do not stay in the next message.
Recipients and reply-to addresses
Call to, cc, bcc, or reply_to more than once to add multiple addresses:
Code
let response = email .email() .from("support@yourdomain.com") .to("customer@example.com") .to("account-owner@example.com") .cc("manager@yourdomain.com") .bcc("archive@yourdomain.com") .reply_to("help@yourdomain.com") .subject("Your support request") .text("We received your support request.") .send() .await?;
Metadata and headers
Use metadata to add application data to webhook payloads. Metadata does not add headers to the email:
Code
let response = email .email() .from("orders@yourdomain.com") .to("customer@example.com") .subject("Order confirmation") .text("Your order is confirmed.") .metadata("order_id", "12345") .metadata("customer_id", "cust_789") .header("X-Priority", "1") .send() .await?;
Tags
Use typed name and value tags to organize messages for filtering and analytics:
Code
use lettermint::types::MessageTag;let response = email .email() .from("notifications@yourdomain.com") .to("user@example.com") .subject("Your account is ready") .text("You can now sign in.") .tags([ MessageTag::new("campaign", "welcome")?, MessageTag::new("customer", "new")?, ]) .send() .await?;
You can add up to 20 typed tags. The tag method remains available for one legacy tag. You can add up to 19 typed tags when you also use a legacy tag. See Tags for the value rules.
Route and tracking settings
Select a route and control open and click tracking for the message:
Code
use lettermint::email::EmailSettings;use lettermint::types::TlsPolicy;let response = email .email() .from("notifications@yourdomain.com") .to("user@example.com") .subject("Security alert") .text("A new device signed in to your account.") .route("transactional") .settings(EmailSettings { track_opens: Some(false), track_clicks: Some(false), tls: Some(TlsPolicy::Enforced), }) .send() .await?;
The SDK removes the active token from API error data before it returns the error.
Use the Team API
Create a separate client with a Team API token. Store the token in LETTERMINT_TEAM_TOKEN:
Code
use lettermint::Lettermint;#[tokio::main]async fn main() -> lettermint::Result<()> { let api = Lettermint::api(std::env::var("LETTERMINT_TEAM_TOKEN").unwrap())?; let domains = api.domains().list(&[("page[size]", "10")]).await?; for domain in domains.data { println!("{}", domain.domain); } Ok(())}
The email client sends the Project API token in X-Lettermint-Token. The Team API client uses bearer authentication. Do not use a Project API token for Team API operations.
Verify webhook signatures
Pass the raw request body and the exact Lettermint signature header to the verifier:
The verifier checks the HMAC-SHA256 signature, the signature timestamp, and the optional delivery timestamp. The default timestamp tolerance is five minutes. Do not change the request body before verification. See Webhook signing for the required headers.