emailit 2.0.3

The official Rust SDK for the Emailit Email API
Documentation
//! # emailit
//!
//! Official Rust SDK for the [Emailit](https://emailit.com) API v2.
//!
//! Provides an async-first client for sending transactional emails, managing domains,
//! API keys, audiences, subscribers, templates, suppressions, contacts, webhooks,
//! email verifications, and events.
//!
//! # Quick start
//!
//! ```no_run
//! use emailit::types::CreateEmailBaseOptions;
//! use emailit::{Emailit, Result};
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//!     let emailit = Emailit::new("secret_xxxxxxxxx");
//!
//!     let from = "Acme <onboarding@emailit.dev>";
//!     let to = ["delivered@emailit.dev"];
//!     let subject = "Hello World";
//!
//!     let email = CreateEmailBaseOptions::new(from, to, subject)
//!         .with_html("<strong>It works!</strong>");
//!
//!     let _email = emailit.emails.send(email).await?;
//!
//!     Ok(())
//! }
//! ```

pub mod client;
pub mod collection;
pub mod error;
pub mod services;
pub mod types;
pub mod webhook_signature;

use std::sync::Arc;

use client::{BaseClient, DEFAULT_BASE_URL};
use services::*;

pub use client::RawResponse;
pub use collection::Collection;
pub use error::{ApiError, Error};
pub use types::*;
pub use webhook_signature::{
    HEADER_SIGNATURE, HEADER_TIMESTAMP, compute_webhook_signature, verify_webhook_signature,
};

/// Convenience type alias for `std::result::Result<T, emailit::Error>`.
pub type Result<T> = std::result::Result<T, Error>;

/// The SDK version, read from `Cargo.toml` at compile time.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// The main Emailit API client.
///
/// Construct one with [`Emailit::new`] (or [`Emailit::with_base_url`] for testing)
/// and then access each API resource through its service field.
///
/// # Example
///
/// ```no_run
/// let client = emailit::Emailit::new("secret_xxxxxxxxx");
/// // client.emails, client.domains, client.api_keys, ...
/// ```
pub struct Emailit {
    /// Email sending and retrieval service (`POST /v2/emails`, `GET /v2/emails/...`).
    pub emails: EmailService,
    /// Sending domain management service (`/v2/domains`).
    pub domains: DomainService,
    /// API key management service (`/v2/api-keys`).
    pub api_keys: ApiKeyService,
    /// Audience management service (`/v2/audiences`).
    pub audiences: AudienceService,
    /// Subscriber management within audiences (`/v2/audiences/:id/subscribers`).
    pub subscribers: SubscriberService,
    /// Email template management service (`/v2/templates`).
    pub templates: TemplateService,
    /// Email suppression management service (`/v2/suppressions`).
    pub suppressions: SuppressionService,
    /// Single email verification service (`/v2/email-verifications`).
    pub email_verifications: EmailVerificationService,
    /// Bulk email verification list service (`/v2/email-verification-lists`).
    pub email_verification_lists: EmailVerificationListService,
    /// Webhook endpoint management service (`/v2/webhooks`).
    pub webhooks: WebhookService,
    /// Contact management service (`/v2/contacts`).
    pub contacts: ContactService,
    /// Event log retrieval service (`/v2/events`).
    pub events: EventService,
    client: Arc<BaseClient>,
}

impl Emailit {
    /// Creates a new client pointing at the production Emailit API.
    ///
    /// # Panics
    ///
    /// Panics if `api_key` is empty.
    pub fn new(api_key: impl Into<String>) -> Self {
        Self::with_base_url(api_key, DEFAULT_BASE_URL)
    }

    /// Creates a new client with a custom base URL, useful for testing against
    /// a mock server.
    ///
    /// Trailing slashes on `base_url` are stripped automatically.
    ///
    /// # Panics
    ///
    /// Panics if `api_key` is empty.
    pub fn with_base_url(api_key: impl Into<String>, base_url: impl Into<String>) -> Self {
        let api_key = api_key.into();
        if api_key.is_empty() {
            panic!("emailit: api_key is required");
        }

        let base_url = base_url.into().trim_end_matches('/').to_string();
        let client = Arc::new(BaseClient::new(api_key, base_url));

        Self {
            emails: EmailService {
                client: Arc::clone(&client),
            },
            domains: DomainService {
                client: Arc::clone(&client),
            },
            api_keys: ApiKeyService {
                client: Arc::clone(&client),
            },
            audiences: AudienceService {
                client: Arc::clone(&client),
            },
            subscribers: SubscriberService {
                client: Arc::clone(&client),
            },
            templates: TemplateService {
                client: Arc::clone(&client),
            },
            suppressions: SuppressionService {
                client: Arc::clone(&client),
            },
            email_verifications: EmailVerificationService {
                client: Arc::clone(&client),
            },
            email_verification_lists: EmailVerificationListService {
                client: Arc::clone(&client),
            },
            webhooks: WebhookService {
                client: Arc::clone(&client),
            },
            contacts: ContactService {
                client: Arc::clone(&client),
            },
            events: EventService {
                client: Arc::clone(&client),
            },
            client,
        }
    }

    /// Returns the API key this client was created with.
    pub fn api_key(&self) -> &str {
        &self.client.api_key
    }

    /// Returns the base URL this client sends requests to.
    pub fn base_url(&self) -> &str {
        &self.client.base_url
    }
}