From d8408815050edcb4c068a3d95ea0ede2c315aba7 Mon Sep 17 00:00:00 2001 From: paulpr0 Date: Mon, 22 Feb 2021 12:29:04 +0000 Subject: [PATCH 1/2] When fetching a large number of UIDs, rust-imap would sometimes produce an error. Lookig into it, dovecot sometimes responds with * OK Searched 91% of the mailbox, ETA 0:01 which is not handled when expecting a response to a Fetch message. This is a small change to handle this case. I have made it quite explicit - it only handles an OK status with no code, as I'm not sure whether other messages which have an unknown code (but do contain a code) would be better handled by returning an error as is currently the case. --- src/parse.rs | 13 +++++++++++++ src/types/mod.rs | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/src/parse.rs b/src/parse.rs index b2dc002f..662c4384 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -331,6 +331,9 @@ fn handle_unilateral<'a>( Response::Expunge(n) => { unsolicited.send(UnsolicitedResponse::Expunge(n)).unwrap(); } + Response::Data {status, code, information} if imap_proto::Status::Ok == status && code.is_none() => { + unsolicited.send(UnsolicitedResponse::Uncategorised(information.unwrap_or("").to_string())).unwrap(); + } res => { return Some(res); } @@ -439,6 +442,16 @@ mod tests { assert_eq!(fetches[0].uid, Some(74)); } + #[test] + fn parse_uncategorised_ok() { + let lines = b"\ + * OK Searched 91% of the mailbox, ETA 0:01\r\n"; + let (mut send, recv) = mpsc::channel(); + parse_fetches(lines.to_vec(), &mut send).unwrap(); + assert_eq!(recv.try_recv(), Ok(UnsolicitedResponse::Uncategorised("Searched 91% of the mailbox, ETA 0:01".to_string()))); + + } + #[test] fn parse_names_w_unilateral() { let lines = b"\ diff --git a/src/types/mod.rs b/src/types/mod.rs index fb57e4e8..4689b7cf 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -277,6 +277,10 @@ pub enum UnsolicitedResponse { /// sequence numbers 9, 8, 7, 6, and 5. // TODO: the spec doesn't seem to say anything about when these may be received as unsolicited? Expunge(Seq), + /// An uncategorised response - one which has no code associated with it, just a text + /// Dovecot is known to send a status message with an ETA for a long running fetch which + /// has no [] enclosed code. + Uncategorised(String), } /// This type wraps an input stream and a type that was constructed by parsing that input stream, From 01f2a93ab46d146909cd2c50eaf3be88fccb50f6 Mon Sep 17 00:00:00 2001 From: paulpr0 Date: Mon, 22 Feb 2021 12:54:11 +0000 Subject: [PATCH 2/2] ran cargo fmt... --- src/parse.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 662c4384..eae2a1f3 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -331,8 +331,16 @@ fn handle_unilateral<'a>( Response::Expunge(n) => { unsolicited.send(UnsolicitedResponse::Expunge(n)).unwrap(); } - Response::Data {status, code, information} if imap_proto::Status::Ok == status && code.is_none() => { - unsolicited.send(UnsolicitedResponse::Uncategorised(information.unwrap_or("").to_string())).unwrap(); + Response::Data { + status, + code, + information, + } if imap_proto::Status::Ok == status && code.is_none() => { + unsolicited + .send(UnsolicitedResponse::Uncategorised( + information.unwrap_or("").to_string(), + )) + .unwrap(); } res => { return Some(res); @@ -448,8 +456,12 @@ mod tests { * OK Searched 91% of the mailbox, ETA 0:01\r\n"; let (mut send, recv) = mpsc::channel(); parse_fetches(lines.to_vec(), &mut send).unwrap(); - assert_eq!(recv.try_recv(), Ok(UnsolicitedResponse::Uncategorised("Searched 91% of the mailbox, ETA 0:01".to_string()))); - + assert_eq!( + recv.try_recv(), + Ok(UnsolicitedResponse::Uncategorised( + "Searched 91% of the mailbox, ETA 0:01".to_string() + )) + ); } #[test]