fetching works

This commit is contained in:
dignifiedquire
2019-05-04 17:09:08 +02:00
committed by Lars-Magnus Skog
parent 2fd38cd533
commit 67f1d67de7

View File

@@ -11,7 +11,8 @@ use crate::dc_loginparam::*;
use crate::dc_sqlite3::*; use crate::dc_sqlite3::*;
use crate::dc_tools::*; use crate::dc_tools::*;
use crate::types::*; use crate::types::*;
use crate::x::*;
pub const DC_IMAP_SEEN: usize = 0x0001;
#[repr(C)] #[repr(C)]
pub struct dc_imap_t { pub struct dc_imap_t {
@@ -213,9 +214,9 @@ impl Default for ImapConfig {
skip_log_capabilities: 0, skip_log_capabilities: 0,
}; };
// prefetch: UID, Envelope, // prefetch: UID, ENVELOPE,
// new: body, body_peek_section // new: FLAGS BODY.PEEK[]
// flags: flags // flags: FLAGS
cfg cfg
} }
@@ -562,41 +563,13 @@ impl dc_imap_t {
return 0; return 0;
} }
if let Some(ref mut session) = *self.session.lock().unwrap() { let list = if let Some(ref mut session) = *self.session.lock().unwrap() {
// `FETCH <message sequence number> (UID)` // `FETCH <message sequence number> (UID)`
let set = format!("{}", mailbox.exists); let set = format!("{}", mailbox.exists);
let query = "(UID ENVELOPE)"; let query = "(UID ENVELOPE)";
println!("fetching: {} {}", set, query); println!("fetching: {} {}", set, query);
match session.fetch(set, query) { match session.fetch(set, query) {
Ok(list) => { Ok(list) => list,
println!("fetched {} messages", list.len());
last_seen_uid = list[0].uid.unwrap_or_else(|| 0);
// if the UIDVALIDITY has _changed_, decrease lastseenuid by one to avoid gaps (well add 1 below
if uid_validity > 0 && last_seen_uid > 1 {
last_seen_uid -= 1;
}
uid_validity = mailbox.uid_validity.unwrap();
self.set_config_last_seen_uid(
context,
&folder,
uid_validity,
last_seen_uid,
);
unsafe {
dc_log_info(
context,
0,
b"lastseenuid initialized to %i for %s@%i\x00" as *const u8
as *const libc::c_char,
last_seen_uid as libc::c_int,
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
uid_validity as libc::c_int,
);
}
}
Err(err) => { Err(err) => {
eprintln!("fetch error: {:?}", err); eprintln!("fetch error: {:?}", err);
unsafe { unsafe {
@@ -611,6 +584,30 @@ impl dc_imap_t {
return 0; return 0;
} }
} }
} else {
return 0;
};
println!("fetched {} messages", list.len());
last_seen_uid = list[0].uid.unwrap_or_else(|| 0);
// if the UIDVALIDITY has _changed_, decrease lastseenuid by one to avoid gaps (well add 1 below
if uid_validity > 0 && last_seen_uid > 1 {
last_seen_uid -= 1;
}
uid_validity = mailbox.uid_validity.unwrap();
self.set_config_last_seen_uid(context, &folder, uid_validity, last_seen_uid);
unsafe {
dc_log_info(
context,
0,
b"lastseenuid initialized to %i for %s@%i\x00" as *const u8
as *const libc::c_char,
last_seen_uid as libc::c_int,
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
uid_validity as libc::c_int,
);
} }
} }
@@ -618,19 +615,23 @@ impl dc_imap_t {
let mut read_errors = 0; let mut read_errors = 0;
let mut new_last_seen_uid = 0; let mut new_last_seen_uid = 0;
if let Some(ref mut session) = *self.session.lock().unwrap() { let list = if let Some(ref mut session) = *self.session.lock().unwrap() {
// fetch messages with larger UID than the last one seen // fetch messages with larger UID than the last one seen
// (`UID FETCH lastseenuid+1:*)`, see RFC 4549 // (`UID FETCH lastseenuid+1:*)`, see RFC 4549
let set = format!("{}:*", last_seen_uid + 1); let set = format!("{}:*", last_seen_uid + 1);
let query = "(UID ENVELOPE)"; let query = "(UID ENVELOPE)";
println!("fetching: {} {}", set, query); println!("fetching: {} {}", set, query);
let list = match session.uid_fetch(set, query) { match session.uid_fetch(set, query) {
Ok(list) => list, Ok(list) => list,
Err(err) => { Err(err) => {
eprintln!("fetch err: {:?}", err); eprintln!("fetch err: {:?}", err);
return 0; return 0;
} }
}
} else {
return 0;
}; };
println!("fetched {} messages", list.len()); println!("fetched {} messages", list.len());
// go through all mails in folder (this is typically _fast_ as we already have the whole list) // go through all mails in folder (this is typically _fast_ as we already have the whole list)
@@ -648,12 +649,7 @@ impl dc_imap_t {
let message_id_c = CString::new(message_id).unwrap(); let message_id_c = CString::new(message_id).unwrap();
let folder_c = CString::new(folder.as_ref().to_owned()).unwrap(); let folder_c = CString::new(folder.as_ref().to_owned()).unwrap();
if 0 == unsafe { if 0 == unsafe {
(self.precheck_imf)( (self.precheck_imf)(context, message_id_c.as_ptr(), folder_c.as_ptr(), cur_uid)
context,
message_id_c.as_ptr(),
folder_c.as_ptr(),
cur_uid,
)
} { } {
// check passed, go fetch the rest // check passed, go fetch the rest
if self.fetch_single_msg(context, &folder, cur_uid) == 0 { if self.fetch_single_msg(context, &folder, cur_uid) == 0 {
@@ -688,7 +684,6 @@ impl dc_imap_t {
} }
} }
} }
}
if 0 == read_errors && new_last_seen_uid > 0 { if 0 == read_errors && new_last_seen_uid > 0 {
// TODO: it might be better to increase the lastseenuid also on partial errors. // TODO: it might be better to increase the lastseenuid also on partial errors.
@@ -748,98 +743,103 @@ impl dc_imap_t {
folder: S, folder: S,
server_uid: u32, server_uid: u32,
) -> usize { ) -> usize {
unimplemented!();
}
// let mut msg_att: *mut mailimap_msg_att = 0 as *mut mailimap_msg_att;
// /* the function returns: // /* the function returns:
// 0 the caller should try over again later // 0 the caller should try over again later
// or 1 if the messages should be treated as received, the caller should not try to read the message again (even if no database entries are returned) */ // or 1 if the messages should be treated as received, the caller should not try to read the message again (even if no database entries are returned) */
// let mut msg_content: *mut libc::c_char = 0 as *mut libc::c_char; if !self.is_connected() {
// let mut msg_bytes: size_t = 0 as size_t; return 0;
// let mut r: libc::c_int = 0; }
// let mut retry_later: libc::c_int = 0;
// let mut deleted: libc::c_int = 0;
// let mut flags: uint32_t = 0 as uint32_t;
// let mut fetch_result: *mut clist = 0 as *mut clist;
// let mut cur: *mut clistiter = 0 as *mut clistiter;
// if !imap.etpan.is_null() {
// let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid);
// r = mailimap_uid_fetch(imap.etpan, set, imap.fetch_type_body, &mut fetch_result);
// if !set.is_null() {
// mailimap_set_free(set);
// set = 0 as *mut mailimap_set
// }
// if 0 != dc_imap_is_error(context, imap, r) || fetch_result.is_null() {
// fetch_result = 0 as *mut clist;
// dc_log_warning(
// context,
// 0,
// b"Error #%i on fetching message #%i from folder \"%s\"; retry=%i.\x00"
// as *const u8 as *const libc::c_char,
// r as libc::c_int,
// server_uid as libc::c_int,
// folder,
// imap.should_reconnect as libc::c_int,
// );
// if 0 != imap.should_reconnect {
// retry_later = 1
// }
// } else {
// /* this is an error that should be recovered; the caller should try over later to fetch the message again (if there is no such message, we simply get an empty result) */
// cur = (*fetch_result).first;
// if cur.is_null() {
// dc_log_warning(
// context,
// 0,
// b"Message #%i does not exist in folder \"%s\".\x00" as *const u8
// as *const libc::c_char,
// server_uid as libc::c_int,
// folder,
// );
// } else {
// /* server response is fine, however, there is no such message, do not try to fetch the message again */
// msg_att = (if !cur.is_null() {
// (*cur).data
// } else {
// 0 as *mut libc::c_void
// }) as *mut mailimap_msg_att;
// peek_body(
// msg_att,
// &mut msg_content,
// &mut msg_bytes,
// &mut flags,
// &mut deleted,
// );
// if !(msg_content.is_null() || msg_bytes <= 0 || 0 != deleted) {
// /* dc_log_warning(imap->context, 0, "Message #%i in folder \"%s\" is empty or deleted.", (int)server_uid, folder); -- this is a quite usual situation, do not print a warning */
// imap.receive_imf.expect("non-null function pointer")(
// context,
// msg_content,
// msg_bytes,
// folder,
// server_uid,
// flags,
// );
// }
// }
// }
// }
// if !fetch_result.is_null() { let mut retry_later = false;
// mailimap_fetch_list_free(fetch_result);
// fetch_result = 0 as *mut clist let msgs = if let Some(ref mut session) = *self.session.lock().unwrap() {
// } let set = format!("{}", server_uid);
// if 0 != retry_later { let query = "(FLAGS BODY.PEEK[])";
// 0 match session.uid_fetch(set, query) {
// } else { Ok(msgs) => msgs,
// 1 Err(err) => {
// } eprintln!("error fetch single: {:?}", err);
// } unsafe {
dc_log_warning(
context,
0,
b"Error on fetching message #%i from folder \"%s\"; retry=%i.\x00"
as *const u8 as *const libc::c_char,
server_uid as libc::c_int,
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
self.should_reconnect() as libc::c_int,
)
};
if self.should_reconnect() {
retry_later = true;
}
return if retry_later { 0 } else { 1 };
}
}
} else {
return if retry_later { 0 } else { 1 };
};
if msgs.is_empty() {
unsafe {
dc_log_warning(
context,
0,
b"Message #%i does not exist in folder \"%s\".\x00" as *const u8
as *const libc::c_char,
server_uid as libc::c_int,
CString::new(folder.as_ref().to_owned()).unwrap().as_ptr(),
)
};
} else {
let msg = &msgs[0];
let is_deleted = msg
.flags()
.iter()
.find(|flag| match flag {
imap::types::Flag::Deleted => true,
_ => false,
})
.is_some();
let is_seen = msg
.flags()
.iter()
.find(|flag| match flag {
imap::types::Flag::Seen => true,
_ => false,
})
.is_some();
let flags = if is_seen { DC_IMAP_SEEN } else { 0 };
if !is_deleted && msg.body().is_some() {
unsafe {
let folder_c = CString::new(folder.as_ref().to_owned()).unwrap();
(self.receive_imf)(
context,
msg.body().unwrap().as_ptr() as *const libc::c_char,
msg.body().unwrap().len(),
folder_c.as_ptr(),
server_uid,
flags as u32,
);
}
}
}
if retry_later {
0
} else {
1
}
}
pub fn idle(&self, context: &dc_context_t) { pub fn idle(&self, context: &dc_context_t) {
// unimplemented!() // unimplemented!()
println!("starting to idle"); println!("starting to idle");
}
// let mut current_block: u64; // let mut current_block: u64;
// let mut r: libc::c_int = 0; // let mut r: libc::c_int = 0;
// let mut r2: libc::c_int = 0; // let mut r2: libc::c_int = 0;
@@ -938,10 +938,10 @@ impl dc_imap_t {
// fake_idle(context, imap); // fake_idle(context, imap);
// } // }
// } // }
}
fn fake_idle(&self, context: &dc_context_t) { fn fake_idle(&self, context: &dc_context_t) {
unimplemented!(); unimplemented!();
}
// /* Idle using timeouts. This is also needed if we're not yet configured - // /* Idle using timeouts. This is also needed if we're not yet configured -
// in this case, we're waiting for a configure job */ // in this case, we're waiting for a configure job */
// let mut fake_idle_start_time = SystemTime::now(); // let mut fake_idle_start_time = SystemTime::now();
@@ -986,11 +986,11 @@ impl dc_imap_t {
// } // }
// } // }
// } // }
}
pub fn interrupt_idle(&self) { pub fn interrupt_idle(&self) {
// unimplemented!(); // unimplemented!();
println!("interrupt idle"); println!("interrupt idle");
}
// println!("imap interrupt"); // println!("imap interrupt");
// if 0 != imap.can_idle { // if 0 != imap.can_idle {
@@ -1006,7 +1006,7 @@ impl dc_imap_t {
// *watch = true; // *watch = true;
// println!("notify"); // println!("notify");
// cvar.notify_one(); // cvar.notify_one();
// } }
pub fn mv( pub fn mv(
&self, &self,
@@ -1017,7 +1017,6 @@ impl dc_imap_t {
dest_uid: *mut uint32_t, dest_uid: *mut uint32_t,
) -> dc_imap_res { ) -> dc_imap_res {
unimplemented!() unimplemented!()
}
// let mut current_block: u64; // let mut current_block: u64;
// let mut res: dc_imap_res = DC_RETRY_LATER; // let mut res: dc_imap_res = DC_RETRY_LATER;
// let mut r: libc::c_int = 0; // let mut r: libc::c_int = 0;
@@ -1158,11 +1157,10 @@ impl dc_imap_t {
// } else { // } else {
// res as libc::c_uint // res as libc::c_uint
// }) as dc_imap_res; // }) as dc_imap_res;
// } }
fn add_flag(&self, server_uid: uint32_t, flag: *mut mailimap_flag) -> usize { fn add_flag(&self, server_uid: uint32_t, flag: *mut mailimap_flag) -> usize {
unimplemented!() unimplemented!()
}
// let mut flag_list: *mut mailimap_flag_list = 0 as *mut mailimap_flag_list; // let mut flag_list: *mut mailimap_flag_list = 0 as *mut mailimap_flag_list;
// let mut store_att_flags: *mut mailimap_store_att_flags = 0 as *mut mailimap_store_att_flags; // let mut store_att_flags: *mut mailimap_store_att_flags = 0 as *mut mailimap_store_att_flags;
// let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid); // let mut set: *mut mailimap_set = mailimap_set_new_single(server_uid);
@@ -1184,7 +1182,7 @@ impl dc_imap_t {
// } else { // } else {
// 1 // 1
// } // }
// } }
pub fn set_seen( pub fn set_seen(
&self, &self,
@@ -1193,7 +1191,6 @@ impl dc_imap_t {
uid: uint32_t, uid: uint32_t,
) -> dc_imap_res { ) -> dc_imap_res {
unimplemented!() unimplemented!()
}
// let mut res: dc_imap_res = DC_RETRY_LATER; // let mut res: dc_imap_res = DC_RETRY_LATER;
// if folder.is_null() || uid == 0 as libc::c_uint { // if folder.is_null() || uid == 0 as libc::c_uint {
// res = DC_FAILED // res = DC_FAILED
@@ -1232,7 +1229,7 @@ impl dc_imap_t {
// } else { // } else {
// res as libc::c_uint // res as libc::c_uint
// }) as dc_imap_res; // }) as dc_imap_res;
// } }
pub fn set_mdnsent( pub fn set_mdnsent(
&self, &self,
@@ -1241,8 +1238,6 @@ impl dc_imap_t {
uid: uint32_t, uid: uint32_t,
) -> dc_imap_res { ) -> dc_imap_res {
unimplemented!(); unimplemented!();
}
// let mut can_create_flag: libc::c_int = 0; // let mut can_create_flag: libc::c_int = 0;
// let mut current_block: u64; // let mut current_block: u64;
// // returns 0=job should be retried later, 1=job done, 2=job done and flag just set // // returns 0=job should be retried later, 1=job done, 2=job done and flag just set
@@ -1399,7 +1394,7 @@ impl dc_imap_t {
// } else { // } else {
// res as libc::c_uint // res as libc::c_uint
// }) as dc_imap_res // }) as dc_imap_res
// } }
// only returns 0 on connection problems; we should try later again in this case * // only returns 0 on connection problems; we should try later again in this case *
pub fn delete_msg( pub fn delete_msg(
@@ -1410,7 +1405,6 @@ impl dc_imap_t {
mut server_uid: uint32_t, mut server_uid: uint32_t,
) -> libc::c_int { ) -> libc::c_int {
unimplemented!() unimplemented!()
}
// let mut success: libc::c_int = 0; // let mut success: libc::c_int = 0;
// let mut r: libc::c_int = 0; // let mut r: libc::c_int = 0;
// let mut fetch_result: *mut clist = 0 as *mut clist; // let mut fetch_result: *mut clist = 0 as *mut clist;
@@ -1521,7 +1515,7 @@ impl dc_imap_t {
// } else { // } else {
// dc_imap_is_connected(imap) // dc_imap_is_connected(imap)
// } // }
// } }
pub fn configure_folders(&self, context: &dc_context_t, flags: libc::c_int) { pub fn configure_folders(&self, context: &dc_context_t, flags: libc::c_int) {
if !self.is_connected() { if !self.is_connected() {