Markdown

Groundmail with Rust

Use the Rust SDK in web handlers, workers and background jobs, or any server-side Rust service where your API key stays secret. It's async and runs on Tokio.

Updated Nov 5, 20261 min read

Install the SDK

Terminal
cargo add groundmail
cargo add tokio --features macros,rt-multi-thread

Configure your API key

Terminal
export GROUNDMAIL_API_KEY=gm_your_key_here

Send an email

use groundmail::{Client, SendEmail};

#[tokio::main]
async fn main() -> Result<(), groundmail::Error> {
    let client = Client::from_env()?;

    let email = SendEmail::new("ops@yourdomain.com", "user@example.com", "Your receipt")
        .html("<p>Thanks for your purchase.</p>")
        .idempotency_key("receipt-order-1042");

    let sent = client.emails().send(&email).await?;
    println!("{} {}", sent.id, sent.status);
    Ok(())
}

Retrying with the same idempotency key returns the first result instead of sending twice. Set any other POST /emails field with .field("tags", json!(["receipt"])).

Handle errors

API errors keep their status, message and code:

match client.emails().send(&email).await {
    Ok(sent) => println!("{}", sent.id),
    Err(groundmail::Error::Api { status, message, code, .. }) => {
        eprintln!("{status} {code:?}: {message}");
    }
    Err(other) => eprintln!("{other}"),
}

Verify webhooks

Pass the raw request body, before parsing it, and the Groundmail-Signature header:

let valid = groundmail::verify_webhook_signature(&secret, &body, &signature_header);

Other resources

The client also has client.domains(), client.webhooks(), client.templates() and client.suppressions(). Reach any other endpoint with client.request(method, path, body).

Resources

Was this page helpful?