4 stable releases
Uses new Rust 2024
| 1.0.3 | Jan 14, 2026 |
|---|---|
| 1.0.2 | Jan 8, 2026 |
| 1.0.1 | Nov 24, 2025 |
| 1.0.0 | Nov 19, 2025 |
#497 in Web programming
150KB
3.5K
SLoC
Unsent Rust SDK
Official Rust SDK for the Unsent API - Send transactional emails with ease.
Prerequisites
- Unsent API key
- Verified domain
- Rust 1.70 or higher
Installation
Add this to your Cargo.toml:
[dependencies]
unsent = "1.0"
serde_json = "1.0"
Usage
Basic Setup
use unsent::{Client, models::EmailCreate};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("un_xxxx")?;
// Use the client
Ok(())
}
Environment Variables
You can also set your API key using environment variables:
// Set UNSENT_API_KEY in your environment
// Then initialize without passing the key
let client = Client::new("")?;
Sending Emails
Simple Email
use unsent::{Client, models::EmailCreate, emails::EmailsClient};
let client = Client::new("un_xxxx")?;
let emails = EmailsClient::new(&client);
let email = EmailCreate {
to: serde_json::json!("hello@acme.com"),
from: "hello@company.com".to_string(),
subject: Some("Unsent email".to_string()),
html: Some(Some("<p>Unsent is the best email service provider to send emails</p>".to_string())),
text: Some(Some("Unsent is the best email service provider to send emails".to_string())),
..Default::default()
};
let response = emails.send(&email)?;
println!("Email sent! ID: {}", response.id);
Email with Attachments
use unsent::models::{EmailCreate, Attachment};
let email = EmailCreate {
to: serde_json::json!("hello@acme.com"),
from: "hello@company.com".to_string(),
subject: Some("Email with attachment".to_string()),
html: Some(Some("<p>Please find the attachment below</p>".to_string())),
attachments: Some(vec![
serde_json::json!({
"filename": "document.pdf",
"content": "base64-encoded-content-here"
})
]),
..Default::default()
};
let response = emails.send(&email)?;
Scheduled Email
use chrono::{Utc, Duration};
let scheduled_time = (Utc::now() + Duration::hours(1)).to_rfc3339();
let email = EmailCreate {
to: serde_json::json!("hello@acme.com"),
from: "hello@company.com".to_string(),
subject: Some("Scheduled email".to_string()),
html: Some(Some("<p>This email was scheduled</p>".to_string())),
scheduled_at: Some(scheduled_time),
..Default::default()
};
let response = emails.send(&email)?;
Batch Emails
use unsent::models::EmailBatchItem;
let batch = vec![
EmailBatchItem {
to: serde_json::json!("user1@example.com"),
from: "hello@company.com".to_string(),
subject: Some("Hello User 1".to_string()),
html: Some(Some("<p>Welcome User 1</p>".to_string())),
..Default::default()
},
EmailBatchItem {
to: serde_json::json!("user2@example.com"),
from: "hello@company.com".to_string(),
subject: Some("Hello User 2".to_string()),
html: Some(Some("<p>Welcome User 2</p>".to_string())),
..Default::default()
},
];
let response = emails.batch(&batch)?;
println!("Sent {} emails", response.ids.len());
Idempotent Retries
To prevent duplicate emails when retrying failed requests, you can provide an idempotency key.
use unsent::models::RequestOptions;
let options = RequestOptions {
idempotency_key: Some("unique-key-123".to_string()),
};
let response = emails.send_with_options(&email, &options)?;
Managing Emails
Get Email Details
let email = emails.get("email_id")?;
println!("Email status: {}", email.data["status"]);
Update Email
use unsent::models::EmailUpdate;
let update = EmailUpdate {
scheduled_at: None,
};
let response = emails.update("email_id", &update)?;
Cancel Scheduled Email
let response = emails.cancel("email_id")?;
println!("Email cancelled successfully");
List Emails
use unsent::models::EmailListParams;
let params = EmailListParams {
limit: Some(20),
page: Some(1),
..Default::default()
};
let emails = emails.list(Some(¶ms))?;
Email Statistics
// Get bounces
let bounces = emails.bounces(None)?;
// Get complaints
let complaints = emails.complaints(None)?;
// Get unsubscribes
let unsubscribes = emails.unsubscribes(None)?;
Managing Contact Books
List Contact Books
use unsent::contact_books::ContactBooksClient;
let client = Client::new("un_xxxx")?;
let books = ContactBooksClient::new(&client);
let book_list = books.list()?;
Create Contact Book
use unsent::models::ContactBookCreate;
let book = ContactBookCreate {
name: "Newsletter Subscribers".to_string(),
emoji: Some("📧".to_string()),
properties: None,
};
let response = books.create(&book)?;
Get Contact Book
let book = books.get("book_id")?;
Update Contact Book
use unsent::models::ContactBookUpdate;
let update = ContactBookUpdate {
name: Some("VIP List".to_string()),
emoji: None,
properties: None,
};
let response = books.update("book_id", &update)?;
Delete Contact Book
let response = books.delete("book_id")?;
Managing Contacts
List Contacts
// List contacts in a book
let contacts_list = contacts.list("book_id", None)?;
Create Contact
use unsent::{models::ContactCreate, contacts::ContactsClient};
use std::collections::HashMap;
let client = Client::new("un_xxxx")?;
let contacts = ContactsClient::new(&client);
let mut metadata = HashMap::new();
metadata.insert("company".to_string(), serde_json::json!("Acme Inc"));
metadata.insert("role".to_string(), serde_json::json!("Developer"));
let contact = ContactCreate {
email: "user@example.com".to_string(),
first_name: Some("John".to_string()),
last_name: Some("Doe".to_string()),
metadata: Some(metadata),
// Optional fields
phone_number: None,
subscribed: None,
};
let response = contacts.create("contact_book_id", &contact)?;
Get Contact
let contact = contacts.get("contact_book_id", "contact_id")?;
Update Contact
use unsent::models::ContactUpdate;
let mut metadata = HashMap::new();
metadata.insert("role".to_string(), serde_json::json!("Senior Developer"));
let update = ContactUpdate {
first_name: Some("Jane".to_string()),
last_name: None,
metadata: Some(metadata),
// Optional
email: None,
phone_number: None,
subscribed: None,
};
let response = contacts.update("contact_book_id", "contact_id", &update)?;
Upsert Contact
use unsent::models::ContactUpsert;
let upsert = ContactUpsert {
email: Some("user@example.com".to_string()),
first_name: Some("John".to_string()),
last_name: Some("Doe".to_string()),
metadata: None,
// Optional fields
phone_number: None,
subscribed: None,
};
// Note: Pass upsert struct directly, serialization handles wrapper
let response = contacts.upsert("contact_book_id", "contact_id", &upsert)?;
Delete Contact
let response = contacts.delete("contact_book_id", "contact_id")?;
Managing Campaigns
List Campaigns
let active_campaigns = campaigns.list().await?;
Create Campaign
use unsent::{models::CampaignCreate, campaigns::CampaignsClient};
let client = Client::new("un_xxxx")?;
let campaigns = CampaignsClient::new(&client);
let campaign = CampaignCreate {
name: "Welcome Series".to_string(),
subject: "Welcome to our service!".to_string(),
html: "<p>Thanks for joining us!</p>".to_string(),
from: "welcome@example.com".to_string(),
contact_book_id: "cb_1234567890".to_string(),
// Optional fields
reply_to: None,
cc: None,
bcc: None,
attachments: None,
};
let response = campaigns.create(&campaign)?;
println!("Campaign created! ID: {}", response.campaign.id);
Schedule Campaign
use unsent::models::CampaignSchedule;
let schedule = CampaignSchedule {
scheduled_at: "2024-12-01T10:00:00Z".to_string(),
};
let response = campaigns.schedule(&campaign.id, &schedule)?;
Pause/Resume Campaigns
// Pause a campaign
let pause_resp = campaigns.pause("campaign_123")?;
println!("Campaign paused successfully!");
// Resume a campaign
let resume_resp = campaigns.resume("campaign_123")?;
println!("Campaign resumed successfully!");
Get Campaign Details
let campaign_item = campaigns.get("campaign_id")?;
println!("Campaign status: {:?}", campaign_item.status);
println!("Recipients: {:?}", campaign_item.stats.total);
println!("Sent: {:?}", campaign_item.stats.sent);
Managing Domains
List Domains
use unsent::domains::DomainsClient;
let client = Client::new("un_xxxx")?;
let domains = DomainsClient::new(&client);
let domain_list = domains.list()?;
for domain in domain_list {
println!("Domain: {}, Status: {:?}", domain.domain, domain.status);
}
Create Domain
use unsent::models::DomainCreate;
let domain = DomainCreate {
domain: "example.com".to_string(),
};
let response = domains.create(&domain)?;
Verify Domain
let response = domains.verify("domain_id")?;
println!("Verification status: {}", response.success);
Get Domain
let domain = domains.get("domain_id")?;
Delete Domain
let response = domains.delete("domain_id")?;
Managing Webhooks (Coming Soon)
Note: Webhooks are currently in development and not fully implemented (server-side). The SDK includes these methods for future compatibility.
List Webhooks
use unsent::webhooks::WebhooksClient;
let client = Client::new("un_xxxx")?;
let webhooks = WebhooksClient::new(&client);
let refs = webhooks.list()?;
Create Webhook
use unsent::models::WebhookCreate;
let webhook = WebhookCreate {
url: "https://example.com/webhook".to_string(),
events: vec!["email.sent".to_string()],
};
let response = webhooks.create(&webhook)?;
println!("Webhook created! ID: {}", response.id);
Get Webhook
let webhook = webhooks.get("webhook_id").await?;
Update Webhook
use unsent::models::WebhookUpdate;
let update = WebhookUpdate {
url: Some("https://example.com/new-webhook".to_string()),
events: None,
};
let response = webhooks.update("webhook_id", &update).await?;
Test Webhook
let response = webhooks.test("webhook_id").await?;
Delete Webhook
let response = webhooks.delete("webhook_id")?;
Managing Templates
List Templates
use unsent::templates::TemplatesClient;
let client = Client::new("un_xxxx")?;
let templates = TemplatesClient::new(&client);
let template_list = templates.list().await?;
Create Template
use unsent::models::TemplateCreate;
let template = TemplateCreate {
name: "Welcome Email".to_string(),
subject: "Welcome!".to_string(),
html: Some("<h1>Welcome</h1>".to_string()),
content: Some("Welcome".to_string()),
};
let response = templates.create(&template).await?;
Get Template
let template = templates.get("template_id").await?;
Update Template
use unsent::models::TemplateUpdate;
let update = TemplateUpdate {
name: Some("Updated Name".to_string()),
subject: None,
html: None,
content: None,
};
let response = templates.update("template_id", &update).await?;
Delete Template
let response = templates.delete("template_id").await?;
Managing Suppressions
List Suppressions
use unsent::suppressions::SuppressionsClient;
let client = Client::new("un_xxxx")?;
let suppressions = SuppressionsClient::new(&client);
let suppression_list = suppressions.list(None).await?;
Add Suppression
use unsent::models::{AddSuppressionRequest, Reason};
let req = AddSuppressionRequest::new("spam@example.com".to_string(), Reason::Complaint);
let response = suppressions.add(&req).await?;
Delete Suppression
let response = suppressions.delete("spam@example.com").await?;
Activity & Analytics
Activity Feed
use unsent::activity::ActivityClient;
let client = Client::new("un_xxxx")?;
let activity = ActivityClient::new(&client);
let feed = activity.get(None).await?;
Analytics
use unsent::analytics::AnalyticsClient;
let client = Client::new("un_xxxx")?;
let analytics = AnalyticsClient::new(&client);
// General analytics
let stats = analytics.get().await?;
// Time series
let time_series = analytics.time_series(None).await?;
// Reputation
let reputation = analytics.reputation(None).await?;
Metrics & Stats
use unsent::{metrics::MetricsClient, stats::StatsClient};
let client = Client::new("un_xxxx")?;
// Metrics
let metrics = MetricsClient::new(&client);
let metrics_data = metrics.get(None).await?;
// Stats
let stats = StatsClient::new(&client);
let stats_data = stats.get(None).await?;
Events
use unsent::events::EventsClient;
let client = Client::new("un_xxxx")?;
let events = EventsClient::new(&client);
let event_list = events.list(None).await?;
System & Settings
API Keys
use unsent::api_keys::ApiKeysClient;
use unsent::models::ApiKeyCreate;
let client = Client::new("un_xxxx")?;
let api_keys = ApiKeysClient::new(&client);
// List
let keys = api_keys.list().await?;
// Create
let new_key = ApiKeyCreate::new("Prod Key".to_string());
let response = api_keys.create(&new_key).await?;
// Delete
let response = api_keys.delete("key_id").await?;
Settings & Team
use unsent::{settings::SettingsClient, teams::TeamsClient};
let client = Client::new("un_xxxx")?;
// Settings
let settings_client = SettingsClient::new(&client);
let settings = settings_client.get().await?;
// Teams
let teams_client = TeamsClient::new(&client);
let teams = teams_client.list().await?;
let my_team = teams_client.get().await?;
System Health
use unsent::system::SystemClient;
let client = Client::new("un_xxxx")?;
let system = SystemClient::new(&client);
let health = system.health().await?;
let version = system.version().await?;
Error Handling
The SDK uses Rust's Result type for error handling:
use unsent::{Client, UnsentError};
let client = Client::new("un_xxxx")?;
match emails.send(&email) {
Ok(response) => println!("Email sent! ID: {}", response.id),
Err(UnsentError::Api(api_error)) => {
eprintln!("API Error: {} - {}", api_error.code, api_error.message);
}
Err(e) => eprintln!("Error: {}", e),
}
To disable automatic error raising:
let client = Client::new("un_xxxx")?.with_raise_on_error(false);
Custom HTTP Client
For advanced use cases, you can provide your own HTTP client:
use reqwest::blocking::Client as HttpClient;
use std::time::Duration;
let http_client = HttpClient::builder()
.timeout(Duration::from_secs(30))
.build()?;
let client = Client::new("un_xxxx")?.with_http_client(http_client);
API Reference
Client Methods
Client::new(key)- Initialize the client.with_base_url(url)- Set custom base URL.with_http_client(client)- Set custom HTTP client.with_raise_on_error(raise)- Set error handling behavior
Email Methods
emails.send(payload)- Send an email (alias for create)emails.create(payload)- Create and send an emailemails.batch(emails)- Send multiple emails in batchemails.get(email_id)- Get email detailsemails.update(email_id, payload)- Update a scheduled emailemails.cancel(email_id)- Cancel a scheduled emailemails.list(params)- List emails with filtersemails.bounces(params)- List bounced emailsemails.complaints(params)- List spam complaintsemails.unsubscribes(params)- List unsubscribes
Contact Methods
contacts.list(book_id, params)- List contactscontacts.create(book_id, payload)- Create a contactcontacts.get(book_id, contact_id)- Get contact detailscontacts.update(book_id, contact_id, payload)- Update a contactcontacts.upsert(book_id, contact_id, payload)- Upsert a contactcontacts.delete(book_id, contact_id)- Delete a contact
Contact Book Methods
contact_books.list()- List contact bookscontact_books.create(payload)- Create contact bookcontact_books.get(id)- Get contact bookcontact_books.update(id, payload)- Update contact bookcontact_books.delete(id)- Delete contact book
Campaign Methods
campaigns.list()- List all campaignscampaigns.create(payload)- Create a campaigncampaigns.get(campaign_id)- Get campaign detailscampaigns.schedule(campaign_id, payload)- Schedule a campaigncampaigns.pause(campaign_id)- Pause a campaigncampaigns.resume(campaign_id)- Resume a campaign
Domain Methods
domains.list()- List all domainsdomains.create(payload)- Create a domaindomains.verify(domain_id)- Verify a domaindomains.get(domain_id)- Get domain detailsdomains.delete(domain_id)- Delete a domain
Webhook Methods
webhooks.list()- List all webhookswebhooks.create(payload)- Create a webhookwebhooks.update(id, payload)- Update a webhookwebhooks.delete(id)- Delete a webhook
Template Methods
templates.list()- List all templatestemplates.create(payload)- Create a templatetemplates.get(id)- Get template detailstemplates.update(id, payload)- Update a templatetemplates.delete(id)- Delete a template
Activity Methods
activity.get(params)- Get activity feed
Analytics Methods
analytics.get()- Get email analyticsanalytics.time_series(params)- Get analytics time seriesanalytics.reputation(params)- Get sender reputation
Metrics Methods
metrics.get(params)- Get performance metrics
Stats Methods
stats.get(params)- Get email statistics
Event Methods
events.list(params)- List email events
API Key Methods
api_keys.list()- List all API keysapi_keys.create(payload)- Create an API keyapi_keys.delete(id)- Delete an API key
Settings Methods
settings.get()- Get team settings
System Methods
system.health()- Check API healthsystem.version()- Get API version
Team Methods
teams.list()- List all teamsteams.get()- Get current team
Suppression Methods
suppressions.list(params)- List suppressed emailssuppressions.add(payload)- Add email to suppression listsuppressions.delete(email)- Remove email from suppression list
Requirements
- Rust 1.70+
License
MIT
Support
Dependencies
~5–20MB
~233K SLoC