From e3b9db45722293803c057eedb476fe3a8e11763e Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Sun, 28 May 2023 12:23:05 -0400 Subject: [PATCH] Fix some issues with Sender, add Multisender --- src/request/mod.rs | 10 ++++----- src/sender/error.rs | 21 +++++++++++++----- src/sender/mod.rs | 54 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/src/request/mod.rs b/src/request/mod.rs index 60ee5fe..febf1ec 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -12,14 +12,14 @@ pub use error::Error; /// The full request as sent by the `Sender` and received by the `Receiver` pub struct Request { /// The sender of the message - pub sender: Mailuser, + pub recipient: Mailuser, /// The message body pub message: String, } impl fmt::Display for Request { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "misfin://{} {}\r\n", self.sender, self.message) + write!(f, "misfin://{} {}\r\n", self.recipient, self.message) } } @@ -37,8 +37,8 @@ impl FromStr for Request { let Some(user) = user.strip_prefix("misfin://") else { return Err(Error::Malformed); }; - let sender = user.parse()?; - Ok(Request { sender, message }) + let recipient = user.parse()?; + Ok(Request { recipient, message }) } else { Err(Error::MissingSeparator) } @@ -98,7 +98,7 @@ mod tests { fn req() -> Request { Request { - sender: Mailuser { + recipient: Mailuser { username: "john".to_string(), host: Host { subdomain: Some("misfin".into()), diff --git a/src/sender/error.rs b/src/sender/error.rs index d618383..bcc55a9 100644 --- a/src/sender/error.rs +++ b/src/sender/error.rs @@ -1,5 +1,5 @@ use { - crate::prelude::{ParseRequestError, ParseResponseError}, + crate::prelude::{ParseMailboxError, ParseRequestError, ParseResponseError}, rustls::InvalidMessage, std::{fmt, io}, }; @@ -9,10 +9,11 @@ use { pub enum Error { CertificateError(InvalidMessage), DnsError, - TlsError(rustls::Error), + IoError(io::Error), + MailboxError(ParseMailboxError), RequestError(ParseRequestError), ResponseError(ParseResponseError), - IoError(io::Error), + TlsError(rustls::Error), } impl fmt::Display for Error { @@ -20,10 +21,11 @@ impl fmt::Display for Error { match self { Self::CertificateError(e) => write!(f, "{e:?}"), Self::DnsError => write!(f, "Dns Error"), - Self::TlsError(e) => write!(f, "{e}"), + Self::IoError(e) => write!(f, "{e}"), + Self::MailboxError(e) => write!(f, "{e}"), Self::RequestError(e) => write!(f, "{e}"), Self::ResponseError(e) => write!(f, "{e}"), - Self::IoError(e) => write!(f, "{e}"), + Self::TlsError(e) => write!(f, "{e}"), } } } @@ -31,10 +33,11 @@ impl fmt::Display for Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { + Self::IoError(e) => Some(e), + Self::MailboxError(e) => Some(e), Self::RequestError(e) => Some(e), Self::ResponseError(e) => Some(e), Self::TlsError(e) => Some(e), - Self::IoError(e) => Some(e), _ => None, } } @@ -52,6 +55,12 @@ impl From for Error { } } +impl From for Error { + fn from(value: ParseMailboxError) -> Self { + Self::MailboxError(value) + } +} + impl From for Error { fn from(value: ParseRequestError) -> Self { Self::RequestError(value) diff --git a/src/sender/mod.rs b/src/sender/mod.rs index bb49891..5ca9caa 100644 --- a/src/sender/mod.rs +++ b/src/sender/mod.rs @@ -21,6 +21,8 @@ where S: CertificateStore, C: ClientCertificateStore, { + /// The address of the sender + pub sender: Mailuser, /// The full message text to be sent pub request: Request, /// A [CertificateStore] for servers known to us @@ -34,9 +36,11 @@ where S: CertificateStore + 'static, C: ClientCertificateStore, { - pub fn new(request_str: &str, store: S, client_store: C) -> Result { + pub fn new(sender: &str, request_str: &str, store: S, client_store: C) -> Result { + let sender = sender.parse()?; let request: Request = request_str.parse()?; Ok(Self { + sender, request, store, client_store, @@ -44,17 +48,17 @@ where } fn host_string(&self) -> String { - self.request.sender.host.to_string() + self.request.recipient.host.to_string() } - pub fn send(self, recipient: &Mailuser) -> Result { - let dnsname = recipient - .to_string() + pub fn send(self) -> Result { + let dnsname = self + .host_string() .as_str() .try_into() .map_err(|_| Error::DnsError)?; - let mut it = recipient.host.to_socket_addrs()?; - let client_cert = self.client_store.get_certificate(&self.request.sender); + let mut it = self.request.recipient.host.to_socket_addrs()?; + let client_cert = self.client_store.get_certificate(&self.sender); let verifier = Arc::new(Verifier::new(self.store)); let Some(socket_addrs) = it.next() else { return Err(io::Error::new(io::ErrorKind::Other, "no data retrieved").into()); @@ -83,3 +87,39 @@ where Ok(res) } } + +#[derive(Debug)] +pub struct MultiSender +where + S: CertificateStore, + C: ClientCertificateStore, +{ + pub sender: Mailuser, + pub recipients: Vec, + pub store: S, + pub client_store: C, +} + +impl MultiSender +where + S: CertificateStore + 'static + Clone, + C: ClientCertificateStore + Clone, +{ + pub fn new(sender: &str, recipients: &[&str], store: S, client_store: C) -> Result { + let mut rec = vec![]; + for r in recipients { + let r = r.parse()?; + rec.push(r); + } + Ok(Self { + sender: sender.parse()?, + recipients: rec, + store, + client_store + }) + } + + pub fn send(&self, f: &dyn Fn(Result)) -> Result<(), Error> { + todo!() + } +}