remove ok_to_continue and simplify/refactor imap and smtp connection trying

address @r10s review comments and also remove unneccessary "unsafe fn"
This commit is contained in:
holger krekel
2019-10-07 01:40:15 +02:00
parent ba5b3ad675
commit 7f5b362eda
4 changed files with 127 additions and 155 deletions

View File

@@ -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<LoginParam> = 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: {}", &param);
if context.inbox.read().unwrap().connect(context, &param) {
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: {}", &param);
if context.inbox.read().unwrap().connect(context, &param) {
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: {}", &param);
if context.inbox.read().unwrap().connect(context, &param) {
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, &param)
{
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: {}", &param);
if !context
.smtp
.clone()
.lock()
.unwrap()
.connect(context, &param)
{
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: {}", &param);
if !context
.smtp
.clone()
.lock()
.unwrap()
.connect(context, &param)
{
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<bool> {
if let Some(res) = try_imap_one_param(context, &param) {
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, &param) {
return Some(res);
}
progress!(context, if success { 1000 } else { 0 });
progress!(context, 660 + variation * 30);
param.mail_port = 143;
try_imap_one_param(context, &param)
}
fn try_imap_one_param(context: &Context, param: &LoginParam) -> Option<bool> {
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, &param) {
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, &param) {
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, &param) {
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, &param) {
return res
}
false
}
fn try_smtp_one_param(context: &Context, param: &LoginParam, ) -> Option<bool> {
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, &param) {
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);
}
}

View File

@@ -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 =

View File

@@ -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<Client> =
if (server_flags & (DC_LP_IMAP_SOCKET_STARTTLS | DC_LP_IMAP_SOCKET_PLAIN)) != 0 {

View File

@@ -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) => {