imap: add status_response() parser
This commit is contained in:
parent
c7835ccc13
commit
c08ceae97c
2 changed files with 79 additions and 1 deletions
|
@ -300,7 +300,7 @@ impl MailBackend for ImapType {
|
||||||
.chain_err_summary(|| {
|
.chain_err_summary(|| {
|
||||||
format!("Could not select mailbox {}", mailbox_path)
|
format!("Could not select mailbox {}", mailbox_path)
|
||||||
})?;
|
})?;
|
||||||
let examine_response = protocol_parser::select_response(&response)
|
let mut examine_response = protocol_parser::select_response(&response)
|
||||||
.chain_err_summary(|| {
|
.chain_err_summary(|| {
|
||||||
format!(
|
format!(
|
||||||
"Could not parse select response for mailbox {}",
|
"Could not parse select response for mailbox {}",
|
||||||
|
@ -345,6 +345,24 @@ impl MailBackend for ImapType {
|
||||||
let mut exists: usize = examine_response.exists;
|
let mut exists: usize = examine_response.exists;
|
||||||
/* reselecting the same mailbox with EXAMINE prevents expunging it */
|
/* reselecting the same mailbox with EXAMINE prevents expunging it */
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response)?;
|
conn.examine_mailbox(mailbox_hash, &mut response)?;
|
||||||
|
if examine_response.uidnext == 0 {
|
||||||
|
/* UIDNEXT shouldn't be 0, since exists != 0 at this point */
|
||||||
|
conn.send_command(
|
||||||
|
format!("STATUS \"{}\" (UIDNEXT)", mailbox_path).as_bytes(),
|
||||||
|
)?;
|
||||||
|
conn.read_response(&mut response, RequiredResponses::STATUS)?;
|
||||||
|
let (_, status) = protocol_parser::status_response(response.as_bytes())?;
|
||||||
|
if let Some(uidnext) = status.uidnext {
|
||||||
|
if uidnext == 0 {
|
||||||
|
return Err(MeliError::new(
|
||||||
|
"IMAP server error: zero UIDNEXt with nonzero exists.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
examine_response.uidnext = uidnext;
|
||||||
|
} else {
|
||||||
|
return Err(MeliError::new("IMAP server did not reply with UIDNEXT"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut tag_lck = uid_store.tag_index.write().unwrap();
|
let mut tag_lck = uid_store.tag_index.write().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1402,6 +1402,66 @@ pub fn bodystructure_has_attachments(input: &[u8]) -> bool {
|
||||||
input.rfind(b" \"mixed\" ").is_some() || input.rfind(b" \"MIXED\" ").is_some()
|
input.rfind(b" \"mixed\" ").is_some() || input.rfind(b" \"MIXED\" ").is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone)]
|
||||||
|
pub struct StatusResponse {
|
||||||
|
pub messages: Option<usize>,
|
||||||
|
pub recent: Option<usize>,
|
||||||
|
pub uidnext: Option<usize>,
|
||||||
|
pub uidvalidity: Option<usize>,
|
||||||
|
pub unseen: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// status = "STATUS" SP mailbox SP "(" status-att *(SP status-att) ")"
|
||||||
|
// status-att = "MESSAGES" / "RECENT" / "UIDNEXT" / "UIDVALIDITY" / "UNSEEN"
|
||||||
|
pub fn status_response(input: &[u8]) -> IResult<&[u8], StatusResponse> {
|
||||||
|
let (input, _) = tag("* STATUS ")(input)?;
|
||||||
|
let (input, _) = take_until(" (")(input)?;
|
||||||
|
let (input, _) = tag(" (")(input)?;
|
||||||
|
let (input, result) = permutation((
|
||||||
|
opt(preceded(
|
||||||
|
tag("MESSAGES "),
|
||||||
|
map_res(digit1, |s| {
|
||||||
|
usize::from_str(unsafe { std::str::from_utf8_unchecked(s) })
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
opt(preceded(
|
||||||
|
tag("RECENT "),
|
||||||
|
map_res(digit1, |s| {
|
||||||
|
usize::from_str(unsafe { std::str::from_utf8_unchecked(s) })
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
opt(preceded(
|
||||||
|
tag("UIDNEXT "),
|
||||||
|
map_res(digit1, |s| {
|
||||||
|
usize::from_str(unsafe { std::str::from_utf8_unchecked(s) })
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
opt(preceded(
|
||||||
|
tag("UIDVALIDITY "),
|
||||||
|
map_res(digit1, |s| {
|
||||||
|
usize::from_str(unsafe { std::str::from_utf8_unchecked(s) })
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
opt(preceded(
|
||||||
|
tag("UNSEEN "),
|
||||||
|
map_res(digit1, |s| {
|
||||||
|
usize::from_str(unsafe { std::str::from_utf8_unchecked(s) })
|
||||||
|
}),
|
||||||
|
)),
|
||||||
|
))(input)?;
|
||||||
|
let (input, _) = tag(")\r\n")(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
StatusResponse {
|
||||||
|
messages: result.0,
|
||||||
|
recent: result.1,
|
||||||
|
uidnext: result.2,
|
||||||
|
uidvalidity: result.3,
|
||||||
|
unseen: result.4,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
// mailbox = "INBOX" / astring
|
// mailbox = "INBOX" / astring
|
||||||
// ; INBOX is case-insensitive. All case variants of
|
// ; INBOX is case-insensitive. All case variants of
|
||||||
// ; INBOX (e.g., "iNbOx") MUST be interpreted as INBOX
|
// ; INBOX (e.g., "iNbOx") MUST be interpreted as INBOX
|
||||||
|
|
Loading…
Add table
Reference in a new issue