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