From 18ca65dd3f1df6ce9daf91f4d93debb14bd1f369 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Sat, 6 Mar 2021 15:02:48 -0800 Subject: [PATCH] Expose mailbox read-only flag --- src/client.rs | 17 ++++++----------- src/parse.rs | 14 ++++++++++++-- src/types/mailbox.rs | 8 +++++++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/client.rs b/src/client.rs index 36535f7..e13dfd6 100644 --- a/src/client.rs +++ b/src/client.rs @@ -599,12 +599,8 @@ impl Session { /// `EXISTS`, `FETCH`, and `EXPUNGE` responses. You can get them from the /// `unsolicited_responses` channel of the [`Session`](struct.Session.html). pub fn select>(&mut self, mailbox_name: S) -> Result { - // TODO: also note READ/WRITE vs READ-only mode! - self.run_command_and_read_response(&format!( - "SELECT {}", - validate_str(mailbox_name.as_ref())? - )) - .and_then(|lines| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx)) + self.run(&format!("SELECT {}", validate_str(mailbox_name.as_ref())?)) + .and_then(|(lines, _)| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx)) } /// The `EXAMINE` command is identical to [`Session::select`] and returns the same output; @@ -612,11 +608,8 @@ impl Session { /// of the mailbox, including per-user state, will happen in a mailbox opened with `examine`; /// in particular, messagess cannot lose [`Flag::Recent`] in an examined mailbox. pub fn examine>(&mut self, mailbox_name: S) -> Result { - self.run_command_and_read_response(&format!( - "EXAMINE {}", - validate_str(mailbox_name.as_ref())? - )) - .and_then(|lines| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx)) + self.run(&format!("EXAMINE {}", validate_str(mailbox_name.as_ref())?)) + .and_then(|(lines, _)| parse_mailbox(&lines[..], &mut self.unsolicited_responses_tx)) } /// Fetch retrieves data associated with a set of messages in the mailbox. @@ -1756,6 +1749,7 @@ mod tests { uid_next: Some(2), uid_validity: Some(1257842737), highest_mod_seq: None, + is_read_only: true, }; let mailbox_name = "INBOX"; let command = format!("a1 EXAMINE {}\r\n", quote!(mailbox_name)); @@ -1803,6 +1797,7 @@ mod tests { uid_next: Some(2), uid_validity: Some(1257842737), highest_mod_seq: None, + is_read_only: true, }; let mailbox_name = "INBOX"; let command = format!("a1 SELECT {}\r\n", quote!(mailbox_name)); diff --git a/src/parse.rs b/src/parse.rs index ae79fe3..32b518e 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,4 +1,4 @@ -use imap_proto::{self, MailboxDatum, Response}; +use imap_proto::{MailboxDatum, Response, ResponseCode}; use lazy_static::lazy_static; use regex::Regex; use std::collections::HashSet; @@ -236,6 +236,17 @@ pub fn parse_mailbox( loop { match imap_proto::parser::parse_response(lines) { + Ok((rest, Response::Done { status, code, .. })) => { + assert!(rest.is_empty()); + lines = rest; + + // We wouldn't get to parsing if this wasn't an Ok response. + assert_eq!(status, imap_proto::Status::Ok); + + if let Some(ResponseCode::ReadOnly) = code { + mailbox.is_read_only = true; + } + } Ok((rest, Response::Data { status, code, .. })) => { lines = rest; @@ -245,7 +256,6 @@ pub fn parse_mailbox( unreachable!(); } - use imap_proto::ResponseCode; match code { Some(ResponseCode::HighestModSeq(seq)) => { mailbox.highest_mod_seq = Some(seq); diff --git a/src/types/mailbox.rs b/src/types/mailbox.rs index 1cadba6..cebe1bd 100644 --- a/src/types/mailbox.rs +++ b/src/types/mailbox.rs @@ -40,6 +40,10 @@ pub struct Mailbox { /// The highest mod sequence for this mailbox. Used with /// [Conditional STORE](https://tools.ietf.org/html/rfc4551#section-3.1.1). pub highest_mod_seq: Option, + + /// The mailbox is selected read-only, or its access while selected has changed from read-write + /// to read-only. + pub is_read_only: bool, } impl Default for Mailbox { @@ -53,6 +57,7 @@ impl Default for Mailbox { uid_next: None, uid_validity: None, highest_mod_seq: None, + is_read_only: false, } } } @@ -62,7 +67,7 @@ impl fmt::Display for Mailbox { write!( f, "flags: {:?}, exists: {}, recent: {}, unseen: {:?}, permanent_flags: {:?},\ - uid_next: {:?}, uid_validity: {:?}, highest_mod_seq: {:?}", + uid_next: {:?}, uid_validity: {:?}, highest_mod_seq: {:?}, is_read_only: {:?}", self.flags, self.exists, self.recent, @@ -71,6 +76,7 @@ impl fmt::Display for Mailbox { self.uid_next, self.uid_validity, self.highest_mod_seq, + self.is_read_only, ) } }