imap: support LIST-STATUS
parent
350c8033b1
commit
6121f77853
|
@ -60,6 +60,7 @@ pub static SUPPORTED_CAPABILITIES: &[&str] = &[
|
||||||
"IDLE",
|
"IDLE",
|
||||||
"LOGIN",
|
"LOGIN",
|
||||||
"LOGINDISABLED",
|
"LOGINDISABLED",
|
||||||
|
"LIST-STATUS",
|
||||||
"ENABLE",
|
"ENABLE",
|
||||||
"IMAP4REV1",
|
"IMAP4REV1",
|
||||||
"SPECIAL-USE",
|
"SPECIAL-USE",
|
||||||
|
@ -914,10 +915,26 @@ impl ImapType {
|
||||||
let mut mailboxes: HashMap<MailboxHash, ImapMailbox> = Default::default();
|
let mut mailboxes: HashMap<MailboxHash, ImapMailbox> = Default::default();
|
||||||
let mut res = String::with_capacity(8 * 1024);
|
let mut res = String::with_capacity(8 * 1024);
|
||||||
let mut conn = connection.lock().await;
|
let mut conn = connection.lock().await;
|
||||||
conn.send_command(b"LIST \"\" \"*\"").await?;
|
let has_list_status: bool = conn
|
||||||
let _ = conn
|
.uid_store
|
||||||
.read_response(&mut res, RequiredResponses::LIST_REQUIRED)
|
.capabilities
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.any(|cap| cap.eq_ignore_ascii_case(b"LIST-STATUS"));
|
||||||
|
if has_list_status {
|
||||||
|
conn.send_command(b"LIST \"\" \"*\" RETURN (STATUS (MESSAGES UNSEEN))")
|
||||||
|
.await?;
|
||||||
|
conn.read_response(
|
||||||
|
&mut res,
|
||||||
|
RequiredResponses::LIST_REQUIRED | RequiredResponses::STATUS,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
} else {
|
||||||
|
conn.send_command(b"LIST \"\" \"*\"").await?;
|
||||||
|
conn.read_response(&mut res, RequiredResponses::LIST_REQUIRED)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
debug!("out: {}", &res);
|
debug!("out: {}", &res);
|
||||||
let mut lines = res.split_rn();
|
let mut lines = res.split_rn();
|
||||||
/* Remove "M__ OK .." line */
|
/* Remove "M__ OK .." line */
|
||||||
|
@ -951,6 +968,20 @@ impl ImapType {
|
||||||
} else {
|
} else {
|
||||||
mailboxes.insert(mailbox.hash, mailbox);
|
mailboxes.insert(mailbox.hash, mailbox);
|
||||||
}
|
}
|
||||||
|
} else if let Ok(status) =
|
||||||
|
protocol_parser::status_response(l.as_bytes()).map(|(_, v)| v)
|
||||||
|
{
|
||||||
|
if let Some(mailbox_hash) = status.mailbox {
|
||||||
|
if mailboxes.contains_key(&mailbox_hash) {
|
||||||
|
let entry = mailboxes.entry(mailbox_hash).or_default();
|
||||||
|
if let Some(total) = status.messages {
|
||||||
|
entry.exists.lock().unwrap().set_not_yet_seen(total);
|
||||||
|
}
|
||||||
|
if let Some(total) = status.unseen {
|
||||||
|
entry.unseen.lock().unwrap().set_not_yet_seen(total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("parse error for {:?}", l);
|
debug!("parse error for {:?}", l);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1459,6 +1459,7 @@ pub fn bodystructure_has_attachments(input: &[u8]) -> bool {
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct StatusResponse {
|
pub struct StatusResponse {
|
||||||
|
pub mailbox: Option<MailboxHash>,
|
||||||
pub messages: Option<usize>,
|
pub messages: Option<usize>,
|
||||||
pub recent: Option<usize>,
|
pub recent: Option<usize>,
|
||||||
pub uidnext: Option<usize>,
|
pub uidnext: Option<usize>,
|
||||||
|
@ -1468,9 +1469,11 @@ pub struct StatusResponse {
|
||||||
|
|
||||||
// status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
|
// status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
|
||||||
// status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / "UNSEEN"
|
// status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / "UNSEEN"
|
||||||
|
//* STATUS INBOX (MESSAGES 1057 UNSEEN 0)
|
||||||
pub fn status_response(input: &[u8]) -> IResult<&[u8], StatusResponse> {
|
pub fn status_response(input: &[u8]) -> IResult<&[u8], StatusResponse> {
|
||||||
let (input, _) = tag("* STATUS ")(input)?;
|
let (input, _) = tag("* STATUS ")(input)?;
|
||||||
let (input, _) = take_until(" (")(input)?;
|
let (input, mailbox) = take_until(" (")(input)?;
|
||||||
|
let mailbox = mailbox_token(mailbox).map(|(_, m)| get_path_hash!(m)).ok();
|
||||||
let (input, _) = tag(" (")(input)?;
|
let (input, _) = tag(" (")(input)?;
|
||||||
let (input, result) = permutation((
|
let (input, result) = permutation((
|
||||||
opt(preceded(
|
opt(preceded(
|
||||||
|
@ -1508,6 +1511,7 @@ pub fn status_response(input: &[u8]) -> IResult<&[u8], StatusResponse> {
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
StatusResponse {
|
StatusResponse {
|
||||||
|
mailbox,
|
||||||
messages: result.0,
|
messages: result.0,
|
||||||
recent: result.1,
|
recent: result.1,
|
||||||
uidnext: result.2,
|
uidnext: result.2,
|
||||||
|
|
Loading…
Reference in New Issue