Rust
Official Unsent Rust SDK for sending emails and managing contacts.
This guide shows how to install and use the official unsent Rust SDK.
Installation
Add the unsent crate to your Cargo.toml file:
[dependencies]
unsent = "1.0"
serde_json = "1.0"Initialize
Initialize the client with your API key.
use unsent::Client;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("un_xxx")?;
Ok(())
}Send an email
Now you can send an email. First, create an EmailsClient using your initialized client. Then, define an EmailCreate struct with your email details and pass it to the send method.
use unsent::{Client, models::EmailCreate, emails::EmailsClient};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("un_xxx")?;
let emails = EmailsClient::new(&client);
let email = EmailCreate {
to: serde_json::json!("user@example.com"),
from: "no-reply@yourdomain.com".to_string(),
subject: Some("Welcome".to_string()),
html: Some(Some("<strong>Hello!</strong>".to_string())),
text: None,
..Default::default()
};
let response = emails.send(&email)?;
println!("Email sent! ID: {}", response.id);
Ok(())
}With attachments and scheduling
You can also send emails with attachments and schedule them for later delivery.
- Attachments: Create a vector of
serde_json::Valueobjects representing the attachments. - Scheduling: Use the
scheduled_atfield with an RFC 3339 formatted string.
use unsent::models::EmailCreate;
use chrono::{Utc, Duration};
// Calculate a time 10 minutes from now
let scheduled_time = (Utc::now() + Duration::minutes(10)).to_rfc3339();
let email = EmailCreate {
to: serde_json::json!("user@example.com"),
from: "no-reply@yourdomain.com".to_string(),
subject: Some("Report".to_string()),
text: Some(Some("See attached.".to_string())),
attachments: Some(vec![
serde_json::json!({
"filename": "report.txt",
"content": "SGVsbG8gd29ybGQ=" // Content must be Base64 encoded
})
]),
scheduled_at: Some(scheduled_time),
..Default::default()
};
let response = emails.create(&email)?;Batch send
To send multiple emails efficiently in a single request, use the batch method with a vector of EmailBatchItem structs.
use unsent::models::EmailBatchItem;
let batch = vec![
EmailBatchItem {
to: serde_json::json!("a@example.com"),
from: "no-reply@yourdomain.com".to_string(),
subject: Some("A".to_string()),
html: Some(Some("<p>A</p>".to_string())),
..Default::default()
},
EmailBatchItem {
to: serde_json::json!("b@example.com"),
from: "no-reply@yourdomain.com".to_string(),
subject: Some("B".to_string()),
html: Some(Some("<p>B</p>".to_string())),
..Default::default()
},
];
let response = emails.batch(&batch)?;
println!("Sent {} emails", response.ids.len());Idempotent Retries
To safely retry requests, you can use RequestOptions with the _with_options methods.
use unsent::models::RequestOptions;
let options = RequestOptions {
idempotency_key: Some("unique-key-123".to_string()),
};
// For single email
emails.send_with_options(&email, &options)?;
// For batch emails
emails.batch_with_options(&batch, &options)?;Retrieve and manage emails
You can retrieve details of sent emails, update scheduled emails, or cancel them.
Get an email
Fetch the status and details of a specific email using its ID:
let email = emails.get("email_123")?;
println!("Email status: {}", email.data["status"]);Update schedule time
Change the scheduled delivery time for a pending email:
use unsent::models::EmailUpdate;
use chrono::{Utc, Duration};
let new_time = (Utc::now() + Duration::hours(1)).to_rfc3339();
let update = EmailUpdate {
scheduled_at: Some(new_time),
};
let response = emails.update("email_123", &update)?;Cancel a scheduled email
Cancel a scheduled email so it won't be sent:
let response = emails.cancel("email_123")?;
println!("Email cancelled successfully");List Emails
List previously sent emails with pagination.
use unsent::models::EmailListParams;
let params = EmailListParams {
limit: Some(20),
page: Some(1),
..Default::default()
};
let email_list = emails.list(Some(¶ms)).await?;Email Statistics
Get statistics on your email delivery.
// Bounces
let bounces = emails.bounces(None).await?;
// Complaints
let complaints = emails.complaints(None).await?;
// Unsubscribes
let unsubscribes = emails.unsubscribes(None).await?;Contact Books
Organize your contacts into 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().await?;Manage Contact Books
use unsent::models::{ContactBookCreate, ContactBookUpdate};
// Create
let book = ContactBookCreate {
name: "Newsletter".to_string(),
emoji: Some("📧".to_string()),
properties: None,
};
let response = books.create(&book).await?;
// Get
let book_details = books.get("book_id").await?;
// Update
let update = ContactBookUpdate {
name: Some("VIPs".to_string()),
emoji: None,
properties: None,
};
let response = books.update("book_id", &update).await?;
// Delete
let response = books.delete("book_id").await?;Contacts
Manage your contacts and organize them into contact books. All contact operations require a contact book ID.
List Contacts
// List contacts in a book
let contacts_list = contacts.list("book_id", None).await?;Create a contact
Add a new contact to a specific contact book. You can include custom metadata using a HashMap.
use unsent::{models::ContactCreate, contacts::ContactsClient};
use std::collections::HashMap;
let client = Client::new("un_xxx")?;
let contacts = ContactsClient::new(&client);
let mut metadata = HashMap::new();
metadata.insert("plan".to_string(), serde_json::json!("pro"));
let contact = ContactCreate {
email: "user@example.com".to_string(),
first_name: Some("Jane".to_string()),
last_name: None,
metadata: Some(metadata),
..Default::default()
};
let response = contacts.create("book_123", &contact)?;Get a contact
Retrieve a contact's details:
let contact = contacts.get("book_123", "contact_456")?;Update a contact
Update a contact's information:
use unsent::models::ContactUpdate;
let mut metadata = HashMap::new();
metadata.insert("plan".to_string(), serde_json::json!("enterprise"));
let update = ContactUpdate {
first_name: Some("John".to_string()),
last_name: None,
metadata: Some(metadata),
// Optional
email: None,
phone_number: None,
subscribed: None,
};
let response = contacts.update("book_123", "contact_456", &update)?;Upsert a contact
Use upsert to create a contact if they don't exist, or update them if they do.
use unsent::models::ContactUpsert;
let upsert = ContactUpsert {
email: Some("user@example.com".to_string()),
first_name: Some("Jane".to_string()),
last_name: None,
metadata: None,
..Default::default()
};
let response = contacts.upsert("book_123", "contact_456", &upsert)?;Delete a contact
Remove a contact from a book:
let response = contacts.delete("book_123", "contact_456")?;Campaigns
Campaigns allow you to send emails to all contacts in a specific contact book.
List Campaigns
let active_campaigns = campaigns.list().await?;Create a campaign
Create a new campaign by defining its content and the target contact book.
use unsent::{models::CampaignCreate, campaigns::CampaignsClient};
let client = Client::new("un_xxx")?;
let campaigns = CampaignsClient::new(&client);
let campaign = CampaignCreate {
name: "Welcome Series".to_string(),
subject: "Welcome!".to_string(),
html: "<p>Thanks for joining us!</p>".to_string(),
from: "welcome@yourdomain.com".to_string(),
contact_book_id: "book_123".to_string(),
..Default::default()
};
let response = campaigns.create(&campaign)?;
println!("Campaign created! ID: {}", response.campaign.id);Schedule a campaign
Schedule the campaign to be sent at a specific time.
use unsent::models::CampaignSchedule;
let schedule = CampaignSchedule {
scheduled_at: "2024-12-01T10:00:00Z".to_string(),
};
let response = campaigns.schedule(&campaign.id, &schedule)?;Pause and resume campaigns
Control the delivery of your campaign.
// Pause
let pause_resp = campaigns.pause("campaign_123")?;
println!("Campaign paused successfully!");
// Resume
let resume_resp = campaigns.resume("campaign_123")?;
println!("Campaign resumed successfully!");Domains
Manage your sending domains.
List domains
Get a list of all domains and their statuses.
use unsent::domains::DomainsClient;
let client = Client::new("un_xxx")?;
let domains = DomainsClient::new(&client);
let domain_list = domains.list()?;
for domain in domain_list {
println!("Domain: {}, Status: {:?}", domain.domain, domain.status);
}Create a domain
Register a new domain for sending.
use unsent::models::DomainCreate;
let domain = DomainCreate {
domain: "yourdomain.com".to_string(),
};
let response = domains.create(&domain)?;Verify a domain
Check the verification status of a domain.
let response = domains.verify("domain_id")?;
println!("Verification status: {}", response.success);Get Domain
let domain = domains.get("domain_id").await?;Delete Domain
let response = domains.delete("domain_id").await?;Templates
Manage your email templates.
use unsent::{models::TemplateCreate, templates::TemplatesClient};
let client = Client::new("un_xxx")?;
let templates = TemplatesClient::new(&client);
// List templates
let response = templates.list().await?;
// Create a template
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?;Activity
Get activity feed for your account.
use unsent::{models::ActivityParams, activity::ActivityClient};
let client = Client::new("un_xxx")?;
let activity = ActivityClient::new(&client);
let params = ActivityParams {
limit: Some(10),
..Default::default()
};
let response = activity.get(Some(¶ms)).await?;Analytics
Get email analytics and reporting.
use unsent::analytics::AnalyticsClient;
let client = Client::new("un_xxx")?;
let analytics = AnalyticsClient::new(&client);
// Get general analytics
let stats = analytics.get().await?;
// Get time series data
let time_series = analytics.time_series(None).await?;
// Get sender reputation
let reputation = analytics.reputation(None).await?;Metric & Stats
Get performance metrics and delivery statistics.
use unsent::{metrics::MetricsClient, stats::StatsClient};
let client = Client::new("un_xxx")?;
// Metrics
let metrics = MetricsClient::new(&client);
let data = metrics.get(None).await?;
// Stats
let stats_client = StatsClient::new(&client);
let stats_data = stats_client.get(None).await?;Events
List email events with optional filtering.
use unsent::{models::EventsListParams, events::EventsClient};
let client = Client::new("un_xxx")?;
let events = EventsClient::new(&client);
let params = EventsListParams {
status: Some("DELIVERED".to_string()),
limit: Some(20),
..Default::default()
};
let response = events.list(Some(¶ms)).await?;API Keys
Manage your API keys programmatically.
use unsent::{models::ApiKeyCreate, api_keys::ApiKeysClient};
let client = Client::new("un_xxx")?;
let api_keys = ApiKeysClient::new(&client);
// List keys
let keys = api_keys.list().await?;
// Create key
let new_key = ApiKeyCreate::new("Production Key".to_string());
let response = api_keys.create(&new_key).await?;
// Delete key
let response = api_keys.delete("key_id").await?;Suppressions
Manage suppression lists (bounces, complaints, unsubscribes).
use unsent::{models::{AddSuppressionRequest, Reason}, suppressions::SuppressionsClient};
let client = Client::new("un_xxx")?;
let suppressions = SuppressionsClient::new(&client);
// List suppressions
let list = suppressions.list(None).await?;
// Add to suppression list
let req = AddSuppressionRequest::new("spam@example.com".to_string(), Reason::Complaint);
let response = suppressions.add(&req).await?;
// Remove from suppression list
let response = suppressions.delete("spam@example.com").await?;Webhooks
Manage webhooks for real-time event notifications.
use unsent::{models::WebhookCreate, webhooks::WebhooksClient};
let client = Client::new("un_xxx")?;
let webhooks = WebhooksClient::new(&client);
// Create webhook
let webhook = WebhookCreate {
url: "https://api.myapp.com/webhooks".to_string(),
events: vec!["email.sent".to_string(), "email.delivered".to_string()],
};
let response = webhooks.create(&webhook).await?;
// List webhooks
let hooks = webhooks.list().await?;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").await?;System & Teams
Access system health and team information.
use unsent::{system::SystemClient, teams::TeamsClient};
let client = Client::new("un_xxx")?;
// System
let system = SystemClient::new(&client);
let health = system.health().await?;
// Teams
let teams = TeamsClient::new(&client);
let my_team = teams.get().await?;Error handling
The SDK uses Rust's Result type for error handling. You can match on the result to handle success or failure.
use unsent::{Client, UnsentError};
let client = Client::new("un_xxx")?;
match emails.send(&email) {
Ok(response) => println!("Email sent! ID: {}", response.id),
Err(UnsentError::Api(api_error)) => {
// Handle API errors (e.g., invalid API key, validation errors)
eprintln!("API Error: {} - {}", api_error.code, api_error.message);
}
Err(e) => eprintln!("Error: {}", e),
}Disable Automatic Error Raising
If you prefer not to have the client return an error for non-2xx responses (though in Rust, Result is idiomatic), you can configure the client:
let client = Client::new("un_xxx")?.with_raise_on_error(false);Custom HTTP client
For advanced use cases, such as adding custom timeouts or proxies, you can provide your own reqwest client.
use reqwest::blocking::Client as HttpClient;
use std::time::Duration;
// Create a custom HTTP client with a timeout
let http_client = HttpClient::builder()
.timeout(Duration::from_secs(30))
.build()?;
// Initialize the SDK with the custom client
let client = Client::new("un_xxx")?.with_http_client(http_client);