aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2022-07-13 15:39:52 +0200
committerAlex Auvolat <alex@adnab.me>2022-07-13 15:39:52 +0200
commit3b256de3dc1347bf449905de714ac5486935264a (patch)
tree55fbeb68d510ed62f02566870a62907d1e37520d
parent956a92377ea46e730f9fe5dcfee8b49be65e78ec (diff)
downloadaerogramme-3b256de3dc1347bf449905de714ac5486935264a.tar.gz
aerogramme-3b256de3dc1347bf449905de714ac5486935264a.zip
Remove OK [UNSEEN x] responses to SELECT and EXAMINE, and fix STATUS UNSEEN
-rw-r--r--src/imap/command/authenticated.rs9
-rw-r--r--src/imap/mailbox_view.rs36
-rw-r--r--src/mail/mailbox.rs5
3 files changed, 18 insertions, 32 deletions
diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs
index 5cf8cf9..dc8b5a8 100644
--- a/src/imap/command/authenticated.rs
+++ b/src/imap/command/authenticated.rs
@@ -218,9 +218,7 @@ impl<'a> AuthenticatedContext<'a> {
for attr in attributes.iter() {
ret_attrs.push(match attr {
StatusAttribute::Messages => StatusAttributeValue::Messages(view.exists()?),
- StatusAttribute::Unseen => {
- StatusAttributeValue::Unseen(view.unseen().map(|x| x.get()).unwrap_or(0))
- }
+ StatusAttribute::Unseen => StatusAttributeValue::Unseen(view.unseen_count() as u32),
StatusAttribute::Recent => StatusAttributeValue::Recent(view.recent()?),
StatusAttribute::UidNext => StatusAttributeValue::UidNext(view.uidnext()),
StatusAttribute::UidValidity => {
@@ -287,6 +285,11 @@ impl<'a> AuthenticatedContext<'a> {
S: A142 OK [READ-WRITE] SELECT completed
--- a mailbox with no unseen message -> no unseen entry
+ NOTES:
+ RFC3501 (imap4rev1) says if there is no OK [UNSEEN] response, client must make no assumption,
+ it is therefore correct to not return it even if there are unseen messages
+ RFC9051 (imap4rev2) says that OK [UNSEEN] responses are deprecated after SELECT and EXAMINE
+ For Aerogramme, we just don't send the OK [UNSEEN], it's correct to do in both specifications.
20 select "INBOX.achats"
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft $Forwarded JUNK $label1)
diff --git a/src/imap/mailbox_view.rs b/src/imap/mailbox_view.rs
index f9485e4..25b3f3e 100644
--- a/src/imap/mailbox_view.rs
+++ b/src/imap/mailbox_view.rs
@@ -61,9 +61,6 @@ impl MailboxView {
data.extend(new_view.flags_status()?.into_iter());
data.push(new_view.uidvalidity_status()?);
data.push(new_view.uidnext_status()?);
- if let Some(unseen) = new_view.unseen_status()? {
- data.push(unseen);
- }
Ok((new_view, data))
}
@@ -432,27 +429,6 @@ impl MailboxView {
self.known_state.uidnext
}
- /// Produces an UNSEEN message (if relevant) corresponding to the
- /// first unseen message id in `known_state`
- fn unseen_status(&self) -> Result<Option<Body>> {
- if let Some(unseen) = self.unseen() {
- let status_unseen =
- Status::ok(None, Some(Code::Unseen(unseen.clone())), "First unseen UID")
- .map_err(Error::msg)?;
- Ok(Some(Body::Status(status_unseen)))
- } else {
- Ok(None)
- }
- }
-
- pub(crate) fn unseen(&self) -> Option<ImapUid> {
- self.known_state
- .idx_by_flag
- .get(&"$unseen".to_string())
- .and_then(|os| os.get_min())
- .cloned()
- }
-
/// Produce an EXISTS message corresponding to the number of mails
/// in `known_state`
fn exists_status(&self) -> Result<Body> {
@@ -504,6 +480,17 @@ impl MailboxView {
Ok(ret)
}
+
+ pub(crate) fn unseen_count(&self) -> usize {
+ let total = self.known_state.table.len();
+ let seen = self
+ .known_state
+ .idx_by_flag
+ .get(&Flag::Seen.to_string())
+ .map(|x| x.len())
+ .unwrap_or(0);
+ total - seen
+ }
}
fn string_to_flag(f: &str) -> Option<Flag> {
@@ -523,7 +510,6 @@ fn string_to_flag(f: &str) -> Option<Flag> {
Ok(a) => Some(Flag::Extension(a)),
},
},
- Some('$') if f == "$unseen" => None,
Some(_) => match Atom::try_from(f.clone()) {
Err(_) => {
tracing::error!(flag=%f, "Unable to encode flag as IMAP atom");
diff --git a/src/mail/mailbox.rs b/src/mail/mailbox.rs
index 19a95e0..c61ab0c 100644
--- a/src/mail/mailbox.rs
+++ b/src/mail/mailbox.rs
@@ -374,10 +374,7 @@ impl MailboxInternal {
)?;
// Add mail to Bayou mail index
- let add_mail_op = self
- .uid_index
- .state()
- .op_mail_add(ident, vec!["\\Unseen".into()]);
+ let add_mail_op = self.uid_index.state().op_mail_add(ident, vec![]);
self.uid_index.push(add_mail_op).await?;
Ok(())