1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
//! Module dedicated to Maildir email folders.
//!
//! This module contains folder-related mapping functions from the
//! [maildirpp] crate types.
use log::{debug, trace};
use maildirpp::{Maildir, Submaildirs};
use rayon::prelude::*;
use std::ffi::OsStr;
use crate::{
account::config::AccountConfig,
folder::{Folder, Folders},
maildir,
};
impl Folder {
/// Parse a folder from a maildir instance.
///
/// Returns [`None`] in case the folder name is too short (does
/// not start by a dot) or is equal to `notmuch` (which should not
/// be treated as a maildir folder).
pub fn from_maildir(config: &AccountConfig, mdir: Maildir) -> Option<Self> {
let folder = mdir
.path()
.file_name()
.and_then(OsStr::to_str)
.filter(|folder| folder.len() >= 2)
.map(|folder| &folder[1..]);
match folder {
None => {
debug!("cannot parse folder from maildir: invalid subdirectory name");
None
}
Some("notmuch") => {
debug!("skipping folder .notmuch");
None
}
Some(name) => {
let name = maildir::decode_folder(name);
let kind = config
.find_folder_kind_from_alias(&name)
.or_else(|| name.parse().ok());
let desc = mdir.path().to_owned().to_string_lossy().to_string();
let folder = Folder { kind, name, desc };
trace!("parsed maildir folder: {folder:#?}");
Some(folder)
}
}
}
}
impl Folders {
/// Parse folders from submaildirs.
///
/// Folders are parsed in parallel, using [`rayon`]. Only parses
/// direct submaildirs (no recursion).
pub fn from_submaildirs(config: &AccountConfig, submdirs: Submaildirs) -> Self {
Folders::from_iter(
submdirs
.collect::<Vec<_>>()
.into_par_iter()
.filter_map(|mdir| match mdir {
Ok(mdir) => Folder::from_maildir(config, mdir),
Err(err) => {
debug!("cannot parse submaildir: {err}");
debug!("{err:?}");
None
}
})
.collect::<Vec<_>>(),
)
}
}