From 1d03e0822e1be106778cabe778577799d0e20a28 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Thu, 24 Oct 2019 17:46:15 +0200 Subject: [PATCH] seems to work --- Cargo.lock | 12 ++++----- Cargo.toml | 2 +- src/imap.rs | 73 ++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51866a4cb..f8c1daf95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,7 +195,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "slice-deque 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -495,7 +495,7 @@ dependencies = [ "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "imap 1.0.2 (git+https://github.com/jonhoo/rust-imap)", + "imap 1.0.2 (git+https://github.com/deltachat/rust-imap?branch=fix-imap-hang1)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "jetscii 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1005,7 +1005,7 @@ dependencies = [ [[package]] name = "imap" version = "1.0.2" -source = "git+https://github.com/jonhoo/rust-imap#465481de88ff128b3c1403a056e56f6ead8a3a0e" +source = "git+https://github.com/deltachat/rust-imap?branch=fix-imap-hang1#b4c4a799860d8b98ee1d480933b007b4d863ff53" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2018,7 +2018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "safemem" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2914,7 +2914,7 @@ dependencies = [ "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum image-meta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b00861cbbb254a627d8acc0cec786b484297d896ab8f20fdc8e28536a3e918ef" -"checksum imap 1.0.2 (git+https://github.com/jonhoo/rust-imap)" = "" +"checksum imap 1.0.2 (git+https://github.com/deltachat/rust-imap?branch=fix-imap-hang1)" = "" "checksum imap-proto 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b92ca529b24c5f80a950abe993d3883df6fe6791d4a46b1fda1eb339796c589" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" @@ -3017,7 +3017,7 @@ dependencies = [ "checksum rusty-fork 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd93264e10c577503e926bd1430193eeb5d21b059148910082245309b424fae" "checksum rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f47ea1ceb347d2deae482d655dc8eef4bd82363d3329baffa3818bd76fea48b" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0" +"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum sanitize-filename 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23fd0fec94ec480abfd86bb8f4f6c57e0efb36dac5c852add176ea7b04c74801" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" diff --git a/Cargo.toml b/Cargo.toml index 19d8b86a2..e6e40252a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ num-derive = "0.2.5" num-traits = "0.2.6" native-tls = "0.2.3" lettre = { git = "https://github.com/deltachat/lettre", branch = "master" } -imap = { git = "https://github.com/jonhoo/rust-imap", branch = "master" } +imap = { git = "https://github.com/deltachat/rust-imap", branch = "fix-imap-hang1" } base64 = "0.10" charset = "0.1" percent-encoding = "2.0" diff --git a/src/imap.rs b/src/imap.rs index ef69ee2d4..59ca996b8 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -96,7 +96,7 @@ impl<'a> IdleHandle<'a> { } } - pub fn wait_keepalive(self) -> imap::error::Result<()> { + pub fn wait_keepalive(self) -> imap::error::Result { match self { IdleHandle::Secure(i) => i.wait_keepalive(), IdleHandle::Insecure(i) => i.wait_keepalive(), @@ -117,6 +117,7 @@ impl Client { let tls_stream = native_tls::TlsConnector::connect(&tls, domain.as_ref(), s)?; let mut client = imap::Client::new(tls_stream); + client.debug = true; client.read_greeting()?; Ok(Client::Secure(client, stream)) @@ -371,15 +372,18 @@ impl Imap { } fn setup_handle_if_needed(&self, context: &Context) -> bool { + println!("setup_handle_if_needed"); if self.config.read().unwrap().imap_server.is_empty() { return false; } if self.should_reconnect() { + println!("unsetup_handle"); self.unsetup_handle(context); } if self.is_connected() && self.stream.read().unwrap().is_some() { + println!("already connected"); self.should_reconnect.store(false, Ordering::Relaxed); return true; } @@ -392,6 +396,7 @@ impl Imap { let imap_server: &str = config.imap_server.as_ref(); let imap_port = config.imap_port; + println!("trying to connect insecure {}:{}", imap_server, imap_port); Client::connect_insecure((imap_server, imap_port)).and_then(|client| { if (server_flags & DC_LP_IMAP_SOCKET_STARTTLS) != 0 { client.secure(imap_server, config.certificate_checks) @@ -404,6 +409,7 @@ impl Imap { let imap_server: &str = config.imap_server.as_ref(); let imap_port = config.imap_port; + println!("trying to connect secure {}:{}", imap_server, imap_port); Client::connect_secure( (imap_server, imap_port), imap_server, @@ -666,9 +672,11 @@ impl Imap { if let Some(ref mut session) = &mut *self.session.lock().unwrap() { match session.select(folder) { Ok(mailbox) => { + println!("session.select returned"); let mut config = self.config.write().unwrap(); config.selected_folder = Some(folder.as_ref().to_string()); config.selected_mailbox = Some(mailbox); + println!("session.select ok-handling complete"); } Err(err) => { info!( @@ -733,6 +741,7 @@ impl Imap { return 0; } + println!("select_folder completed"); // compare last seen UIDVALIDITY against the current one let (mut uid_validity, mut last_seen_uid) = self.get_config_last_seen_uid(context, &folder); @@ -991,23 +1000,38 @@ impl Imap { std::thread::spawn(move || { let &(ref lock, ref cvar) = &*v; if let Some(ref mut session) = &mut *session.lock().unwrap() { - let mut idle = match session.idle() { - Ok(idle) => idle, - Err(err) => { - eprintln!("failed to setup idle: {:?}", err); - return; + loop { + let res = match session.idle() { + Ok(mut idle) => { + // most servers do not allow more than ~28 minutes; stay clearly below that. + // a good value that is also used by other MUAs is 23 minutes. + // if needed, the ui can call dc_imap_interrupt_idle() to trigger a reconnect. + // idle.set_keepalive(Duration::from_secs(23 * 60)); + idle.set_keepalive(Duration::from_secs(20)); + println!("entering idle wait_keepalive"); + idle.wait_keepalive() + } + Err(err) => { + sender.send(Err(imap::error::Error::Bad(err.to_string()))); + break; + } + }; + match res { + Ok(true) => { + println!("wait_keepalive returned data, idle-finished"); + sender.send(Ok(())); + break ; + } + Ok(false) => { + println!("wait_keepalive returned no data, let's re-enter idle"); + } + Err(err) => { + eprintln!("wait_keepalive returned error {} -- SHUTTING DOWN", err); + sender.send(Err(imap::error::Error::Bad("wait_keepalive failed".to_string()))); + break; + } } - }; - - // most servers do not allow more than ~28 minutes; stay clearly below that. - // a good value that is also used by other MUAs is 23 minutes. - // if needed, the ui can call dc_imap_interrupt_idle() to trigger a reconnect. - idle.set_keepalive(Duration::from_secs(23 * 60)); - let res = idle.wait_keepalive(); - - // Ignoring the error, as this happens when we try sending after the drop - let _send_res = sender.send(res); - + } // Trigger condvar let mut watch = lock.lock().unwrap(); *watch = true; @@ -1025,8 +1049,10 @@ impl Imap { info!(context, "IMAP-IDLE has data."); } Err(err) => match err { - imap::error::Error::Io(_) | imap::error::Error::ConnectionLost => { + imap::error::Error::Io(_) | imap::error::Error::ConnectionLost | imap::error::Error::Bad(_) => { info!(context, "IMAP-IDLE wait cancelled, we will reconnect soon."); + self.unsetup_handle(context); + info!(context, "IMAP-IDLE has SHUTDOWN"); self.should_reconnect.store(true, Ordering::Relaxed); } _ => { @@ -1083,6 +1109,7 @@ impl Imap { loop { let res = cvar.wait_timeout(watch, seconds_to_wait).unwrap(); + println!("returned wait_timeout"); watch = res.0; if *watch { do_fake_idle = false; @@ -1091,6 +1118,7 @@ impl Imap { break; } } + println!("fake-idle: wait_timeout finished"); *watch = false; @@ -1102,10 +1130,19 @@ impl Imap { // are also downloaded, however, typically this would take place in the FETCH command // following IDLE otherwise, so this seems okay here. if self.setup_handle_if_needed(context) { + let mut res: Option = None; if let Some(ref watch_folder) = self.config.read().unwrap().watch_folder { + res = Some(watch_folder.to_string()) + } + if let Some(watch_folder) = res { + println!("before fetch_from_single_folder"); if 0 != self.fetch_from_single_folder(context, watch_folder) { do_fake_idle = false; } + if self.is_connected() { + do_fake_idle = false; + } + println!("after fetch_from_single_folder do_fake_idle={}", do_fake_idle); } } else { // if we cannot connect, set the starting time to a small value which will