From 746bdfe6b909cb21c088b0128ff7ec0dfb3067bb Mon Sep 17 00:00:00 2001 From: Todd Mortimer Date: Sat, 18 Apr 2020 19:48:25 -0400 Subject: [PATCH] Handle Dovecot's periodic IDLE notification messages ("OK Still here"). These messages show up at an interval controlled by Dovecot's imap_idle_notify_interval setting, which defaults to 2 minutes. These messages were causing the IDLE loop to exit prematurely because it looks like a notification response from the server. --- src/extensions/idle.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/extensions/idle.rs b/src/extensions/idle.rs index e802d32..12aa514 100644 --- a/src/extensions/idle.rs +++ b/src/extensions/idle.rs @@ -93,16 +93,26 @@ impl<'a, T: Read + Write + 'a> Handle<'a, T> { /// This is necessary so that we can keep using the inner `Session` in `wait_keepalive`. fn wait_inner(&mut self) -> Result<()> { let mut v = Vec::new(); - match self.session.readline(&mut v).map(|_| ()) { - Err(Error::Io(ref e)) - if e.kind() == io::ErrorKind::TimedOut || e.kind() == io::ErrorKind::WouldBlock => - { - // we need to refresh the IDLE connection - self.terminate()?; - self.init()?; - self.wait_inner() + loop { + match self.session.readline(&mut v).map(|_| ()) { + Err(Error::Io(ref e)) + if e.kind() == io::ErrorKind::TimedOut + || e.kind() == io::ErrorKind::WouldBlock => + { + // we need to refresh the IDLE connection + self.terminate()?; + self.init()?; + return self.wait_inner(); + } + r => r, + }?; + + // Handle Dovecot's imap_idle_notify_interval message + if v.eq_ignore_ascii_case(b"* OK Still here\r\n") { + v.clear(); + } else { + break Ok(()); } - r => r, } }