use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use crate::address::Address;
use crate::email::{Email, PreparedEmail};
use crate::error::MailError;
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
#[doc(hidden)]
pub trait MailerThreadSafety: Send + Sync {}
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
impl<T: Send + Sync> MailerThreadSafety for T {}
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[doc(hidden)]
pub trait MailerThreadSafety {}
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
impl<T> MailerThreadSafety for T {}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeliveryResult {
pub message_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub provider_response: Option<serde_json::Value>,
}
impl DeliveryResult {
pub fn new(message_id: impl Into<String>) -> Self {
Self {
message_id: message_id.into(),
provider_response: None,
}
}
pub fn with_response(message_id: impl Into<String>, response: serde_json::Value) -> Self {
Self {
message_id: message_id.into(),
provider_response: Some(response),
}
}
}
#[cfg_attr(
all(target_family = "wasm", target_os = "unknown"),
async_trait(?Send)
)]
#[cfg_attr(not(all(target_family = "wasm", target_os = "unknown")), async_trait)]
pub trait Mailer: MailerThreadSafety {
fn prepare_email(
&self,
email: Email,
default_from: Option<Address>,
) -> Result<PreparedEmail, MailError> {
PreparedEmail::with_default_from(email, default_from)
}
async fn deliver(&self, email: &Email) -> Result<DeliveryResult, MailError> {
let email = self.prepare_email(email.clone(), None)?;
self.deliver_prepared(&email).await
}
async fn deliver_prepared(&self, email: &PreparedEmail) -> Result<DeliveryResult, MailError>;
fn validate_batch(&self, _emails: &[PreparedEmail]) -> Result<(), MailError> {
Ok(()) }
async fn deliver_many(&self, emails: &[Email]) -> Result<Vec<DeliveryResult>, MailError> {
let emails = emails
.iter()
.cloned()
.map(|email| self.prepare_email(email, None))
.collect::<Result<Vec<_>, _>>()?;
self.deliver_many_prepared(&emails).await
}
async fn deliver_many_prepared(
&self,
emails: &[PreparedEmail],
) -> Result<Vec<DeliveryResult>, MailError> {
self.validate_batch(emails)?;
let mut results = Vec::with_capacity(emails.len());
for email in emails {
results.push(self.deliver_prepared(email).await?);
}
Ok(results)
}
fn provider_name(&self) -> &'static str {
"unknown"
}
fn validate_config(&self) -> Result<(), MailError> {
Ok(())
}
}
#[cfg_attr(
all(target_family = "wasm", target_os = "unknown"),
async_trait(?Send)
)]
#[cfg_attr(not(all(target_family = "wasm", target_os = "unknown")), async_trait)]
impl<T: Mailer + ?Sized> Mailer for &T {
fn prepare_email(
&self,
email: Email,
default_from: Option<Address>,
) -> Result<PreparedEmail, MailError> {
(**self).prepare_email(email, default_from)
}
async fn deliver(&self, email: &Email) -> Result<DeliveryResult, MailError> {
(**self).deliver(email).await
}
async fn deliver_prepared(&self, email: &PreparedEmail) -> Result<DeliveryResult, MailError> {
(**self).deliver_prepared(email).await
}
fn validate_batch(&self, emails: &[PreparedEmail]) -> Result<(), MailError> {
(**self).validate_batch(emails)
}
async fn deliver_many(&self, emails: &[Email]) -> Result<Vec<DeliveryResult>, MailError> {
(**self).deliver_many(emails).await
}
async fn deliver_many_prepared(
&self,
emails: &[PreparedEmail],
) -> Result<Vec<DeliveryResult>, MailError> {
(**self).deliver_many_prepared(emails).await
}
fn provider_name(&self) -> &'static str {
(**self).provider_name()
}
fn validate_config(&self) -> Result<(), MailError> {
(**self).validate_config()
}
}
#[cfg_attr(
all(target_family = "wasm", target_os = "unknown"),
async_trait(?Send)
)]
#[cfg_attr(not(all(target_family = "wasm", target_os = "unknown")), async_trait)]
impl<T: Mailer + ?Sized> Mailer for Arc<T> {
fn prepare_email(
&self,
email: Email,
default_from: Option<Address>,
) -> Result<PreparedEmail, MailError> {
(**self).prepare_email(email, default_from)
}
async fn deliver(&self, email: &Email) -> Result<DeliveryResult, MailError> {
(**self).deliver(email).await
}
async fn deliver_prepared(&self, email: &PreparedEmail) -> Result<DeliveryResult, MailError> {
(**self).deliver_prepared(email).await
}
fn validate_batch(&self, emails: &[PreparedEmail]) -> Result<(), MailError> {
(**self).validate_batch(emails)
}
async fn deliver_many(&self, emails: &[Email]) -> Result<Vec<DeliveryResult>, MailError> {
(**self).deliver_many(emails).await
}
async fn deliver_many_prepared(
&self,
emails: &[PreparedEmail],
) -> Result<Vec<DeliveryResult>, MailError> {
(**self).deliver_many_prepared(emails).await
}
fn provider_name(&self) -> &'static str {
(**self).provider_name()
}
fn validate_config(&self) -> Result<(), MailError> {
(**self).validate_config()
}
}