Skip to main content

emailit/
lib.rs

1//! # emailit
2//!
3//! Official Rust SDK for the [Emailit](https://emailit.com) API v2.
4//!
5//! Provides an async-first client for sending transactional emails, managing domains,
6//! API keys, audiences, subscribers, templates, suppressions, contacts, webhooks,
7//! email verifications, and events.
8//!
9//! # Quick start
10//!
11//! ```no_run
12//! use emailit::types::CreateEmailBaseOptions;
13//! use emailit::{Emailit, Result};
14//!
15//! #[tokio::main]
16//! async fn main() -> Result<()> {
17//!     let emailit = Emailit::new("secret_xxxxxxxxx");
18//!
19//!     let from = "Acme <onboarding@emailit.dev>";
20//!     let to = ["delivered@emailit.dev"];
21//!     let subject = "Hello World";
22//!
23//!     let email = CreateEmailBaseOptions::new(from, to, subject)
24//!         .with_html("<strong>It works!</strong>");
25//!
26//!     let _email = emailit.emails.send(email).await?;
27//!
28//!     Ok(())
29//! }
30//! ```
31
32pub mod client;
33pub mod collection;
34pub mod error;
35pub mod services;
36pub mod types;
37pub mod webhook_signature;
38
39use std::sync::Arc;
40
41use client::{BaseClient, DEFAULT_BASE_URL};
42use services::*;
43
44pub use client::RawResponse;
45pub use collection::Collection;
46pub use error::{ApiError, Error};
47pub use types::*;
48pub use webhook_signature::{
49    HEADER_SIGNATURE, HEADER_TIMESTAMP, compute_webhook_signature, verify_webhook_signature,
50};
51
52/// Convenience type alias for `std::result::Result<T, emailit::Error>`.
53pub type Result<T> = std::result::Result<T, Error>;
54
55/// The SDK version, read from `Cargo.toml` at compile time.
56pub const VERSION: &str = env!("CARGO_PKG_VERSION");
57
58/// The main Emailit API client.
59///
60/// Construct one with [`Emailit::new`] (or [`Emailit::with_base_url`] for testing)
61/// and then access each API resource through its service field.
62///
63/// # Example
64///
65/// ```no_run
66/// let client = emailit::Emailit::new("secret_xxxxxxxxx");
67/// // client.emails, client.domains, client.api_keys, ...
68/// ```
69pub struct Emailit {
70    /// Email sending and retrieval service (`POST /v2/emails`, `GET /v2/emails/...`).
71    pub emails: EmailService,
72    /// Sending domain management service (`/v2/domains`).
73    pub domains: DomainService,
74    /// API key management service (`/v2/api-keys`).
75    pub api_keys: ApiKeyService,
76    /// Audience management service (`/v2/audiences`).
77    pub audiences: AudienceService,
78    /// Subscriber management within audiences (`/v2/audiences/:id/subscribers`).
79    pub subscribers: SubscriberService,
80    /// Email template management service (`/v2/templates`).
81    pub templates: TemplateService,
82    /// Email suppression management service (`/v2/suppressions`).
83    pub suppressions: SuppressionService,
84    /// Single email verification service (`/v2/email-verifications`).
85    pub email_verifications: EmailVerificationService,
86    /// Bulk email verification list service (`/v2/email-verification-lists`).
87    pub email_verification_lists: EmailVerificationListService,
88    /// Webhook endpoint management service (`/v2/webhooks`).
89    pub webhooks: WebhookService,
90    /// Contact management service (`/v2/contacts`).
91    pub contacts: ContactService,
92    /// Event log retrieval service (`/v2/events`).
93    pub events: EventService,
94    client: Arc<BaseClient>,
95}
96
97impl Emailit {
98    /// Creates a new client pointing at the production Emailit API.
99    ///
100    /// # Panics
101    ///
102    /// Panics if `api_key` is empty.
103    pub fn new(api_key: impl Into<String>) -> Self {
104        Self::with_base_url(api_key, DEFAULT_BASE_URL)
105    }
106
107    /// Creates a new client with a custom base URL, useful for testing against
108    /// a mock server.
109    ///
110    /// Trailing slashes on `base_url` are stripped automatically.
111    ///
112    /// # Panics
113    ///
114    /// Panics if `api_key` is empty.
115    pub fn with_base_url(api_key: impl Into<String>, base_url: impl Into<String>) -> Self {
116        let api_key = api_key.into();
117        if api_key.is_empty() {
118            panic!("emailit: api_key is required");
119        }
120
121        let base_url = base_url.into().trim_end_matches('/').to_string();
122        let client = Arc::new(BaseClient::new(api_key, base_url));
123
124        Self {
125            emails: EmailService {
126                client: Arc::clone(&client),
127            },
128            domains: DomainService {
129                client: Arc::clone(&client),
130            },
131            api_keys: ApiKeyService {
132                client: Arc::clone(&client),
133            },
134            audiences: AudienceService {
135                client: Arc::clone(&client),
136            },
137            subscribers: SubscriberService {
138                client: Arc::clone(&client),
139            },
140            templates: TemplateService {
141                client: Arc::clone(&client),
142            },
143            suppressions: SuppressionService {
144                client: Arc::clone(&client),
145            },
146            email_verifications: EmailVerificationService {
147                client: Arc::clone(&client),
148            },
149            email_verification_lists: EmailVerificationListService {
150                client: Arc::clone(&client),
151            },
152            webhooks: WebhookService {
153                client: Arc::clone(&client),
154            },
155            contacts: ContactService {
156                client: Arc::clone(&client),
157            },
158            events: EventService {
159                client: Arc::clone(&client),
160            },
161            client,
162        }
163    }
164
165    /// Returns the API key this client was created with.
166    pub fn api_key(&self) -> &str {
167        &self.client.api_key
168    }
169
170    /// Returns the base URL this client sends requests to.
171    pub fn base_url(&self) -> &str {
172        &self.client.base_url
173    }
174}