Add Account, Domain, MultiDomain structs and MailStore trait

This commit is contained in:
Nathan Fisher 2023-05-27 23:38:41 -04:00
parent c7ed63a260
commit 2afbede154
5 changed files with 131 additions and 11 deletions

View file

@ -52,3 +52,19 @@ impl GetFingerprint for Certificate {
})
}
}
#[cfg(test)]
mod tests {
use super::*;
const CERT: &[u8] = include_bytes!("../../test/certificates/gemini.example.org/cert.der");
const FP: &'static str =
include_str!("../../test/certificates/gemini.example.org/fingerprint.txt");
#[test]
fn get_fingerprint() {
let cert = Certificate(CERT.into());
let fp = cert.fingerprint().unwrap();
assert_eq!(fp.fingerprint, FP);
}
}

View file

@ -1,13 +1,16 @@
#![warn(clippy::all, clippy::pedantic)]
mod certificate;
mod fingerprint;
mod host;
mod mailbox;
mod mailuser;
mod message;
pub mod certificate;
pub mod fingerprint;
pub mod host;
pub mod mailbox;
pub mod mailstore;
pub mod mailuser;
pub mod message;
pub mod prelude;
mod receiver;
mod request;
mod response;
mod sender;
mod status;
pub mod receiver;
pub mod request;
pub mod response;
pub mod sender;
pub mod status;
pub use sender::{Error as SenderError, Sender};

100
src/mailstore/mod.rs Normal file
View file

@ -0,0 +1,100 @@
use crate::prelude::{Host, Mailbox, Mailuser, Message, ParseMailboxError};
use std::{
collections::{BTreeMap, HashMap},
str::FromStr,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
pub trait MailStore {
/// Retreives a list of all valid mailusers on this server
fn users(&self) -> Vec<Mailuser>;
/// Checks whether this server services that domain
fn serves_domain(&self, domain: &str) -> bool;
/// Checks whether this server has the given mailuser
fn has_mailuser(&self, mailuser: &str) -> bool;
/// Retreives all of the messages for this user
fn get_user_messages(&self, user: &str) -> Option<BTreeMap<String, Message>>;
/// 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<Message>;
/// 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
fn remove_user(&mut self, user: &str) -> bool;
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Domain {
pub host: Host,
pub users: HashMap<String, Account>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Account {
pub user: Mailbox,
pub messages: BTreeMap<String, Message>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MultiDomain {
pub domains: HashMap<String, Domain>,
}
impl MailStore for Domain {
fn users(&self) -> Vec<Mailuser> {
self.users
.values()
.map(|act| act.user.clone().into())
.collect()
}
fn serves_domain(&self, domain: &str) -> bool {
self.host.to_string().as_str() == domain
}
fn has_mailuser(&self, mailuser: &str) -> bool {
self.users()
.iter()
.find(|x| x.username == mailuser)
.is_some()
}
fn get_user_messages(&self, user: &str) -> Option<BTreeMap<String, Message>> {
self.users.get(user).cloned().map(|u| u.messages)
}
fn get_message(&self, user: &str, title: &str) -> Option<Message> {
self.users
.get(user)
.map(|u| {
u.messages
.values()
.find(|m| m.title.as_ref().map(|x| x.as_str()) == Some(title))
})
.flatten()
.cloned()
}
fn add_user(&mut self, user: &str) -> Result<(), ParseMailboxError> {
if self.users.contains_key(user) {
return Ok(());
}
let mbox = Mailbox::from_str(&format!("{user}@{}", self.host.to_string()))?;
let messages = BTreeMap::new();
let acct = Account {
user: mbox,
messages,
};
self.users.insert(user.to_string(), acct);
Ok(())
}
fn remove_user(&mut self, user: &str) -> bool {
self.users.remove(user).is_some()
}
}

View file

@ -59,6 +59,7 @@ pub struct Message {
pub senders: Vec<Mailbox>,
pub recipients: Vec<Mailbox>,
pub timstamp: Option<String>,
pub title: Option<String>,
pub body: String,
}

0
src/message/parser.rs Normal file
View file