imap: add UntaggedResponse::UIDFetch
parent
f41a1ffe3a
commit
031e81ac8f
|
@ -129,7 +129,7 @@ impl BackendOp for ImapOp {
|
||||||
response.len(),
|
response.len(),
|
||||||
response.lines().collect::<Vec<&str>>().len()
|
response.lines().collect::<Vec<&str>>().len()
|
||||||
);
|
);
|
||||||
let v = protocol_parser::uid_fetch_flags_response(response.as_bytes())
|
let v = protocol_parser::uid_fetch_flags_responses(response.as_bytes())
|
||||||
.map(|(_, v)| v)
|
.map(|(_, v)| v)
|
||||||
.map_err(MeliError::from)?;
|
.map_err(MeliError::from)?;
|
||||||
if v.len() != 1 {
|
if v.len() != 1 {
|
||||||
|
|
|
@ -139,7 +139,7 @@ fn test_imap_required_responses() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert_eq!(&ret, "* 1040 FETCH (UID 1064 FLAGS ())\r\n");
|
assert_eq!(&ret, "* 1040 FETCH (UID 1064 FLAGS ())\r\n");
|
||||||
let v = protocol_parser::uid_fetch_flags_response(response.as_bytes())
|
let v = protocol_parser::uid_fetch_flags_responses(response.as_bytes())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.1;
|
.1;
|
||||||
assert_eq!(v.len(), 1);
|
assert_eq!(v.len(), 1);
|
||||||
|
@ -727,24 +727,28 @@ pub fn uid_fetch_response_(
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uid_fetch_flags_response(input: &[u8]) -> IResult<&[u8], Vec<(usize, (Flag, Vec<String>))>> {
|
pub fn uid_fetch_flags_responses(
|
||||||
many0(|input| -> IResult<&[u8], (usize, (Flag, Vec<String>))> {
|
input: &[u8],
|
||||||
let (input, _) = tag("* ")(input)?;
|
) -> IResult<&[u8], Vec<(usize, (Flag, Vec<String>))>> {
|
||||||
let (input, _msn) = take_while(is_digit)(input)?;
|
many0(uid_fetch_flags_response)(input)
|
||||||
let (input, _) = tag(" FETCH (")(input)?;
|
}
|
||||||
let (input, uid_flags) = permutation((
|
|
||||||
preceded(
|
pub fn uid_fetch_flags_response(input: &[u8]) -> IResult<&[u8], (usize, (Flag, Vec<String>))> {
|
||||||
alt((tag("UID "), tag(" UID "))),
|
let (input, _) = tag("* ")(input)?;
|
||||||
map_res(digit1, |s| usize::from_str(to_str!(s))),
|
let (input, _msn) = take_while(is_digit)(input)?;
|
||||||
),
|
let (input, _) = tag(" FETCH (")(input)?;
|
||||||
preceded(
|
let (input, uid_flags) = permutation((
|
||||||
alt((tag("FLAGS "), tag(" FLAGS "))),
|
preceded(
|
||||||
delimited(tag("("), byte_flags, tag(")")),
|
alt((tag("UID "), tag(" UID "))),
|
||||||
),
|
map_res(digit1, |s| usize::from_str(to_str!(s))),
|
||||||
))(input)?;
|
),
|
||||||
let (input, _) = tag(")\r\n")(input)?;
|
preceded(
|
||||||
Ok((input, (uid_flags.0, uid_flags.1)))
|
alt((tag("FLAGS "), tag(" FLAGS "))),
|
||||||
})(input)
|
delimited(tag("("), byte_flags, tag(")")),
|
||||||
|
),
|
||||||
|
))(input)?;
|
||||||
|
let (input, _) = tag(")\r\n")(input)?;
|
||||||
|
Ok((input, (uid_flags.0, uid_flags.1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! flags_to_imap_list {
|
macro_rules! flags_to_imap_list {
|
||||||
|
@ -871,18 +875,20 @@ pub enum UntaggedResponse {
|
||||||
/// ```
|
/// ```
|
||||||
Recent(usize),
|
Recent(usize),
|
||||||
Fetch(usize, (Flag, Vec<String>)),
|
Fetch(usize, (Flag, Vec<String>)),
|
||||||
|
UIDFetch(UID, (Flag, Vec<String>)),
|
||||||
Bye {
|
Bye {
|
||||||
reason: String,
|
reason: String,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn untagged_responses(input: &[u8]) -> IResult<&[u8], Option<UntaggedResponse>> {
|
pub fn untagged_responses(input: &[u8]) -> IResult<&[u8], Option<UntaggedResponse>> {
|
||||||
|
let orig_input = input;
|
||||||
let (input, _) = tag("* ")(input)?;
|
let (input, _) = tag("* ")(input)?;
|
||||||
let (input, num) = map_res(digit1, |s| usize::from_str(to_str!(s)))(input)?;
|
let (input, num) = map_res(digit1, |s| usize::from_str(to_str!(s)))(input)?;
|
||||||
let (input, _) = tag(" ")(input)?;
|
let (input, _) = tag(" ")(input)?;
|
||||||
let (input, _tag) = take_until("\r\n")(input)?;
|
let (input, _tag) = take_until("\r\n")(input)?;
|
||||||
let (input, _) = tag("\r\n")(input)?;
|
let (input, _) = tag("\r\n")(input)?;
|
||||||
debug!("Parse untagged response from {:?}", to_str!(input));
|
debug!("Parse untagged response from {:?}", to_str!(orig_input));
|
||||||
Ok((input, {
|
Ok((input, {
|
||||||
use UntaggedResponse::*;
|
use UntaggedResponse::*;
|
||||||
match _tag {
|
match _tag {
|
||||||
|
@ -890,18 +896,23 @@ pub fn untagged_responses(input: &[u8]) -> IResult<&[u8], Option<UntaggedRespons
|
||||||
b"EXISTS" => Some(Exists(num)),
|
b"EXISTS" => Some(Exists(num)),
|
||||||
b"RECENT" => Some(Recent(num)),
|
b"RECENT" => Some(Recent(num)),
|
||||||
_ if _tag.starts_with(b"FETCH ") => {
|
_ if _tag.starts_with(b"FETCH ") => {
|
||||||
let f = flags(unsafe {
|
if to_str!(_tag).contains("UID") {
|
||||||
std::str::from_utf8_unchecked(&_tag[b"FETCH (FLAGS (".len()..])
|
let (uid, flags) = uid_fetch_flags_response(orig_input)?.1;
|
||||||
})
|
Some(UIDFetch(uid, flags))
|
||||||
.map(|(_, flags)| Fetch(num, flags));
|
} else {
|
||||||
if let Err(ref err) = f {
|
let f = flags(unsafe {
|
||||||
debug!(
|
std::str::from_utf8_unchecked(&_tag[b"FETCH (FLAGS (".len()..])
|
||||||
"untagged_response malformed fetch: {} {}",
|
})
|
||||||
unsafe { std::str::from_utf8_unchecked(_tag) },
|
.map(|(_, flags)| Fetch(num, flags));
|
||||||
err
|
if let Err(ref err) = f {
|
||||||
)
|
debug!(
|
||||||
|
"untagged_response malformed fetch: {} {}",
|
||||||
|
unsafe { std::str::from_utf8_unchecked(_tag) },
|
||||||
|
err
|
||||||
|
)
|
||||||
|
}
|
||||||
|
f.ok()
|
||||||
}
|
}
|
||||||
f.ok()
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
debug!("unknown untagged_response: {}", to_str!(_tag));
|
debug!("unknown untagged_response: {}", to_str!(_tag));
|
||||||
|
|
|
@ -279,6 +279,24 @@ impl ImapConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UntaggedResponse::UIDFetch(uid, flags) => {
|
||||||
|
debug!("fetch uid {} {:?}", uid, flags);
|
||||||
|
let lck = self.uid_store.uid_index.lock().unwrap();
|
||||||
|
let env_hash = lck.get(&(mailbox_hash, uid)).copied();
|
||||||
|
drop(lck);
|
||||||
|
if let Some(env_hash) = env_hash {
|
||||||
|
if !flags.0.intersects(crate::email::Flag::SEEN) {
|
||||||
|
mailbox.unseen.lock().unwrap().insert_new(env_hash);
|
||||||
|
} else {
|
||||||
|
mailbox.unseen.lock().unwrap().remove(env_hash);
|
||||||
|
}
|
||||||
|
self.add_refresh_event(RefreshEvent {
|
||||||
|
account_hash: self.uid_store.account_hash,
|
||||||
|
mailbox_hash,
|
||||||
|
kind: NewFlags(env_hash, flags),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
UntaggedResponse::Fetch(msg_seq, flags) => {
|
UntaggedResponse::Fetch(msg_seq, flags) => {
|
||||||
/* a * {msg_seq} FETCH (FLAGS ({flags})) was received, so find out UID from msg_seq
|
/* a * {msg_seq} FETCH (FLAGS ({flags})) was received, so find out UID from msg_seq
|
||||||
* and send update
|
* and send update
|
||||||
|
@ -288,7 +306,7 @@ impl ImapConnection {
|
||||||
mailbox_hash,
|
mailbox_hash,
|
||||||
self.send_command(
|
self.send_command(
|
||||||
&[
|
&[
|
||||||
b"UID SEARCH ",
|
b"UID SEARCH",
|
||||||
format!("{}", msg_seq).as_bytes(),
|
format!("{}", msg_seq).as_bytes(),
|
||||||
]
|
]
|
||||||
.join(&b' '),
|
.join(&b' '),
|
||||||
|
|
|
@ -444,6 +444,27 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(Some(UIDFetch(uid, flags))) => {
|
||||||
|
let res = uid_store
|
||||||
|
.uid_index
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get(&(mailbox_hash, uid))
|
||||||
|
.map(|h| *h);
|
||||||
|
if let Some(env_hash) = res {
|
||||||
|
if !flags.0.intersects(crate::email::Flag::SEEN) {
|
||||||
|
mailbox.unseen.lock().unwrap().insert_new(env_hash);
|
||||||
|
} else {
|
||||||
|
mailbox.unseen.lock().unwrap().remove(env_hash);
|
||||||
|
}
|
||||||
|
let mut conn = main_conn.lock().await;
|
||||||
|
conn.add_refresh_event(RefreshEvent {
|
||||||
|
account_hash: uid_store.account_hash,
|
||||||
|
mailbox_hash,
|
||||||
|
kind: NewFlags(env_hash, flags),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Some(Fetch(msg_seq, flags))) => {
|
Ok(Some(Fetch(msg_seq, flags))) => {
|
||||||
/* a * {msg_seq} FETCH (FLAGS ({flags})) was received, so find out UID from msg_seq
|
/* a * {msg_seq} FETCH (FLAGS ({flags})) was received, so find out UID from msg_seq
|
||||||
* and send update
|
* and send update
|
||||||
|
@ -456,7 +477,7 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
|
||||||
conn.examine_mailbox(mailbox_hash, &mut response, false).await
|
conn.examine_mailbox(mailbox_hash, &mut response, false).await
|
||||||
conn.send_command(
|
conn.send_command(
|
||||||
&[
|
&[
|
||||||
b"UID SEARCH ",
|
b"UID SEARCH",
|
||||||
format!("{}", msg_seq).as_bytes(),
|
format!("{}", msg_seq).as_bytes(),
|
||||||
]
|
]
|
||||||
.join(&b' '),
|
.join(&b' '),
|
||||||
|
|
Loading…
Reference in New Issue