Expose mailbox read-only flag

This commit is contained in:
Jon Gjengset 2021-03-06 15:02:48 -08:00
parent 9b78550394
commit 18ca65dd3f
3 changed files with 25 additions and 14 deletions

View file

@ -599,12 +599,8 @@ impl<T: Read + Write> Session<T> {
/// `EXISTS`, `FETCH`, and `EXPUNGE` responses. You can get them from the
/// `unsolicited_responses` channel of the [`Session`](struct.Session.html).
pub fn select<S: AsRef<str>>(&mut self, mailbox_name: S) -> Result<Mailbox> {
// 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<T: Read + Write> Session<T> {
/// 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<S: AsRef<str>>(&mut self, mailbox_name: S) -> Result<Mailbox> {
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));

View file

@ -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);

View file

@ -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<u64>,
/// 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,
)
}
}