emailit 2.0.3

The official Rust SDK for the Emailit Email API
Documentation

Emailit Rust

Tests Crates.io License

The official Rust SDK for the Emailit Email API.

Requirements

  • Rust 1.85+
  • Tokio runtime

Installation

Add to your Cargo.toml:

[dependencies]
emailit = "2"
tokio = { version = "1", features = ["full"] }

Getting Started

use emailit::types::CreateEmailBaseOptions;
use emailit::{Emailit, Result};

#[tokio::main]
async fn main() -> Result<()> {
    let emailit = Emailit::new("your_api_key");

    let email = CreateEmailBaseOptions::new(
        "hello@yourdomain.com",
        ["user@example.com"],
        "Hello from Emailit",
    )
    .with_html("<h1>Welcome!</h1><p>Thanks for signing up.</p>");

    let result = emailit.emails.send(email).await?;

    println!("{}", result.id.unwrap());     // em_abc123...
    println!("{}", result.status.unwrap()); // pending

    Ok(())
}

All service methods return strongly typed response structs with Option fields for flexible API responses.

Available Services

Service Property Description
Emails emailit.emails Send, list, get, cancel, retry emails
Domains emailit.domains Create, verify, list, manage sending domains
API Keys emailit.api_keys Create, list, manage API keys
Audiences emailit.audiences Create, list, manage audiences
Subscribers emailit.subscribers Add, list, manage subscribers in audiences
Templates emailit.templates Create, list, publish email templates
Suppressions emailit.suppressions Create, list, manage suppressed addresses
Email Verifications emailit.email_verifications Verify email addresses
Email Verification Lists emailit.email_verification_lists Create, list, get results, export
Webhooks emailit.webhooks Create, list, manage webhooks
Contacts emailit.contacts Create, list, manage contacts
Events emailit.events List and retrieve events

Usage

Emails

Send an email

use emailit::types::CreateEmailBaseOptions;

let email = CreateEmailBaseOptions::new(
    "hello@yourdomain.com",
    ["user@example.com"],
    "Hello from Emailit",
)
.with_html("<h1>Welcome!</h1>");

let result = emailit.emails.send(email).await?;
println!("{}", result.id.unwrap());
println!("{}", result.status.unwrap());

Send with a template

use emailit::types::CreateEmailBaseOptions;
use std::collections::HashMap;
use serde_json::json;

let mut variables = HashMap::new();
variables.insert("name".into(), json!("John Doe"));
variables.insert("company".into(), json!("Acme Inc"));

let email = CreateEmailBaseOptions::new(
    "hello@yourdomain.com",
    ["user@example.com"],
    "",
)
.with_template("welcome_email")
.with_variables(variables);

let result = emailit.emails.send(email).await?;

Send with attachments

use emailit::types::{Attachment, CreateEmailBaseOptions};

let email = CreateEmailBaseOptions::new(
    "invoices@yourdomain.com",
    ["customer@example.com"],
    "Your Invoice #12345",
)
.with_html("<p>Please find your invoice attached.</p>")
.with_attachments(vec![
    Attachment::new("invoice.pdf", base64_content)
        .with_content_type("application/pdf"),
]);

let result = emailit.emails.send(email).await?;

Schedule an email

let email = CreateEmailBaseOptions::new(
    "reminders@yourdomain.com",
    ["user@example.com"],
    "Appointment Reminder",
)
.with_html("<p>Your appointment is tomorrow at 2 PM.</p>")
.with_scheduled_at("2026-01-10T09:00:00Z");

let result = emailit.emails.send(email).await?;
println!("{}", result.status.unwrap());       // scheduled

Send with tracking

use emailit::types::{CreateEmailBaseOptions, Tracking};

let email = CreateEmailBaseOptions::new(
    "hello@yourdomain.com",
    ["user@example.com"],
    "Tracked Email",
)
.with_html("<p>This email is tracked.</p>")
.with_tracking(Tracking::new().with_loads(true).with_clicks(true));

let result = emailit.emails.send(email).await?;

List emails

use emailit::types::ListEmailsParams;

let emails = emailit.emails.list(Some(ListEmailsParams {
    page: Some(1),
    limit: Some(10),
})).await?;

for email in &emails {
    println!("{}{}", email.id.as_deref().unwrap_or(""), email.status.as_deref().unwrap_or(""));
}

if emails.has_more() {
    // fetch next page
}

Cancel / Retry

emailit.emails.cancel("em_abc123").await?;
emailit.emails.retry("em_abc123").await?;

Domains

use emailit::types::{CreateDomainParams, UpdateDomainParams};

// Create a domain
let domain = emailit.domains.create(
    CreateDomainParams::new("example.com")
        .with_track_loads(true)
        .with_track_clicks(true),
).await?;
println!("{}", domain.id.unwrap());

// Verify DNS
let domain = emailit.domains.verify("sd_123").await?;

// List all domains
let domains = emailit.domains.list(None).await?;

// Get a domain
let domain = emailit.domains.get("sd_123").await?;

// Update a domain
let domain = emailit.domains.update("sd_123", UpdateDomainParams {
    track_loads: None,
    track_clicks: Some(false),
}).await?;

// Delete a domain
emailit.domains.delete("sd_123").await?;

API Keys

use emailit::types::{CreateApiKeyParams, UpdateApiKeyParams};

// Create an API key
let key = emailit.api_keys.create(
    CreateApiKeyParams::new("Production Key").with_scope("full"),
).await?;
println!("{}", key.key.unwrap()); // only available on create

// List all API keys
let keys = emailit.api_keys.list(None).await?;

// Get an API key
let key = emailit.api_keys.get("ak_123").await?;

// Update an API key
emailit.api_keys.update("ak_123", UpdateApiKeyParams {
    name: Some("Renamed Key".into()),
    scope: None,
    sending_domain_id: None,
}).await?;

// Delete an API key
emailit.api_keys.delete("ak_123").await?;

Audiences

use emailit::types::{CreateAudienceParams, UpdateAudienceParams};

// Create an audience
let audience = emailit.audiences.create(
    CreateAudienceParams::new("Newsletter"),
).await?;
println!("{}", audience.id.unwrap());
println!("{}", audience.token.unwrap());

// List audiences
let audiences = emailit.audiences.list(None).await?;

// Get an audience
let audience = emailit.audiences.get("aud_123").await?;

// Update an audience
emailit.audiences.update("aud_123", UpdateAudienceParams {
    name: "Updated Newsletter".into(),
}).await?;

// Delete an audience
emailit.audiences.delete("aud_123").await?;

Subscribers

Subscribers belong to an audience, so the audience ID is always the first argument.

use emailit::types::{CreateSubscriberParams, UpdateSubscriberParams};

// Add a subscriber
let subscriber = emailit.subscribers.create("aud_123",
    CreateSubscriberParams::new("user@example.com")
        .with_first_name("John")
        .with_last_name("Doe"),
).await?;

// List subscribers in an audience
let subscribers = emailit.subscribers.list("aud_123", None).await?;

// Get a subscriber
let subscriber = emailit.subscribers.get("aud_123", "sub_456").await?;

// Update a subscriber
emailit.subscribers.update("aud_123", "sub_456", UpdateSubscriberParams {
    email: None,
    first_name: Some("Jane".into()),
    last_name: None,
    custom_fields: None,
    subscribed: None,
}).await?;

// Delete a subscriber
emailit.subscribers.delete("aud_123", "sub_456").await?;

Templates

use emailit::types::{CreateTemplateParams, UpdateTemplateParams};

// Create a template
let template = emailit.templates.create(
    CreateTemplateParams::new("Welcome")
        .with_subject("Welcome!")
        .with_html("<h1>Hi {{name}}</h1>"),
).await?;

// List templates
let templates = emailit.templates.list(None).await?;

// Get a template
let template = emailit.templates.get("tem_123").await?;

// Update a template
emailit.templates.update("tem_123", UpdateTemplateParams {
    name: None,
    subject: Some("New Subject".into()),
    from: None,
    reply_to: None,
    html: None,
    text: None,
}).await?;

// Publish a template
emailit.templates.publish("tem_123").await?;

// Delete a template
emailit.templates.delete("tem_123").await?;

Suppressions

use emailit::types::{CreateSuppressionParams, UpdateSuppressionParams};

// Create a suppression
let suppression = emailit.suppressions.create(
    CreateSuppressionParams::new("spam@example.com")
        .with_type("hard_bounce")
        .with_reason("Manual suppression"),
).await?;

// List suppressions
let suppressions = emailit.suppressions.list(None).await?;

// Get a suppression
let suppression = emailit.suppressions.get("sup_123").await?;

// Update a suppression
emailit.suppressions.update("sup_123", UpdateSuppressionParams {
    reason: Some("Updated".into()),
    keep_until: None,
}).await?;

// Delete a suppression
emailit.suppressions.delete("sup_123").await?;

Email Verifications

use emailit::types::VerifyEmailParams;

let result = emailit.email_verifications.verify(
    VerifyEmailParams::new("test@example.com"),
).await?;

println!("{}", result.status.unwrap()); // valid
println!("{}", result.score.unwrap());  // 0.95
println!("{}", result.risk.unwrap());   // low

Email Verification Lists

use emailit::types::{
    CreateEmailVerificationListParams,
    EmailVerificationListResultsParams,
};

// Create a verification list
let list = emailit.email_verification_lists.create(
    CreateEmailVerificationListParams::new(
        "Marketing List Q1",
        ["user1@example.com", "user2@example.com", "user3@example.com"],
    ),
).await?;
println!("{}", list.id.unwrap());     // evl_abc123...
println!("{}", list.status.unwrap()); // pending

// List all verification lists
let lists = emailit.email_verification_lists.list(None).await?;

// Get a verification list
let list = emailit.email_verification_lists.get("evl_abc123").await?;

// Get verification results
let results = emailit.email_verification_lists.results(
    "evl_abc123",
    Some(EmailVerificationListResultsParams {
        page: Some(1),
        limit: Some(50),
    }),
).await?;

for result in &results {
    println!("{}{}", result["email"], result["result"]);
}

// Export results as XLSX
let response = emailit.email_verification_lists.export("evl_abc123").await?;
std::fs::write("results.xlsx", &response.body)?;

Webhooks

use emailit::types::{CreateWebhookParams, UpdateWebhookParams};

// Create a webhook
let webhook = emailit.webhooks.create(
    CreateWebhookParams::new("My Webhook", "https://example.com/hook")
        .with_all_events(true)
        .with_enabled(true),
).await?;
println!("{}", webhook.id.unwrap());

// List webhooks
let webhooks = emailit.webhooks.list(None).await?;

// Get a webhook
let webhook = emailit.webhooks.get("wh_123").await?;

// Update a webhook
emailit.webhooks.update("wh_123", UpdateWebhookParams {
    name: None,
    url: None,
    all_events: None,
    enabled: Some(false),
    events: None,
}).await?;

// Delete a webhook
emailit.webhooks.delete("wh_123").await?;

Contacts

use emailit::types::{CreateContactParams, UpdateContactParams};

// Create a contact
let contact = emailit.contacts.create(
    CreateContactParams::new("user@example.com")
        .with_first_name("John")
        .with_last_name("Doe"),
).await?;
println!("{}", contact.id.unwrap());

// List contacts
let contacts = emailit.contacts.list(None).await?;

// Get a contact
let contact = emailit.contacts.get("con_123").await?;

// Update a contact
emailit.contacts.update("con_123", UpdateContactParams {
    email: None,
    first_name: Some("Jane".into()),
    last_name: None,
    custom_fields: None,
    unsubscribed: None,
}).await?;

// Delete a contact
emailit.contacts.delete("con_123").await?;

Events

use emailit::types::ListEventsParams;

// List events
let events = emailit.events.list(Some(ListEventsParams {
    page: None,
    limit: None,
    event_type: Some("email.delivered".into()),
})).await?;

for event in &events {
    println!("{}", event.event_type.as_deref().unwrap_or(""));
}

// Get an event
let event = emailit.events.get("evt_123").await?;
println!("{}", event.event_type.unwrap());

Webhook Events

The SDK provides webhook signature verification via standalone functions, plus header constants.

Verifying Webhook Signatures

use emailit::{verify_webhook_signature, HEADER_SIGNATURE, HEADER_TIMESTAMP};

let raw_body = r#"{"type":"email.delivered","data":{"email_id":"em_123"}}"#;
let signature = headers.get(HEADER_SIGNATURE).unwrap();
let timestamp = headers.get(HEADER_TIMESTAMP).unwrap();
let secret = "your_webhook_signing_secret";

match verify_webhook_signature(raw_body, signature, timestamp, secret, None) {
    Ok(event) => {
        println!("Event type: {}", event.event_type);

        if let Some(data) = &event.data {
            println!("Email ID: {}", data["email_id"]);
        }
    }
    Err(e) => {
        eprintln!("Verification failed: {}", e);
    }
}

You can disable replay protection by passing Some(0), or set a custom tolerance in seconds:

// Skip replay check
let event = verify_webhook_signature(raw_body, signature, timestamp, secret, Some(0))?;

// Custom 10-minute tolerance
let event = verify_webhook_signature(raw_body, signature, timestamp, secret, Some(600))?;

Available Event Types

Emails: email.accepted, email.scheduled, email.delivered, email.bounced, email.attempted, email.failed, email.rejected, email.suppressed, email.received, email.complained, email.clicked, email.loaded

Domains: domain.created, domain.updated, domain.deleted

Audiences: audience.created, audience.updated, audience.deleted

Subscribers: subscriber.created, subscriber.updated, subscriber.deleted

Contacts: contact.created, contact.updated, contact.deleted

Templates: template.created, template.updated, template.deleted

Suppressions: suppression.created, suppression.updated, suppression.deleted

Email Verifications: email_verification.created, email_verification.updated, email_verification.deleted

Email Verification Lists: email_verification_list.created, email_verification_list.updated, email_verification_list.deleted

Error Handling

The SDK uses a typed Error enum for all API errors:

use emailit::Error;

match emailit.emails.send(email).await {
    Ok(result) => println!("Sent: {}", result.id.unwrap()),
    Err(e) if e.is_authentication() => {
        // Invalid API key (401)
        println!("Auth error: {}", e);
    }
    Err(e) if e.is_invalid_request() => {
        // Bad request or not found (400, 404)
        if let Some(api_err) = e.api_error() {
            println!("Status: {}, Body: {}", api_err.status, api_err.body);
        }
    }
    Err(e) if e.is_rate_limit() => {
        // Too many requests (429)
    }
    Err(e) if e.is_unprocessable_entity() => {
        // Validation failed (422)
    }
    Err(e) if e.is_connection() => {
        // Network error
    }
    Err(e) => {
        // Any other API error
        println!("Error: {}", e);
        if let Some(status) = e.status() {
            println!("HTTP status: {}", status);
        }
    }
}

License

MIT -- see LICENSE for details.