mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +03:00
fetching works
This commit is contained in:
committed by
Lars-Magnus Skog
parent
2fd38cd533
commit
67f1d67de7
276
src/dc_imap.rs
276
src/dc_imap.rs
@@ -11,7 +11,8 @@ use crate::dc_loginparam::*;
|
||||
use crate::dc_sqlite3::*;
|
||||
use crate::dc_tools::*;
|
||||
use crate::types::*;
|
||||
use crate::x::*;
|
||||
|
||||
pub const DC_IMAP_SEEN: usize = 0x0001;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct dc_imap_t {
|
||||
@@ -213,9 +214,9 @@ impl Default for ImapConfig {
|
||||
skip_log_capabilities: 0,
|
||||
};
|
||||
|
||||
// prefetch: UID, Envelope,
|
||||
// new: body, body_peek_section
|
||||
// flags: flags
|
||||
// prefetch: UID, ENVELOPE,
|
||||
// new: FLAGS BODY.PEEK[]
|
||||
// flags: FLAGS
|
||||
|
||||
cfg
|
||||
}
|
||||
@@ -562,41 +563,13 @@ impl dc_imap_t {
|
||||
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)`
|
||||
let set = format!("{}", mailbox.exists);
|
||||
let query = "(UID ENVELOPE)";
|
||||
println!("fetching: {} {}", set, query);
|
||||
match session.fetch(set, query) {
|
||||
Ok(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,
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(list) => list,
|
||||
Err(err) => {
|
||||
eprintln!("fetch error: {:?}", err);
|
||||
unsafe {
|
||||
@@ -611,6 +584,30 @@ impl dc_imap_t {
|
||||
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 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
|
||||
// (`UID FETCH lastseenuid+1:*)`, see RFC 4549
|
||||
let set = format!("{}:*", last_seen_uid + 1);
|
||||
let query = "(UID ENVELOPE)";
|
||||
println!("fetching: {} {}", set, query);
|
||||
let list = match session.uid_fetch(set, query) {
|
||||
match session.uid_fetch(set, query) {
|
||||
Ok(list) => list,
|
||||
Err(err) => {
|
||||
eprintln!("fetch err: {:?}", err);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
println!("fetched {} messages", list.len());
|
||||
// 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 folder_c = CString::new(folder.as_ref().to_owned()).unwrap();
|
||||
if 0 == unsafe {
|
||||
(self.precheck_imf)(
|
||||
context,
|
||||
message_id_c.as_ptr(),
|
||||
folder_c.as_ptr(),
|
||||
cur_uid,
|
||||
)
|
||||
(self.precheck_imf)(context, message_id_c.as_ptr(), folder_c.as_ptr(), cur_uid)
|
||||
} {
|
||||
// check passed, go fetch the rest
|
||||
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 {
|
||||
// TODO: it might be better to increase the lastseenuid also on partial errors.
|
||||
@@ -748,98 +743,103 @@ impl dc_imap_t {
|
||||
folder: S,
|
||||
server_uid: u32,
|
||||
) -> usize {
|
||||
unimplemented!();
|
||||
}
|
||||
// let mut msg_att: *mut mailimap_msg_att = 0 as *mut mailimap_msg_att;
|
||||
// /* the function returns:
|
||||
// 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) */
|
||||
// let mut msg_content: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||
// let mut msg_bytes: size_t = 0 as size_t;
|
||||
// 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 !self.is_connected() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if !fetch_result.is_null() {
|
||||
// mailimap_fetch_list_free(fetch_result);
|
||||
// fetch_result = 0 as *mut clist
|
||||
// }
|
||||
// if 0 != retry_later {
|
||||
// 0
|
||||
// } else {
|
||||
// 1
|
||||
// }
|
||||
// }
|
||||
let mut retry_later = false;
|
||||
|
||||
let msgs = if let Some(ref mut session) = *self.session.lock().unwrap() {
|
||||
let set = format!("{}", server_uid);
|
||||
let query = "(FLAGS BODY.PEEK[])";
|
||||
match session.uid_fetch(set, query) {
|
||||
Ok(msgs) => msgs,
|
||||
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) {
|
||||
// unimplemented!()
|
||||
println!("starting to idle");
|
||||
}
|
||||
// let mut current_block: u64;
|
||||
// let mut r: libc::c_int = 0;
|
||||
// let mut r2: libc::c_int = 0;
|
||||
@@ -938,10 +938,10 @@ impl dc_imap_t {
|
||||
// fake_idle(context, imap);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
fn fake_idle(&self, context: &dc_context_t) {
|
||||
unimplemented!();
|
||||
}
|
||||
// /* Idle using timeouts. This is also needed if we're not yet configured -
|
||||
// in this case, we're waiting for a configure job */
|
||||
// let mut fake_idle_start_time = SystemTime::now();
|
||||
@@ -986,11 +986,11 @@ impl dc_imap_t {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn interrupt_idle(&self) {
|
||||
// unimplemented!();
|
||||
println!("interrupt idle");
|
||||
}
|
||||
|
||||
// println!("imap interrupt");
|
||||
// if 0 != imap.can_idle {
|
||||
@@ -1006,7 +1006,7 @@ impl dc_imap_t {
|
||||
// *watch = true;
|
||||
// println!("notify");
|
||||
// cvar.notify_one();
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn mv(
|
||||
&self,
|
||||
@@ -1017,7 +1017,6 @@ impl dc_imap_t {
|
||||
dest_uid: *mut uint32_t,
|
||||
) -> dc_imap_res {
|
||||
unimplemented!()
|
||||
}
|
||||
// let mut current_block: u64;
|
||||
// let mut res: dc_imap_res = DC_RETRY_LATER;
|
||||
// let mut r: libc::c_int = 0;
|
||||
@@ -1158,11 +1157,10 @@ impl dc_imap_t {
|
||||
// } else {
|
||||
// res as libc::c_uint
|
||||
// }) as dc_imap_res;
|
||||
// }
|
||||
}
|
||||
|
||||
fn add_flag(&self, server_uid: uint32_t, flag: *mut mailimap_flag) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
// 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 set: *mut mailimap_set = mailimap_set_new_single(server_uid);
|
||||
@@ -1184,7 +1182,7 @@ impl dc_imap_t {
|
||||
// } else {
|
||||
// 1
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn set_seen(
|
||||
&self,
|
||||
@@ -1193,7 +1191,6 @@ impl dc_imap_t {
|
||||
uid: uint32_t,
|
||||
) -> dc_imap_res {
|
||||
unimplemented!()
|
||||
}
|
||||
// let mut res: dc_imap_res = DC_RETRY_LATER;
|
||||
// if folder.is_null() || uid == 0 as libc::c_uint {
|
||||
// res = DC_FAILED
|
||||
@@ -1232,7 +1229,7 @@ impl dc_imap_t {
|
||||
// } else {
|
||||
// res as libc::c_uint
|
||||
// }) as dc_imap_res;
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn set_mdnsent(
|
||||
&self,
|
||||
@@ -1241,8 +1238,6 @@ impl dc_imap_t {
|
||||
uid: uint32_t,
|
||||
) -> dc_imap_res {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// let mut can_create_flag: libc::c_int = 0;
|
||||
// let mut current_block: u64;
|
||||
// // 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 {
|
||||
// res as libc::c_uint
|
||||
// }) as dc_imap_res
|
||||
// }
|
||||
}
|
||||
|
||||
// only returns 0 on connection problems; we should try later again in this case *
|
||||
pub fn delete_msg(
|
||||
@@ -1410,7 +1405,6 @@ impl dc_imap_t {
|
||||
mut server_uid: uint32_t,
|
||||
) -> libc::c_int {
|
||||
unimplemented!()
|
||||
}
|
||||
// let mut success: libc::c_int = 0;
|
||||
// let mut r: libc::c_int = 0;
|
||||
// let mut fetch_result: *mut clist = 0 as *mut clist;
|
||||
@@ -1521,7 +1515,7 @@ impl dc_imap_t {
|
||||
// } else {
|
||||
// dc_imap_is_connected(imap)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn configure_folders(&self, context: &dc_context_t, flags: libc::c_int) {
|
||||
if !self.is_connected() {
|
||||
|
||||
Reference in New Issue
Block a user