aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-01-19 17:39:55 +0100
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-01-19 17:39:55 +0100
commitc2a518a997fa12f6e82b2a9eb1ba8cd6059fdf41 (patch)
treeb183720d2a048b1c6641260431258f6332739db3
parent0cc38571f494a40170dc9913eddad5012337574a (diff)
downloadaerogramme-c2a518a997fa12f6e82b2a9eb1ba8cd6059fdf41.tar.gz
aerogramme-c2a518a997fa12f6e82b2a9eb1ba8cd6059fdf41.zip
filter expunge
-rw-r--r--Cargo.lock4
-rw-r--r--src/imap/command/selected.rs11
-rw-r--r--src/imap/mailbox_view.rs22
3 files changed, 25 insertions, 12 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4b49312..afa6980 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1807,7 +1807,7 @@ dependencies = [
[[package]]
name = "imap-codec"
version = "2.0.0"
-source = "git+https://github.com/superboum/imap-codec?branch=custom/aerogramme#b0a80c4826f3d8bf2d2e69f68443c261e62bb40f"
+source = "git+https://github.com/superboum/imap-codec?branch=custom/aerogramme#0f27fe2f10d16c96e0be18914fdbeda9df545beb"
dependencies = [
"abnf-core",
"base64 0.21.5",
@@ -1834,7 +1834,7 @@ dependencies = [
[[package]]
name = "imap-types"
version = "2.0.0"
-source = "git+https://github.com/superboum/imap-codec?branch=custom/aerogramme#b0a80c4826f3d8bf2d2e69f68443c261e62bb40f"
+source = "git+https://github.com/superboum/imap-codec?branch=custom/aerogramme#0f27fe2f10d16c96e0be18914fdbeda9df545beb"
dependencies = [
"base64 0.21.5",
"bounded-static",
diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs
index 98b3b00..154e28c 100644
--- a/src/imap/command/selected.rs
+++ b/src/imap/command/selected.rs
@@ -59,7 +59,10 @@ pub async fn dispatch<'a>(
criteria,
uid,
} => ctx.search(charset, criteria, uid).await,
- CommandBody::Expunge => ctx.expunge().await,
+ CommandBody::Expunge {
+ // UIDPLUS (rfc4315)
+ uid_sequence_set,
+ } => ctx.expunge(uid_sequence_set).await,
CommandBody::Store {
sequence_set,
kind,
@@ -114,7 +117,7 @@ impl<'a> SelectedContext<'a> {
// We expunge messages,
// but we don't send the untagged EXPUNGE responses
let tag = self.req.tag.clone();
- self.expunge().await?;
+ self.expunge(&None).await?;
Ok((
Response::build().tag(tag).message("CLOSE completed").ok()?,
flow::Transition::Unselect,
@@ -223,13 +226,13 @@ impl<'a> SelectedContext<'a> {
))
}
- async fn expunge(self) -> Result<(Response<'static>, flow::Transition)> {
+ async fn expunge(self, uid_sequence_set: &Option<SequenceSet>) -> Result<(Response<'static>, flow::Transition)> {
if let Some(failed) = self.fail_read_only() {
return Ok((failed, flow::Transition::None));
}
let tag = self.req.tag.clone();
- let data = self.mailbox.expunge().await?;
+ let data = self.mailbox.expunge(uid_sequence_set).await?;
Ok((
Response::build()
diff --git a/src/imap/mailbox_view.rs b/src/imap/mailbox_view.rs
index 0efa987..f632df1 100644
--- a/src/imap/mailbox_view.rs
+++ b/src/imap/mailbox_view.rs
@@ -237,16 +237,26 @@ impl MailboxView {
self.update(UpdateParameters::default()).await
}
- pub async fn expunge(&mut self) -> Result<Vec<Body<'static>>> {
+ pub async fn expunge(&mut self, maybe_seq_set: &Option<SequenceSet>) -> Result<Vec<Body<'static>>> {
+ // Get a recent view to apply our change
self.internal.sync().await?;
let state = self.internal.peek().await;
+ let idx = Index::new(&state)?;
+
+ // Build a default sequence set for the default case
+ use imap_codec::imap_types::sequence::{Sequence, SeqOrUid};
+ let seq = match maybe_seq_set {
+ Some(s) => s.clone(),
+ None => SequenceSet(vec![Sequence::Range(SeqOrUid::Value(NonZeroU32::MIN), SeqOrUid::Asterisk)].try_into().unwrap()),
+ };
+
let deleted_flag = Flag::Deleted.to_string();
- let msgs = state
- .table
- .iter()
- .filter(|(_uuid, (_uid, _modseq, flags))| flags.iter().any(|x| *x == deleted_flag))
- .map(|(uuid, _)| *uuid);
+ let msgs = idx
+ .fetch_on_uid(&seq)
+ .into_iter()
+ .filter(|midx| midx.flags.iter().any(|x| *x == deleted_flag))
+ .map(|midx| midx.uuid);
for msg in msgs {
self.internal.mailbox.delete(msg).await?;