parent
674073899d
commit
1db2c16f95
11
meli.conf.5
11
meli.conf.5
|
@ -257,6 +257,17 @@ Valid values are:
|
|||
.\" default value
|
||||
.Pq Em auto
|
||||
.El
|
||||
to set multiple mailboxes, you have to explicitly state the mailboxes you want in the
|
||||
.Ic mailboxes
|
||||
field and set the
|
||||
.Ar path
|
||||
property to each of them.
|
||||
Example:
|
||||
.Bd -literal
|
||||
[accounts.mbox]
|
||||
format = "mbox"
|
||||
mailboxes."Python mailing list" = { path = "~/.mail/python.mbox", subscribe = true, autoload = true }
|
||||
.Ed
|
||||
.Sh mailboxes
|
||||
.Bl -tag -width 36n
|
||||
.It Ic alias Ar String
|
||||
|
|
|
@ -84,6 +84,7 @@ struct MboxMailbox {
|
|||
hash: MailboxHash,
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
fs_path: PathBuf,
|
||||
content: Vec<u8>,
|
||||
children: Vec<MailboxHash>,
|
||||
parent: Option<MailboxHash>,
|
||||
|
@ -92,6 +93,7 @@ struct MboxMailbox {
|
|||
permissions: MailboxPermissions,
|
||||
pub total: Arc<Mutex<usize>>,
|
||||
pub unseen: Arc<Mutex<usize>>,
|
||||
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
||||
}
|
||||
|
||||
impl BackendMailbox for MboxMailbox {
|
||||
|
@ -117,6 +119,7 @@ impl BackendMailbox for MboxMailbox {
|
|||
hash: self.hash,
|
||||
name: self.name.clone(),
|
||||
path: self.path.clone(),
|
||||
fs_path: self.fs_path.clone(),
|
||||
content: self.content.clone(),
|
||||
children: self.children.clone(),
|
||||
usage: self.usage.clone(),
|
||||
|
@ -125,6 +128,7 @@ impl BackendMailbox for MboxMailbox {
|
|||
permissions: self.permissions,
|
||||
unseen: self.unseen.clone(),
|
||||
total: self.total.clone(),
|
||||
index: self.index.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -659,7 +663,7 @@ pub fn mbox_parse(
|
|||
pub struct MboxType {
|
||||
account_name: String,
|
||||
path: PathBuf,
|
||||
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
||||
mailbox_index: Arc<Mutex<HashMap<EnvelopeHash, MailboxHash>>>,
|
||||
mailboxes: Arc<Mutex<HashMap<MailboxHash, MboxMailbox>>>,
|
||||
prefer_mbox_type: Option<MboxReader>,
|
||||
}
|
||||
|
@ -673,14 +677,13 @@ impl MailBackend for MboxType {
|
|||
let mut w = AsyncBuilder::new();
|
||||
let handle = {
|
||||
let tx = w.tx();
|
||||
let index = self.index.clone();
|
||||
let mailbox_path = mailbox.path().to_string();
|
||||
let mailbox_hash = mailbox.hash();
|
||||
let mailbox_index = self.mailbox_index.clone();
|
||||
let mailboxes = self.mailboxes.clone();
|
||||
let mailbox_path = mailboxes.lock().unwrap()[&mailbox_hash].fs_path.clone();
|
||||
let prefer_mbox_type = self.prefer_mbox_type.clone();
|
||||
let closure = move |_work_context| {
|
||||
let tx = tx.clone();
|
||||
let index = index.clone();
|
||||
let file = match std::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
|
@ -702,9 +705,18 @@ impl MailBackend for MboxType {
|
|||
return;
|
||||
};
|
||||
|
||||
let mailboxes_lck = mailboxes.lock().unwrap();
|
||||
let mut mailbox_index_lck = mailbox_index.lock().unwrap();
|
||||
let index = mailboxes_lck[&mailbox_hash].index.clone();
|
||||
drop(mailboxes_lck);
|
||||
let payload = mbox_parse(index, contents.as_slice(), 0, prefer_mbox_type)
|
||||
.map_err(|e| MeliError::from(e))
|
||||
.map(|(_, v)| v);
|
||||
.map(|(_, v)| {
|
||||
for v in v.iter() {
|
||||
mailbox_index_lck.insert(v.hash(), mailbox_hash);
|
||||
}
|
||||
v
|
||||
});
|
||||
{
|
||||
let mut mailbox_lock = mailboxes.lock().unwrap();
|
||||
mailbox_lock
|
||||
|
@ -731,17 +743,16 @@ impl MailBackend for MboxType {
|
|||
.map_err(MeliError::new)?;
|
||||
for f in self.mailboxes.lock().unwrap().values() {
|
||||
watcher
|
||||
.watch(&f.path, RecursiveMode::Recursive)
|
||||
.watch(&f.fs_path, RecursiveMode::Recursive)
|
||||
.map_err(|e| e.to_string())
|
||||
.map_err(MeliError::new)?;
|
||||
debug!("watching {:?}", f.path.as_path());
|
||||
debug!("watching {:?}", f.fs_path.as_path());
|
||||
}
|
||||
let account_hash = {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
hasher.write(self.account_name.as_bytes());
|
||||
hasher.finish()
|
||||
};
|
||||
let index = self.index.clone();
|
||||
let mailboxes = self.mailboxes.clone();
|
||||
let prefer_mbox_type = self.prefer_mbox_type.clone();
|
||||
let handle = std::thread::Builder::new()
|
||||
|
@ -750,7 +761,6 @@ impl MailBackend for MboxType {
|
|||
// Move `watcher` in the closure's scope so that it doesn't get dropped.
|
||||
let _watcher = watcher;
|
||||
let _work_context = work_context;
|
||||
let index = index;
|
||||
let mailboxes = mailboxes;
|
||||
loop {
|
||||
match rx.recv() {
|
||||
|
@ -791,7 +801,7 @@ impl MailBackend for MboxType {
|
|||
.starts_with(mailbox_lock[&mailbox_hash].content.as_slice())
|
||||
{
|
||||
if let Ok((_, envelopes)) = mbox_parse(
|
||||
index.clone(),
|
||||
mailbox_lock[&mailbox_hash].index.clone(),
|
||||
&contents[mailbox_lock[&mailbox_hash].content.len()..],
|
||||
mailbox_lock[&mailbox_hash].content.len(),
|
||||
prefer_mbox_type,
|
||||
|
@ -822,7 +832,7 @@ impl MailBackend for MboxType {
|
|||
.lock()
|
||||
.unwrap()
|
||||
.values()
|
||||
.any(|f| &f.path == &pathbuf)
|
||||
.any(|f| &f.fs_path == &pathbuf)
|
||||
{
|
||||
let mailbox_hash = get_path_hash!(&pathbuf);
|
||||
sender.send(RefreshEvent {
|
||||
|
@ -837,7 +847,12 @@ impl MailBackend for MboxType {
|
|||
}
|
||||
}
|
||||
DebouncedEvent::Rename(src, dest) => {
|
||||
if mailboxes.lock().unwrap().values().any(|f| &f.path == &src) {
|
||||
if mailboxes
|
||||
.lock()
|
||||
.unwrap()
|
||||
.values()
|
||||
.any(|f| &f.fs_path == &src)
|
||||
{
|
||||
let mailbox_hash = get_path_hash!(&src);
|
||||
sender.send(RefreshEvent {
|
||||
account_hash,
|
||||
|
@ -879,12 +894,20 @@ impl MailBackend for MboxType {
|
|||
.map(|(h, f)| (*h, f.clone() as Mailbox))
|
||||
.collect())
|
||||
}
|
||||
fn operation(&self, hash: EnvelopeHash) -> Box<dyn BackendOp> {
|
||||
fn operation(&self, env_hash: EnvelopeHash) -> Box<dyn BackendOp> {
|
||||
let mailbox_hash = self.mailbox_index.lock().unwrap()[&env_hash];
|
||||
let mailboxes_lck = self.mailboxes.lock().unwrap();
|
||||
let (offset, length) = {
|
||||
let index = self.index.lock().unwrap();
|
||||
index[&hash]
|
||||
let index = mailboxes_lck[&mailbox_hash].index.lock().unwrap();
|
||||
index[&env_hash]
|
||||
};
|
||||
Box::new(MboxOp::new(hash, self.path.as_path(), offset, length))
|
||||
let mailbox_path = mailboxes_lck[&mailbox_hash].fs_path.clone();
|
||||
Box::new(MboxOp::new(
|
||||
env_hash,
|
||||
mailbox_path.as_path(),
|
||||
offset,
|
||||
length,
|
||||
))
|
||||
}
|
||||
|
||||
fn save(&self, _bytes: &[u8], _mailbox_hash: MailboxHash, _flags: Option<Flag>) -> Result<()> {
|
||||
|
@ -974,7 +997,8 @@ impl MboxType {
|
|||
hash,
|
||||
MboxMailbox {
|
||||
hash,
|
||||
path: ret.path.clone(),
|
||||
path: name.clone().into(),
|
||||
fs_path: ret.path.clone(),
|
||||
name,
|
||||
content: Vec::new(),
|
||||
children: Vec::new(),
|
||||
|
@ -993,39 +1017,60 @@ impl MboxType {
|
|||
},
|
||||
unseen: Arc::new(Mutex::new(0)),
|
||||
total: Arc::new(Mutex::new(0)),
|
||||
index: Default::default(),
|
||||
},
|
||||
);
|
||||
/*
|
||||
/* Look for other mailboxes */
|
||||
let parent_mailbox = Path::new(path).parent().unwrap();
|
||||
let read_dir = std::fs::read_dir(parent_mailbox);
|
||||
if read_dir.is_ok() {
|
||||
for f in read_dir.unwrap() {
|
||||
if f.is_err() {
|
||||
continue;
|
||||
for (k, f) in s.mailboxes.iter() {
|
||||
if let Some(path_str) = f.extra.get("path") {
|
||||
let hash = get_path_hash!(path_str);
|
||||
let pathbuf: PathBuf = path_str.into();
|
||||
if !pathbuf.exists() || pathbuf.is_dir() {
|
||||
return Err(MeliError::new(format!(
|
||||
"mbox mailbox configuration entry \"{}\" path value {} is not a file.",
|
||||
k, path_str
|
||||
)));
|
||||
}
|
||||
let f = f.unwrap().path();
|
||||
if f.is_file() && f != path {
|
||||
let name: String = f
|
||||
.file_name()
|
||||
.map(|f| f.to_string_lossy().into())
|
||||
.unwrap_or(String::new());
|
||||
let hash = get_path_hash!(f);
|
||||
ret.mailboxes.lock().unwrap().insert(
|
||||
let read_only = if let Ok(metadata) = std::fs::metadata(&pathbuf) {
|
||||
metadata.permissions().readonly()
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
ret.mailboxes.lock().unwrap().insert(
|
||||
hash,
|
||||
MboxMailbox {
|
||||
hash,
|
||||
MboxMailbox {
|
||||
hash,
|
||||
path: f,
|
||||
name,
|
||||
content: Vec::new(),
|
||||
children: Vec::new(),
|
||||
parent: None,
|
||||
name: k.to_string(),
|
||||
fs_path: pathbuf,
|
||||
path: k.into(),
|
||||
content: Vec::new(),
|
||||
children: Vec::new(),
|
||||
parent: None,
|
||||
usage: Arc::new(RwLock::new(f.usage.unwrap_or_default())),
|
||||
is_subscribed: f.subscribe.is_true(),
|
||||
permissions: MailboxPermissions {
|
||||
create_messages: !read_only,
|
||||
remove_messages: !read_only,
|
||||
set_flags: !read_only,
|
||||
create_child: !read_only,
|
||||
rename_messages: !read_only,
|
||||
delete_messages: !read_only,
|
||||
delete_mailbox: !read_only,
|
||||
change_permissions: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
unseen: Arc::new(Mutex::new(0)),
|
||||
total: Arc::new(Mutex::new(0)),
|
||||
index: Default::default(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Err(MeliError::new(format!(
|
||||
"mbox mailbox configuration entry \"{}\" should have a \"path\" value set pointing to an mbox file.",
|
||||
k
|
||||
)));
|
||||
}
|
||||
}
|
||||
*/
|
||||
Ok(Box::new(ret))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue