Rust
Official Unsent Rust SDK for sending emails and managing contacts.
This guide shows how to install and use the official unsent Rust SDK.
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, types::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: "user@example.com".to_string(),
from: "no-reply@yourdomain.com".to_string(),
subject: "Welcome".to_string(),
html: Some("<strong>Hello!</strong>".to_string()),
text: None,
reply_to: None,
cc: None,
bcc: None,
attachments: None,
scheduled_at: None,
};
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
Attachmentstructs. Content must be Base64 encoded. - Scheduling: Use the
scheduled_atfield with an RFC 3339 formatted string.
use unsent::types::{EmailCreate, Attachment};
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: "user@example.com".to_string(),
from: "no-reply@yourdomain.com".to_string(),
subject: "Report".to_string(),
text: Some("See attached.".to_string()),
attachments: Some(vec![
Attachment {
filename: "report.txt".to_string(),
content: "SGVsbG8gd29ybGQ=".to_string(), // Content must be Base64 encoded
}
]),
scheduled_at: Some(scheduled_time),
html: None,
reply_to: None,
cc: None,
bcc: None,
};
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::types::EmailBatchItem;
let batch = vec![
EmailBatchItem {
to: "a@example.com".to_string(),
from: "no-reply@yourdomain.com".to_string(),
subject: "A".to_string(),
html: Some("<p>A</p>".to_string()),
text: None,
attachments: None,
scheduled_at: None,
},
EmailBatchItem {
to: "b@example.com".to_string(),
from: "no-reply@yourdomain.com".to_string(),
subject: "B".to_string(),
html: Some("<p>B</p>".to_string()),
text: None,
attachments: None,
scheduled_at: None,
},
];
let response = emails.batch(&batch)?;
println!("Sent {} emails", response.emails.len());Idempotent Retries
To safely retry requests, you can use RequestOptions with the _with_options methods.
use unsent::types::RequestOptions;
let options = RequestOptions::new().with_idempotency_key("unique-key-123");
// 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.status);Update schedule time
Change the scheduled delivery time for a pending email:
use unsent::types::EmailUpdate;
use chrono::{Utc, Duration};
let new_time = (Utc::now() + Duration::hours(1)).to_rfc3339();
let update = EmailUpdate {
scheduled_at: Some(new_time),
subject: None,
html: None,
text: None,
attachments: None,
};
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");Contacts
Manage your contacts and organize them into contact books. All contact operations require a contact book ID.
Create a contact
Add a new contact to a specific contact book. You can include custom metadata using a HashMap.
use unsent::{types::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),
};
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::types::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),
};
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::types::ContactUpsert;
let upsert = ContactUpsert {
email: "user@example.com".to_string(),
first_name: Some("Jane".to_string()),
last_name: None,
metadata: None,
};
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.
Create a campaign
Create a new campaign by defining its content and the target contact book.
use unsent::{types::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(),
};
let response = campaigns.create(&campaign)?;
println!("Campaign created! ID: {}", response.id);Schedule a campaign
Schedule the campaign to be sent at a specific time.
use unsent::types::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::types::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(123)?;
println!("Verification status: {}", response.status);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);