From 179b8ad1006d21a478772a96b5d294e9202aa9a0 Mon Sep 17 00:00:00 2001 From: Nathan Fisher Date: Mon, 29 May 2023 00:56:15 -0400 Subject: [PATCH] Tweak `MailStore` and `MultiDomain` traits to add Error types --- src/mailstore/filesystem.rs | 43 ++++++++++++++++++++++++++----------- src/mailstore/mod.rs | 19 ++++++++++------ src/sender/mod.rs | 9 ++++++-- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/mailstore/filesystem.rs b/src/mailstore/filesystem.rs index fd4b738..0212383 100644 --- a/src/mailstore/filesystem.rs +++ b/src/mailstore/filesystem.rs @@ -1,11 +1,11 @@ use super::*; -use std::{fs, io, os::unix::fs::DirBuilderExt, path::PathBuf}; +use std::{fs::{self, File}, io::{self, Write}, os::unix::fs::DirBuilderExt, path::PathBuf}; pub trait MultiDomain: MailStore { type Error; - fn domains(&self) -> Result, Self::Error>; - fn add_domain(&mut self, domain: &str) -> Result<(), Self::Error>; - fn remove_domain(&mut self, domain: &str) -> Result<(), Self::Error>; + fn domains(&self) -> Result, ::Error>; + fn add_domain(&mut self, domain: &str) -> Result<(), ::Error>; + fn remove_domain(&mut self, domain: &str) -> Result<(), ::Error>; } #[derive(Clone, Debug)] @@ -15,6 +15,8 @@ pub struct Filesystem { } impl MailStore for Filesystem { + type Error = io::Error; + fn users(&self) -> Vec { todo!() } @@ -48,7 +50,10 @@ impl MailStore for Filesystem { let Ok(dir) = fs::read_dir(path) else { return None; }; - let mut folder = Folder { name: folder.to_string(), messages: HashMap::new() }; + let mut folder = Folder { + name: folder.to_string(), + messages: HashMap::new(), + }; dir.filter(|x| x.is_ok()).map(|x| x.unwrap()).for_each(|e| { if let Ok(contents) = fs::read_to_string(e.path()) { if let Ok(message) = contents.parse::() { @@ -60,14 +65,28 @@ impl MailStore for Filesystem { } fn get_message(&self, user: &str, folder: &str, title: &str) -> Option { - todo!() + self.get_folder(user, folder).and_then(|f| { + f.messages + .values() + .find(|m| m.title.as_ref().map(|x| x.as_str()) == Some(title)) + .cloned() + }) } - fn add_message(&mut self, user: &str, folder: &str, message: Message) { - todo!() + fn add_message(&mut self, user: &str, folder: &str, message: Message) -> Result<(), Self::Error> { + let Some((user, host)) = user.rsplit_once('@') else { + return Err(io::Error::new(io::ErrorKind::Other, "Invalid username")); + }; + let mut path = self.path.clone(); + path.push(host); + path.push(user); + path.push(folder); + path.push(&message.id); + let mut fd = File::create(path)?; + write!(fd, "{message}") } - fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> bool { + fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> Result<(), Self::Error> { todo!() } @@ -87,7 +106,7 @@ impl MailStore for Filesystem { impl MultiDomain for Filesystem { type Error = io::Error; - fn domains(&self) -> Result, Self::Error> { + fn domains(&self) -> Result, io::Error> { Ok(self .path .read_dir()? @@ -103,7 +122,7 @@ impl MultiDomain for Filesystem { .collect::>()) } - fn add_domain(&mut self, domain: &str) -> Result<(), Self::Error> { + fn add_domain(&mut self, domain: &str) -> Result<(), io::Error> { let mut path = self.path.clone(); path.push(domain); if !path.exists() { @@ -115,7 +134,7 @@ impl MultiDomain for Filesystem { Ok(()) } - fn remove_domain(&mut self, domain: &str) -> Result<(), Self::Error> { + fn remove_domain(&mut self, domain: &str) -> Result<(), io::Error> { let mut path = self.path.clone(); path.push(domain); if path.exists() { diff --git a/src/mailstore/mod.rs b/src/mailstore/mod.rs index bd41096..658e0f0 100644 --- a/src/mailstore/mod.rs +++ b/src/mailstore/mod.rs @@ -1,5 +1,6 @@ +#![allow(unused_variables)] use crate::prelude::{Host, Mailbox, Mailuser, Message, ParseMailboxError}; -use std::{collections::HashMap, str::FromStr}; +use std::{collections::HashMap, str::FromStr, convert::Infallible}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -7,6 +8,8 @@ use serde::{Deserialize, Serialize}; pub mod filesystem; pub trait MailStore { + type Error; + /// Retreives a list of all valid mailusers on this server fn users(&self) -> Vec; /// Checks whether this server services that domain @@ -19,11 +22,11 @@ pub trait MailStore { /// returns the message fn get_message(&self, user: &str, folder: &str, title: &str) -> Option; /// Move a message to a new folder - fn move_message(&mut self, user: &str, title: &str, folder: &str); + fn move_message(&mut self, user: &str, id: &str, folder: &str); /// Deletes a message it it exists - fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> bool; + fn delete_message(&mut self, user: &str, folder: &str, id: &str) -> Result<(), Self::Error>; /// Adds a message - fn add_message(&mut self, user: &str, folder: &str, message: Message); + fn add_message(&mut self, user: &str, folder: &str, message: Message) -> Result<(), Self::Error>; /// Adds a new mailuser to the given domain fn add_user(&mut self, user: &str) -> Result<(), ParseMailboxError>; /// Removes the given user if the account exists @@ -58,6 +61,8 @@ pub struct MultiDomain { } impl MailStore for Domain { + type Error = Infallible; + fn users(&self) -> Vec { self.users .values() @@ -96,7 +101,7 @@ impl MailStore for Domain { .cloned() } - fn move_message(&mut self, user: &str, title: &str, folder: &str) { + fn move_message(&mut self, user: &str, id: &str, folder: &str) { todo!() } @@ -118,11 +123,11 @@ impl MailStore for Domain { self.users.remove(user).is_some() } - fn add_message(&mut self, user: &str, folder: &str, message: Message) { + fn add_message(&mut self, user: &str, folder: &str, message: Message) -> Result<(), Self::Error> { todo!() } - fn delete_message(&mut self, user: &str, folder: &str, key: &str) -> bool { + fn delete_message(&mut self, user: &str, folder: &str, id: &str) -> Result<(), Self::Error> { todo!() } } diff --git a/src/sender/mod.rs b/src/sender/mod.rs index 5ca9caa..fa3a762 100644 --- a/src/sender/mod.rs +++ b/src/sender/mod.rs @@ -105,7 +105,12 @@ where S: CertificateStore + 'static + Clone, C: ClientCertificateStore + Clone, { - pub fn new(sender: &str, recipients: &[&str], store: S, client_store: C) -> Result { + 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()?; @@ -115,7 +120,7 @@ where sender: sender.parse()?, recipients: rec, store, - client_store + client_store, }) }