dust-mail 0.4.0

A multi protocol email client
use std::path::{Path, PathBuf};

use maildir::Maildir;
use sled::Db;

use crate::error::{err, ErrorKind, Result};

use super::builder::MessageBuilder;

pub struct MailDirectory {
    dir: Maildir,
    id_mappings: Db,
}

impl MailDirectory {
    pub fn open<P: AsRef<str>>(path: P) -> Result<Self> {
        let dir: PathBuf = Path::new(path.as_ref()).into();

        let db = sled::open(dir.join("metadata"))?;

        let mail_dir = Self {
            dir: Maildir::from(dir),
            id_mappings: db,
        };

        Ok(mail_dir)
    }

    pub fn retr<I: AsRef<str>>(&self, id: I) -> Result<MessageBuilder> {
        match self
            .id_mappings
            .get(id.as_ref())?
            .map(|maildir_id| self.dir.find(std::str::from_utf8(&maildir_id).ok()?))
            .flatten()
        {
            Some(mail_entry) => Ok(mail_entry.try_into()?),
            None => {
                err!(
                    ErrorKind::MessageNotFound,
                    "Could not find a message with id {}",
                    id.as_ref()
                );
            }
        }
    }

    pub fn store<B: AsRef<[u8]>, I: AsRef<str>>(&mut self, id: I, data: B) -> Result<()> {
        self.dir.create_dirs()?;

        let maildir_id = self.dir.store_new(data.as_ref())?;

        self.id_mappings
            .insert(id.as_ref(), maildir_id.as_bytes())?;

        Ok(())
    }
}