diff --git a/src/configure/mod.rs b/src/configure/mod.rs index c5afda852..5a0b08e60 100644 --- a/src/configure/mod.rs +++ b/src/configure/mod.rs @@ -46,18 +46,22 @@ pub fn dc_is_configured(context: &Context) -> bool { ******************************************************************************/ // the other dc_job_do_DC_JOB_*() functions are declared static in the c-file #[allow(non_snake_case, unused_must_use)] -pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) { +pub fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) { + if !context.sql.is_open() { + error!(context, "Cannot configure, database not opened.",); + progress!(context, 0); + return + } + if !context.alloc_ongoing() { + progress!(context, 0); + return + } let mut success = false; let mut imap_connected_here = false; let mut smtp_connected_here = false; - let mut ongoing_allocated_here = false; let mut param_autoconfig: Option = None; - if context.alloc_ongoing() { - ongoing_allocated_here = true; - if !context.sql.is_open() { - error!(context, "Cannot configure, database not opened.",); - } else { + context.inbox.read().unwrap().disconnect(context); context .sentbox_thread @@ -337,140 +341,13 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) { progress!(context, 600); /* try to connect to IMAP - if we did not got an autoconfig, do some further tries with different settings and username variations */ - let ok_to_continue8; - let mut username_variation = 0; - loop { - if !(username_variation <= 1) { - ok_to_continue8 = true; - break; - } - info!(context, "Trying: {}", ¶m); - - if context.inbox.read().unwrap().connect(context, ¶m) { - ok_to_continue8 = true; - break; - } - if param_autoconfig.is_some() { - ok_to_continue8 = false; - break; - } - // probe STARTTLS/993 - if context.shall_stop_ongoing() { - ok_to_continue8 = false; - break; - } - progress!(context, 650 + username_variation * 30); - param.server_flags &= !(0x100 | 0x200 | 0x400); - param.server_flags |= 0x100; - info!(context, "Trying: {}", ¶m); - - if context.inbox.read().unwrap().connect(context, ¶m) { - ok_to_continue8 = true; - break; - } - // probe STARTTLS/143 - if context.shall_stop_ongoing() { - ok_to_continue8 = false; - break; - } - progress!(context, 660 + username_variation * 30); - param.mail_port = 143; - info!(context, "Trying: {}", ¶m); - - if context.inbox.read().unwrap().connect(context, ¶m) { - ok_to_continue8 = true; - break; - } - if 0 != username_variation { - ok_to_continue8 = false; - break; - } - // next probe round with only the localpart of the email-address as the loginname - if context.shall_stop_ongoing() { - ok_to_continue8 = false; - break; - } - progress!(context, 670 + username_variation * 30); - param.server_flags &= !(0x100 | 0x200 | 0x400); - param.server_flags |= 0x200; - param.mail_port = 993; - - if let Some(at) = param.mail_user.find('@') { - param.mail_user = param.mail_user.split_at(at).0.to_string(); - } - if let Some(at) = param.send_user.find('@') { - param.send_user = param.send_user.split_at(at).0.to_string(); - } - - username_variation += 1 - } - if ok_to_continue8 { - // success, so we are connected and should disconnect in cleanup - imap_connected_here = true; - } - ok_to_continue8 + imap_connected_here = try_imap_connections(context, &mut param, param_autoconfig.is_some()); + imap_connected_here } 15 => { progress!(context, 800); - let success; - /* try to connect to SMTP - if we did not got an autoconfig, the first try was SSL-465 and we do a second try with STARTTLS-587 */ - if !context - .smtp - .clone() - .lock() - .unwrap() - .connect(context, ¶m) - { - if param_autoconfig.is_some() { - success = false; - } else if context.shall_stop_ongoing() { - success = false; - } else { - progress!(context, 850); - param.server_flags &= !(DC_LP_SMTP_SOCKET_FLAGS as i32); - param.server_flags |= DC_LP_SMTP_SOCKET_STARTTLS as i32; - param.send_port = 587; - info!(context, "Trying: {}", ¶m); - - if !context - .smtp - .clone() - .lock() - .unwrap() - .connect(context, ¶m) - { - if context.shall_stop_ongoing() { - success = false; - } else { - progress!(context, 860); - param.server_flags &= !(DC_LP_SMTP_SOCKET_FLAGS as i32); - param.server_flags |= DC_LP_SMTP_SOCKET_STARTTLS as i32; - param.send_port = 25; - info!(context, "Trying: {}", ¶m); - - if !context - .smtp - .clone() - .lock() - .unwrap() - .connect(context, ¶m) - { - success = false; - } else { - success = true; - } - } - } else { - success = true; - } - } - } else { - success = true; - } - if success { - smtp_connected_here = true; - } - success + smtp_connected_here = try_smtp_connections(context, &mut param, param_autoconfig.is_some()); + smtp_connected_here } 16 => { progress!(context, 900); @@ -523,8 +400,6 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) { break; } } - } - } if imap_connected_here { context.inbox.read().unwrap().disconnect(context); } @@ -549,11 +424,110 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context) { ); } */ - if ongoing_allocated_here { - context.free_ongoing(); + context.free_ongoing(); + progress!(context, if success { 1000 } else { 0 }); +} + +fn try_imap_connections(context: &Context, mut param: &mut LoginParam, was_autoconfig: bool) -> bool { + // progress 650 and 660 + if let Some(res) = try_imap_connection(context, &mut param, was_autoconfig, 0) { + return res; + } + progress!(context, 670); + param.server_flags &= !(DC_LP_IMAP_SOCKET_FLAGS); + param.server_flags |= DC_LP_IMAP_SOCKET_SSL; + param.mail_port = 993; + + if let Some(at) = param.mail_user.find('@') { + param.mail_user = param.mail_user.split_at(at).0.to_string(); + } + if let Some(at) = param.send_user.find('@') { + param.send_user = param.send_user.split_at(at).0.to_string(); + } + // progress 680 and 690 + if let Some(res) = try_imap_connection(context, &mut param, was_autoconfig, 1) { + res + } else { + false + } +} + +fn try_imap_connection(context: &Context, param: &mut LoginParam, was_autoconfig: bool, variation: usize) -> Option { + if let Some(res) = try_imap_one_param(context, ¶m) { + return Some(res); + } + if was_autoconfig { + return Some(false); + } + progress!(context, 650 + variation * 30); + param.server_flags &= !(DC_LP_IMAP_SOCKET_FLAGS); + param.server_flags |= DC_LP_IMAP_SOCKET_STARTTLS; + if let Some(res) = try_imap_one_param(context, ¶m) { + return Some(res); } - progress!(context, if success { 1000 } else { 0 }); + progress!(context, 660 + variation * 30); + param.mail_port = 143; + + try_imap_one_param(context, ¶m) +} + +fn try_imap_one_param(context: &Context, param: &LoginParam) -> Option { + let inf = format!( + "imap: {}@{}:{} flags=0x{:x}", + param.mail_user, param.mail_server, param.mail_port, param.server_flags); + info!(context, "Trying: {}", inf); + if context.inbox.read().unwrap().connect(context, ¶m) { + info!(context, "success: {}", inf); + return Some(true); + } + if context.shall_stop_ongoing() { + return Some(false); + } + info!(context, "Could not connect: {}", inf); + None +} + +fn try_smtp_connections(context: &Context, mut param: &mut LoginParam, was_autoconfig: bool) -> bool { + /* try to connect to SMTP - if we did not got an autoconfig, the first try was SSL-465 and we do a second try with STARTTLS-587 */ + if let Some(res) = try_smtp_one_param(context, ¶m) { + return res + } + if was_autoconfig { + return false; + } + progress!(context, 850); + param.server_flags &= !(DC_LP_SMTP_SOCKET_FLAGS as i32); + param.server_flags |= DC_LP_SMTP_SOCKET_STARTTLS as i32; + param.send_port = 587; + + if let Some(res) = try_smtp_one_param(context, ¶m) { + return res + } + progress!(context, 860); + param.server_flags &= !(DC_LP_SMTP_SOCKET_FLAGS as i32); + param.server_flags |= DC_LP_SMTP_SOCKET_STARTTLS as i32; + param.send_port = 25; + if let Some(res) = try_smtp_one_param(context, ¶m) { + return res + } + false +} + +fn try_smtp_one_param(context: &Context, param: &LoginParam, ) -> Option { + let inf = format!( + "smtp: {}@{}:{} flags: 0x{:x}", + param.send_user, param.send_server, param.send_port, param.server_flags); + info!(context, "Trying: {}", inf); + if context.smtp.clone().lock().unwrap().connect(context, ¶m) { + info!(context, "success: {}", inf); + return Some(true); + } + if context.shall_stop_ongoing() { + return Some(false) + } + info!(context, "could not connect: {}", inf); + None } /******************************************************************************* @@ -613,8 +587,6 @@ mod tests { .set_config(Config::Addr, Some("probably@unexistant.addr")) .unwrap(); t.ctx.set_config(Config::MailPw, Some("123456")).unwrap(); - unsafe { - dc_job_do_DC_JOB_CONFIGURE_IMAP(&t.ctx); - } + dc_job_do_DC_JOB_CONFIGURE_IMAP(&t.ctx); } } diff --git a/src/constants.rs b/src/constants.rs index fdc80be91..309379abf 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -129,23 +129,23 @@ pub const DC_CREATE_MVBOX: usize = 1; /// Force OAuth2 authorization. This flag does not skip automatic configuration. /// Before calling configure() with DC_LP_AUTH_OAUTH2 set, /// the user has to confirm access at the URL returned by dc_get_oauth2_url(). -pub const DC_LP_AUTH_OAUTH2: usize = 0x2; +pub const DC_LP_AUTH_OAUTH2: i32 = 0x2; /// Force NORMAL authorization, this is the default. /// If this flag is set, automatic configuration is skipped. -pub const DC_LP_AUTH_NORMAL: usize = 0x4; +pub const DC_LP_AUTH_NORMAL: i32 = 0x4; /// Connect to IMAP via STARTTLS. /// If this flag is set, automatic configuration is skipped. -pub const DC_LP_IMAP_SOCKET_STARTTLS: usize = 0x100; +pub const DC_LP_IMAP_SOCKET_STARTTLS: i32 = 0x100; /// Connect to IMAP via SSL. /// If this flag is set, automatic configuration is skipped. -pub const DC_LP_IMAP_SOCKET_SSL: usize = 0x200; +pub const DC_LP_IMAP_SOCKET_SSL: i32 = 0x200; /// Connect to IMAP unencrypted, this should not be used. /// If this flag is set, automatic configuration is skipped. -pub const DC_LP_IMAP_SOCKET_PLAIN: usize = 0x400; +pub const DC_LP_IMAP_SOCKET_PLAIN: i32 = 0x400; /// Connect to SMTP via STARTTLS. /// If this flag is set, automatic configuration is skipped. @@ -160,9 +160,9 @@ pub const DC_LP_SMTP_SOCKET_SSL: usize = 0x20000; pub const DC_LP_SMTP_SOCKET_PLAIN: usize = 0x40000; /// if none of these flags are set, the default is chosen -pub const DC_LP_AUTH_FLAGS: usize = (DC_LP_AUTH_OAUTH2 | DC_LP_AUTH_NORMAL); +pub const DC_LP_AUTH_FLAGS: i32 = (DC_LP_AUTH_OAUTH2 | DC_LP_AUTH_NORMAL); /// if none of these flags are set, the default is chosen -pub const DC_LP_IMAP_SOCKET_FLAGS: usize = +pub const DC_LP_IMAP_SOCKET_FLAGS: i32 = (DC_LP_IMAP_SOCKET_STARTTLS | DC_LP_IMAP_SOCKET_SSL | DC_LP_IMAP_SOCKET_PLAIN); /// if none of these flags are set, the default is chosen pub const DC_LP_SMTP_SOCKET_FLAGS: usize = diff --git a/src/imap.rs b/src/imap.rs index bdd54e506..f45529adf 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -384,7 +384,7 @@ impl Imap { return true; } - let server_flags = self.config.read().unwrap().server_flags; + let server_flags = self.config.read().unwrap().server_flags as i32; let connection_res: imap::error::Result = if (server_flags & (DC_LP_IMAP_SOCKET_STARTTLS | DC_LP_IMAP_SOCKET_PLAIN)) != 0 { diff --git a/src/job.rs b/src/job.rs index af36a6171..4d238ee67 100644 --- a/src/job.rs +++ b/src/job.rs @@ -781,7 +781,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) { Action::MarkseenMdnOnImap => job.do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context), Action::MoveMsg => job.do_DC_JOB_MOVE_MSG(context), Action::SendMdn => job.do_DC_JOB_SEND(context), - Action::ConfigureImap => unsafe { dc_job_do_DC_JOB_CONFIGURE_IMAP(context) }, + Action::ConfigureImap => dc_job_do_DC_JOB_CONFIGURE_IMAP(context), Action::ImexImap => match job_do_DC_JOB_IMEX_IMAP(context, &job) { Ok(()) => {} Err(err) => {