keplars 2.1.0

Official Rust SDK for Keplars Email API
Documentation
use crate::client::Keplars;
use crate::errors::KeplarsResult;
use crate::models::{ScheduleEmailRequest, SendEmailRequest, SendEmailResponse};
use crate::utils::validate_email;

pub struct Emails<'a> {
    client: &'a Keplars,
}

impl<'a> Emails<'a> {
    pub fn new(client: &'a Keplars) -> Self {
        Self { client }
    }

    pub async fn send_instant(&self, request: SendEmailRequest) -> KeplarsResult<SendEmailResponse> {
        validate_request(&request)?;
        self.client.post("/api/v1/send-email/instant", &request).await
    }

    pub async fn send_high(&self, request: SendEmailRequest) -> KeplarsResult<SendEmailResponse> {
        validate_request(&request)?;
        self.client.post("/api/v1/send-email/high", &request).await
    }

    pub async fn send_async(&self, request: SendEmailRequest) -> KeplarsResult<SendEmailResponse> {
        validate_request(&request)?;
        self.client.post("/api/v1/send-email/async", &request).await
    }

    pub async fn send_bulk(&self, request: SendEmailRequest) -> KeplarsResult<SendEmailResponse> {
        validate_request(&request)?;
        self.client.post("/api/v1/send-email/bulk", &request).await
    }

    pub async fn send(&self, request: SendEmailRequest) -> KeplarsResult<SendEmailResponse> {
        self.send_async(request).await
    }

    pub async fn schedule(&self, request: ScheduleEmailRequest) -> KeplarsResult<SendEmailResponse> {
        validate_request(&request.email)?;
        validate_schedule_date(&request.scheduled_for)?;
        self.client.post("/api/v1/send-email/schedule", &request).await
    }
}

fn validate_request(request: &SendEmailRequest) -> KeplarsResult<()> {
    use crate::errors::KeplarsError;
    use crate::models::ToRecipient;

    match &request.to {
        ToRecipient::Email(e) => {
            if !validate_email(e) {
                return Err(KeplarsError::Validation {
                    message: format!("Invalid email address in to: {}", e),
                    status_code: 0,
                });
            }
        }
        ToRecipient::Emails(emails) => {
            for e in emails {
                if !validate_email(e) {
                    return Err(KeplarsError::Validation {
                        message: format!("Invalid email address in to: {}", e),
                        status_code: 0,
                    });
                }
            }
        }
    }

    if request.from.is_empty() {
        return Err(KeplarsError::Validation {
            message: "from is required".to_string(),
            status_code: 0,
        });
    }
    if request.subject.is_empty() {
        return Err(KeplarsError::Validation {
            message: "subject is required".to_string(),
            status_code: 0,
        });
    }
    if request.subject.len() > 998 {
        return Err(KeplarsError::Validation {
            message: "Subject cannot exceed 998 characters".to_string(),
            status_code: 0,
        });
    }

    let has_content = request.body.is_some();
    let has_template = request.template_id.is_some();

    if !has_content && !has_template {
        return Err(KeplarsError::Validation {
            message: "Either body or template_id is required".to_string(),
            status_code: 0,
        });
    }
    if has_content && has_template {
        return Err(KeplarsError::Validation {
            message: "Cannot use both body and template_id".to_string(),
            status_code: 0,
        });
    }

    Ok(())
}

fn validate_schedule_date(date_string: &str) -> KeplarsResult<()> {
    use crate::errors::KeplarsError;

    if date_string.is_empty() {
        return Err(KeplarsError::Validation {
            message: "scheduled_for is required".to_string(),
            status_code: 0,
        });
    }
    Ok(())
}