From d3c156a087f3c767fc0d2376abd7c1d304161d47 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 5 Jan 2024 15:26:57 +0100 Subject: [PATCH] Select what to fecth for search --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/imap/mailbox_view.rs | 9 ++++++++- src/imap/search.rs | 30 ++++++++++++++++++++++++++---- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6a01b9..2c264f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1723,7 +1723,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite 0.2.13", - "socket2 0.5.5", + "socket2 0.4.10", "tokio", "tower-service", "tracing", diff --git a/Cargo.toml b/Cargo.toml index b110a6a..68a46e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ aws-sdk-s3 = "1.9.0" eml-codec = { git = "https://git.deuxfleurs.fr/Deuxfleurs/eml-codec.git", branch = "main" } smtp-message = { git = "http://github.com/Alexis211/kannader", branch = "feature/lmtp" } smtp-server = { git = "http://github.com/Alexis211/kannader", branch = "feature/lmtp" } -imap-codec = { version = "1.0.0", features = ["quirk_crlf_relaxed", "bounded-static", "ext_condstore_qresync"] } +imap-codec = { version = "1.0.0", features = ["bounded-static", "ext_condstore_qresync"] } imap-flow = { git = "https://github.com/duesee/imap-flow.git", rev = "e45ce7bb6ab6bda3c71a0c7b05e9b558a5902e90" } [dev-dependencies] diff --git a/src/imap/mailbox_view.rs b/src/imap/mailbox_view.rs index 5311635..4d0858f 100644 --- a/src/imap/mailbox_view.rs +++ b/src/imap/mailbox_view.rs @@ -344,12 +344,19 @@ impl MailboxView { search_key: &SearchKey<'a>, uid: bool, ) -> Result>> { - let (seq_set, seq_type) = search::Criteria(search_key).to_sequence_set(); + // 1. Compute the subset of sequence identifiers we need to fetch + let query = search::Criteria(search_key); + let (seq_set, seq_type) = query.to_sequence_set(); let mailids = MailIdentifiersList(self.get_mail_ids(&seq_set, seq_type.is_uid())?); let mail_u32 = match uid { true => mailids.uids(), _ => mailids.ids(), }; + + // 2. Compute wether we will need to fetch the mail meta and/or the body + let _need_meta = query.need_meta(); + let _need_body = query.need_body(); + Ok(vec![Body::Data(Data::Search(mail_u32))]) } diff --git a/src/imap/search.rs b/src/imap/search.rs index bf1d30e..ef89288 100644 --- a/src/imap/search.rs +++ b/src/imap/search.rs @@ -69,12 +69,34 @@ impl<'a> Criteria<'a> { } } - fn need_meta(&self) { - unimplemented!(); + /// Not really clever as we can have cases where we filter out + /// the email before needing to inspect its meta. + /// But for now we are seeking the most basic/stupid algorithm. + pub fn need_meta(&self) -> bool { + use SearchKey::*; + match self.0 { + // IMF Headers + Bcc(_) | Cc(_) | From(_) | Header(..) | SentBefore(_) | SentOn(_) | SentSince(_) | Subject(_) | To(_) => true, + // Internal Date is also stored in MailMeta + Before(_) | On(_) | Since(_) => true, + // Message size is also stored in MailMeta + Larger(_) | Smaller(_) => true, + And(and_list) => and_list.as_ref().iter().any(|sk| Criteria(sk).need_meta()), + Not(inner) => Criteria(inner).need_meta(), + Or(left, right) => Criteria(left).need_meta() || Criteria(right).need_meta(), + _ => false, + } } - fn need_body(&self) { - unimplemented!(); + pub fn need_body(&self) -> bool { + use SearchKey::*; + match self.0 { + Text(_) | Body(_) => true, + And(and_list) => and_list.as_ref().iter().any(|sk| Criteria(sk).need_body()), + Not(inner) => Criteria(inner).need_body(), + Or(left, right) => Criteria(left).need_body() || Criteria(right).need_body(), + _ => false, + } } }