aboutsummaryrefslogblamecommitdiff
path: root/src/imap/selectors.rs
blob: 6b5372aea078462b7ecb13c3ef8cfb73055a66c6 (plain) (tree)






































































































                                                                                                                              
use std::iter::zip;

use anyhow::{anyhow, Result};


use crate::cryptoblob::Key;
use crate::imap::mail_view::{MailView, FetchedMail};
use crate::imap::mailbox_view::MailIdentifiers;
use crate::mail::mailbox::MailMeta;
use crate::mail::unique_ident::UniqueIdent;

pub struct BodyIdentifier<'a> {
    pub msg_uuid: &'a UniqueIdent,
    pub msg_key: &'a Key,
}


#[derive(Default)]
pub struct MailSelectionBuilder<'a> {
    //attrs: AttributeProxy,
    mail_count: usize,
    need_body: bool,
    mi: &'a [MailIdentifiers],
    meta: &'a [MailMeta],
    flags: &'a [&'a Vec<String>],
    bodies: &'a [Vec<u8>],
}

impl<'a> MailSelectionBuilder<'a> {
    pub fn new(need_body: bool, mail_count: usize) -> Self {
        Self {
            mail_count,
            need_body,
            ..MailSelectionBuilder::default()
        }
    }

    pub fn with_mail_identifiers(&mut self, mi: &'a [MailIdentifiers]) -> &mut Self {
        self.mi = mi;
        self
    }

    pub fn with_metadata(&mut self, meta: &'a [MailMeta]) -> &mut Self {
        self.meta = meta;
        self
    }

    pub fn with_flags(&mut self, flags: &'a [&'a Vec<String>]) -> &mut Self {
        self.flags = flags;
        self
    }

    pub fn bodies_to_collect(&self) -> Vec<BodyIdentifier> {
        if !self.need_body {
            return vec![];
        }
        zip(self.mi, self.meta)
            .map(|(mi, meta)| BodyIdentifier {
                msg_uuid: &mi.uuid,
                msg_key: &meta.message_key,
            })
            .collect::<Vec<_>>()
    }

    pub fn with_bodies(&mut self, rbodies: &'a [Vec<u8>]) -> &mut Self {
        self.bodies = rbodies;
        self
    }

    pub fn build(&self) -> Result<Vec<MailView<'a>>> {
        let mut bodies = vec![];

        if !self.need_body {
            for m in self.meta.iter() {
                let (_, hdrs) =
                    eml_codec::parse_imf(&m.headers).or(Err(anyhow!("Invalid mail headers")))?;
                bodies.push(FetchedMail::Partial(hdrs));
            }
        } else {
            for rb in self.bodies.iter() {
                let (_, p) = eml_codec::parse_message(&rb).or(Err(anyhow!("Invalid mail body")))?;
                bodies.push(FetchedMail::new_from_message(p));
            }
        }

        if self.mi.len() != self.mail_count && self.meta.len() != self.mail_count
            || self.flags.len() != self.mail_count
            || bodies.len() != self.mail_count
        {
            return Err(anyhow!("Can't build a mail view selection as parts were not correctly registered into the builder."));
        }

        Ok(zip(self.mi, zip(self.meta, zip(self.flags, bodies)))
            .map(|(ids, (meta, (flags, content)))| MailView {
                ids,
                meta,
                flags,
                content,
            })
            .collect())
    }
}