melib/notmuch: avoid parsing entire email in Envelope creation

jmap-eventsource
Manos Pitsidianakis 2021-01-05 01:13:13 +02:00
parent 806254436b
commit db69349251
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 98 additions and 53 deletions

View File

@ -22,7 +22,7 @@
use crate::backends::*; use crate::backends::*;
use crate::conf::AccountSettings; use crate::conf::AccountSettings;
use crate::email::{Envelope, EnvelopeHash, Flag}; use crate::email::{Envelope, EnvelopeHash, Flag};
use crate::error::{MeliError, Result, ResultIntoMeliError}; use crate::error::{MeliError, Result};
use crate::shellexpand::ShellExpandTrait; use crate::shellexpand::ShellExpandTrait;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::collections::{ use std::collections::{
@ -130,8 +130,7 @@ impl DbConnection {
} }
} else { } else {
let message_id = message.msg_id_cstr().to_string_lossy().to_string(); let message_id = message.msg_id_cstr().to_string_lossy().to_string();
match message.into_envelope(index.clone(), tag_index.clone()) { let env = message.into_envelope(&index, &tag_index);
Ok(env) => {
for (&mailbox_hash, m) in mailboxes_lck.iter() { for (&mailbox_hash, m) in mailboxes_lck.iter() {
let query_str = format!("{} id:{}", m.query_str.as_str(), &message_id); let query_str = format!("{} id:{}", m.query_str.as_str(), &message_id);
let query: Query = Query::new(self, &query_str)?; let query: Query = Query::new(self, &query_str)?;
@ -153,11 +152,6 @@ impl DbConnection {
} }
} }
} }
Err(err) => {
debug!("could not parse message {:?}", err);
}
}
}
} }
drop(query); drop(query);
index.write().unwrap().retain(|&env_hash, msg_id| { index.write().unwrap().retain(|&env_hash, msg_id| {
@ -481,8 +475,7 @@ impl MailBackend for NotmuchDb {
} else { } else {
continue; continue;
}; };
match message.into_envelope(self.index.clone(), self.tag_index.clone()) { let env = message.into_envelope(&self.index, &self.tag_index);
Ok(env) => {
mailbox_index_lck mailbox_index_lck
.entry(env.hash()) .entry(env.hash())
.or_default() .or_default()
@ -491,11 +484,6 @@ impl MailBackend for NotmuchDb {
unseen_count += 1; unseen_count += 1;
} }
ret.push(env); ret.push(env);
}
Err(err) => {
debug!("could not parse message {:?}", err);
}
}
} else { } else {
done = true; done = true;
break; break;

View File

@ -65,6 +65,16 @@ impl<'m> Message<'m> {
} }
} }
pub fn header(&self, header: &CStr) -> Option<&[u8]> {
let header_val =
unsafe { call!(self.lib, notmuch_message_get_header)(self.message, header.as_ptr()) };
if header_val.is_null() {
None
} else {
Some(unsafe { CStr::from_ptr(header_val).to_bytes() })
}
}
pub fn msg_id(&self) -> &[u8] { pub fn msg_id(&self) -> &[u8] {
let c_str = self.msg_id_cstr(); let c_str = self.msg_id_cstr();
c_str.to_bytes() c_str.to_bytes()
@ -81,19 +91,11 @@ impl<'m> Message<'m> {
pub fn into_envelope( pub fn into_envelope(
self, self,
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>, index: &RwLock<HashMap<EnvelopeHash, CString>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>, tag_index: &RwLock<BTreeMap<u64, String>>,
) -> Result<Envelope> { ) -> Envelope {
let mut contents = Vec::new();
let path = self.get_filename().to_os_string();
let mut f = std::fs::File::open(&path)?;
f.read_to_end(&mut contents)?;
let env_hash = self.env_hash(); let env_hash = self.env_hash();
let mut env = Envelope::from_bytes(&contents, None).chain_err_summary(|| { let mut env = Envelope::new(env_hash);
index.write().unwrap().remove(&env_hash);
format!("could not parse path {:?}", path)
})?;
env.set_hash(env_hash);
index index
.write() .write()
.unwrap() .unwrap()
@ -109,8 +111,63 @@ impl<'m> Message<'m> {
} }
env.labels_mut().push(num); env.labels_mut().push(num);
} }
env.set_flags(flags); unsafe {
Ok(env) use crate::email::parser::address::rfc2822address_list;
env.set_message_id(self.msg_id())
.set_date(
self.header(CStr::from_bytes_with_nul_unchecked(b"Date\0"))
.unwrap_or_default(),
)
.set_from(
rfc2822address_list(
self.header(CStr::from_bytes_with_nul_unchecked(b"From\0"))
.unwrap_or_default(),
)
.map(|(_, v)| v)
.unwrap_or_default(),
)
.set_to(
rfc2822address_list(
self.header(CStr::from_bytes_with_nul_unchecked(b"To\0"))
.unwrap_or_default(),
)
.map(|(_, v)| v)
.unwrap_or_default(),
)
.set_cc(
rfc2822address_list(
self.header(CStr::from_bytes_with_nul_unchecked(b"Cc\0"))
.unwrap_or_default(),
)
.map(|(_, v)| v)
.unwrap_or_default(),
)
.set_bcc(
rfc2822address_list(
self.header(CStr::from_bytes_with_nul_unchecked(b"Bcc\0"))
.unwrap_or_default(),
)
.map(|(_, v)| v)
.unwrap_or_default()
.to_vec(),
)
.set_subject(
self.header(CStr::from_bytes_with_nul_unchecked(b"Subject\0"))
.unwrap_or_default()
.to_vec(),
)
.set_references(
self.header(CStr::from_bytes_with_nul_unchecked(b"References\0"))
.unwrap_or_default(),
)
.set_in_reply_to(
self.header(CStr::from_bytes_with_nul_unchecked(b"In-Reply-To\0"))
.unwrap_or_default(),
)
.set_datetime(self.date())
.set_flags(flags);
}
env
} }
pub fn replies_iter(&self) -> Option<MessageIterator> { pub fn replies_iter(&self) -> Option<MessageIterator> {