diff --git a/src/mailstore/filesystem.rs b/src/mailstore/filesystem.rs new file mode 100644 index 0000000..238c623 --- /dev/null +++ b/src/mailstore/filesystem.rs @@ -0,0 +1,100 @@ +use super::*; +use std::{fs, io, 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>; +} + +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] +pub struct Filesystem { + pub path: PathBuf, +} + +impl MailStore for Filesystem { + fn users(&self) -> Vec { + todo!() + } + + fn serves_domain(&self, domain: &str) -> bool { + let mut path = self.path.clone(); + path.push(domain); + path.exists() + } + + fn has_mailuser(&self, mailuser: &str) -> bool { + if let Some((user, host)) = mailuser.rsplit_once('@') { + let mut path = self.path.clone(); + if host.contains('.') && !host.contains(|c: char| c.is_whitespace()) { + path.push(host); + path.push(user); + return path.exists(); + } + } + false + } + + fn get_user_messages(&self, user: &str) -> Option> { + todo!() + } + + fn get_message(&self, user: &str, title: &str) -> Option { + todo!() + } + + fn move_message(&mut self, user: &str, title: &str, folder: &str) { + todo!() + } + + fn add_user(&mut self, user: &str) -> Result<(), ParseMailboxError> { + todo!() + } + + fn remove_user(&mut self, user: &str) -> bool { + todo!() + } +} + +impl MultiDomain for Filesystem { + type Error = io::Error; + + fn domains(&self) -> Result, Self::Error> { + Ok(self + .path + .read_dir()? + .filter(|x| { + if let Ok(x) = x { + if let Ok(t) = x.file_type() { + return t.is_dir(); + } + } + false + }) + .map(|x| x.unwrap().file_name().to_string_lossy().to_string()) + .collect::>()) + } + + fn add_domain(&mut self, domain: &str) -> Result<(), Self::Error> { + let mut path = self.path.clone(); + path.push(domain); + if !path.exists() { + fs::DirBuilder::new() + .recursive(true) + .mode(700) + .create(path)?; + } + Ok(()) + } + + fn remove_domain(&mut self, domain: &str) -> Result<(), Self::Error> { + let mut path = self.path.clone(); + path.push(domain); + if path.exists() { + fs::remove_dir_all(path)?; + } + Ok(()) + } +} diff --git a/src/mailstore/mod.rs b/src/mailstore/mod.rs index b7e32bd..8ce18b7 100644 --- a/src/mailstore/mod.rs +++ b/src/mailstore/mod.rs @@ -7,6 +7,8 @@ use std::{ #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +pub mod filesystem; + pub trait MailStore { /// Retreives a list of all valid mailusers on this server fn users(&self) -> Vec; @@ -19,6 +21,8 @@ pub trait MailStore { /// Checks whether this server has a message with the given title for this user and if so /// returns the message fn get_message(&self, user: &str, title: &str) -> Option; + /// Move a message to a new folder + fn move_message(&mut self, user: &str, title: &str, folder: &str); /// 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 @@ -80,6 +84,10 @@ impl MailStore for Domain { .cloned() } + fn move_message(&mut self, user: &str, title: &str, folder: &str) { + todo!() + } + fn add_user(&mut self, user: &str) -> Result<(), ParseMailboxError> { if self.users.contains_key(user) { return Ok(());