# Emailit Rust
[](https://github.com/emailit/emailit-rust/actions)
[](https://crates.io/crates/emailit)
[](https://github.com/emailit/emailit-rust/blob/main/LICENSE)
The official Rust SDK for the [Emailit](https://emailit.com) Email API.
## Requirements
- Rust 1.85+
- Tokio runtime
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
emailit = "2"
tokio = { version = "1", features = ["full"] }
```
## Getting Started
```rust
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
| 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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
emailit.emails.cancel("em_abc123").await?;
emailit.emails.retry("em_abc123").await?;
```
---
### Domains
```rust
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
```rust
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
```rust
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.
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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:
```rust
// 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:
```rust
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](LICENSE) for details.