ceal 0.1.0

Opportunistic E-Mail Encryption - Stand-Alone Library and Extensions for Lettre
Documentation
use async_trait::async_trait;
use lettre::{AsyncTransport, address::Envelope};

/// A wrapper for [`lettre::AsyncTransport`] that adds opportunistic encryption before
/// transporting the message.
pub struct CealTransport<T>(T);

impl<T: AsyncTransport> CealTransport<T> {
	/// Create a new transport that applies opportunistic encryption before handing the
	/// (possibly encrypted) message to the provided transport.
	pub const fn new(transport: T) -> Self {
		Self(transport)
	}
}

#[async_trait]
impl<T: AsyncTransport + Send + Sync> AsyncTransport for CealTransport<T> {
	type Ok = T::Ok;
	type Error = T::Error;

	async fn send_raw(
		&self,
		envelope: &Envelope,
		email: &[u8]
	) -> Result<Self::Ok, Self::Error> {
		let email = crate::encrypt(email, envelope.to()).await;
		self.0.send_raw(envelope, &email).await
	}

	async fn shutdown(&self) {
		self.0.shutdown().await
	}
}

/// Extension functions for [`lettre::AsyncTransport`].
pub trait AsyncTransportExt: AsyncTransport + Sized {
	/// Create a new transport that applies opportunistic encryption before handing the
	/// (possibly encrypted) message to this transport.
	fn with_opportunistic_encryption(self) -> CealTransport<Self>;
}

impl<T: AsyncTransport> AsyncTransportExt for T {
	fn with_opportunistic_encryption(self) -> CealTransport<Self> {
		CealTransport::new(self)
	}
}