mailstrom 0.8.0

Email sender
Documentation
use crate::message_status::InternalMessageStatus;
use crate::prepared_email::PreparedEmail;
use crate::storage::{MailstromStorage, MailstromStorageError};
use std::collections::HashMap;
use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum MemoryStorageError {
    NotFound,
}
impl Error for MemoryStorageError { }
impl MailstromStorageError for MemoryStorageError {}

impl fmt::Display for MemoryStorageError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Memory Storage Error: Email not found")
    }
}

pub struct Record {
    email: PreparedEmail,
    status: InternalMessageStatus,
    retrieved: bool,
}

#[derive(Default)]
pub struct MemoryStorage(HashMap<String, Record>);

impl MemoryStorage {
    pub fn new() -> MemoryStorage {
        MemoryStorage(HashMap::new())
    }
}

impl MailstromStorage for MemoryStorage {
    type Error = MemoryStorageError;

    fn store(
        &mut self,
        email: PreparedEmail,
        internal_message_status: InternalMessageStatus,
    ) -> Result<(), MemoryStorageError> {
        self.0.insert(
            internal_message_status.message_id.clone(),
            Record {
                email,
                status: internal_message_status,
                retrieved: false,
            },
        );
        Ok(())
    }

    fn update_status(
        &mut self,
        internal_message_status: InternalMessageStatus,
    ) -> Result<(), MemoryStorageError> {
        let record: &mut Record = match self.0.get_mut(&internal_message_status.message_id) {
            None => return Err(MemoryStorageError::NotFound),
            Some(record) => record,
        };

        record.status = internal_message_status;
        Ok(())
    }

    fn retrieve(
        &self,
        message_id: &str,
    ) -> Result<(PreparedEmail, InternalMessageStatus), MemoryStorageError> {
        let record: &Record = match self.0.get(message_id) {
            None => return Err(MemoryStorageError::NotFound),
            Some(record) => record,
        };
        Ok((record.email.clone(), record.status.clone()))
    }

    fn retrieve_status(
        &self,
        message_id: &str,
    ) -> Result<InternalMessageStatus, MemoryStorageError> {
        let record: &Record = match self.0.get(message_id) {
            None => return Err(MemoryStorageError::NotFound),
            Some(record) => record,
        };
        Ok(record.status.clone())
    }

    fn retrieve_all_incomplete(&self) -> Result<Vec<InternalMessageStatus>, Self::Error> {
        Ok(self.0
            .values()
            .filter_map(|record| {
                if record.status.attempts_remaining == 0 {
                    None
                } else {
                    Some(record.status.clone())
                }
            })
            .collect())
    }

    fn retrieve_all_recent(&mut self) -> Result<Vec<InternalMessageStatus>, Self::Error> {
        Ok(self.0
            .values_mut()
            .filter_map(|record| {
                if record.status.attempts_remaining == 0 {
                    if record.retrieved {
                        None
                    } else {
                        record.retrieved = true;
                        Some(record.status.clone())
                    }
                } else {
                    Some(record.status.clone())
                }
            })
            .collect())
    }
}