mirror of
https://github.com/chatmail/core.git
synced 2026-10-14 09:00:46 +03:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad4be80b4e | ||
|
|
8737c1d142 | ||
|
|
964fe466cc | ||
|
|
43936e7db7 | ||
|
|
0e80ce9c39 | ||
|
|
c652bae68a | ||
|
|
bc904a495d | ||
|
|
8d99444c6a | ||
|
|
9dab53e0af | ||
|
|
360089ac74 | ||
|
|
e892c5cf4d | ||
|
|
9ad4c9a6fe |
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
cargo build -p deltachat_ffi --release
|
cargo build -p deltachat_ffi
|
||||||
rm -rf build/ src/deltachat/*.so
|
rm -rf build/ src/deltachat/*.so
|
||||||
DCC_RS_DEV=`pwd`/.. pip install -e .
|
DCC_RS_DEV=`pwd`/.. pip install -e .
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ def py_dc_callback(ctx, evt, data1, data2):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
ret = callback(ctx, evt_name, data1, data2)
|
ret = callback(ctx, evt_name, data1, data2)
|
||||||
|
if ret is None:
|
||||||
|
ret = 0
|
||||||
|
assert isinstance(ret, int), repr(ret)
|
||||||
if event_sig_types & 4:
|
if event_sig_types & 4:
|
||||||
return ffi.cast('uintptr_t', ret)
|
return ffi.cast('uintptr_t', ret)
|
||||||
elif event_sig_types & 8:
|
elif event_sig_types & 8:
|
||||||
|
|||||||
@@ -23,13 +23,14 @@ class Account(object):
|
|||||||
by the underlying deltachat c-library. All public Account methods are
|
by the underlying deltachat c-library. All public Account methods are
|
||||||
meant to be memory-safe and return memory-safe objects.
|
meant to be memory-safe and return memory-safe objects.
|
||||||
"""
|
"""
|
||||||
def __init__(self, db_path, logid=None):
|
def __init__(self, db_path, logid=None, eventlogging=True):
|
||||||
""" initialize account object.
|
""" initialize account object.
|
||||||
|
|
||||||
:param db_path: a path to the account database. The database
|
:param db_path: a path to the account database. The database
|
||||||
will be created if it doesn't exist.
|
will be created if it doesn't exist.
|
||||||
:param logid: an optional logging prefix that should be used with
|
:param logid: an optional logging prefix that should be used with
|
||||||
the default internal logging.
|
the default internal logging.
|
||||||
|
:param eventlogging: if False no eventlogging and no context callback will be configured
|
||||||
"""
|
"""
|
||||||
self._dc_context = ffi.gc(
|
self._dc_context = ffi.gc(
|
||||||
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL),
|
||||||
@@ -39,12 +40,16 @@ class Account(object):
|
|||||||
db_path = db_path.encode("utf8")
|
db_path = db_path.encode("utf8")
|
||||||
if not lib.dc_open(self._dc_context, db_path, ffi.NULL):
|
if not lib.dc_open(self._dc_context, db_path, ffi.NULL):
|
||||||
raise ValueError("Could not dc_open: {}".format(db_path))
|
raise ValueError("Could not dc_open: {}".format(db_path))
|
||||||
self._evlogger = EventLogger(self._dc_context, logid)
|
if eventlogging:
|
||||||
deltachat.set_context_callback(self._dc_context, self._process_event)
|
self._evlogger = EventLogger(self._dc_context, logid)
|
||||||
|
deltachat.set_context_callback(self._dc_context, self._process_event)
|
||||||
self._threads = IOThreads(self._dc_context)
|
self._threads = IOThreads(self._dc_context)
|
||||||
self._configkeys = self.get_config("sys.config_keys").split()
|
self._configkeys = self.get_config("sys.config_keys").split()
|
||||||
self._imex_completed = threading.Event()
|
self._imex_completed = threading.Event()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self.shutdown()
|
||||||
|
|
||||||
def _check_config_key(self, name):
|
def _check_config_key(self, name):
|
||||||
if name not in self._configkeys:
|
if name not in self._configkeys:
|
||||||
raise KeyError("{!r} not a valid config key, existing keys: {!r}".format(
|
raise KeyError("{!r} not a valid config key, existing keys: {!r}".format(
|
||||||
@@ -333,12 +338,22 @@ class Account(object):
|
|||||||
lib.dc_stop_ongoing_process(self._dc_context)
|
lib.dc_stop_ongoing_process(self._dc_context)
|
||||||
self._threads.stop(wait=wait)
|
self._threads.stop(wait=wait)
|
||||||
|
|
||||||
|
def shutdown(self, wait=True):
|
||||||
|
""" stop threads and close and remove underlying dc_context and callbacks. """
|
||||||
|
if hasattr(self, "_dc_context"):
|
||||||
|
self.stop_threads(wait=False) # to interrupt idle and tell python threads to stop
|
||||||
|
lib.dc_close(self._dc_context)
|
||||||
|
self.stop_threads(wait=wait) # to wait for threads
|
||||||
|
deltachat.clear_context_callback(self._dc_context)
|
||||||
|
del self._dc_context
|
||||||
|
|
||||||
def _process_event(self, ctx, evt_name, data1, data2):
|
def _process_event(self, ctx, evt_name, data1, data2):
|
||||||
assert ctx == self._dc_context
|
assert ctx == self._dc_context
|
||||||
self._evlogger(evt_name, data1, data2)
|
if hasattr(self, "_evlogger"):
|
||||||
method = getattr(self, "on_" + evt_name.lower(), None)
|
self._evlogger(evt_name, data1, data2)
|
||||||
if method is not None:
|
method = getattr(self, "on_" + evt_name.lower(), None)
|
||||||
method(data1, data2)
|
if method is not None:
|
||||||
|
method(data1, data2)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def on_dc_event_imex_progress(self, data1, data2):
|
def on_dc_event_imex_progress(self, data1, data2):
|
||||||
@@ -380,11 +395,13 @@ class IOThreads:
|
|||||||
lib.dc_perform_imap_jobs(self._dc_context)
|
lib.dc_perform_imap_jobs(self._dc_context)
|
||||||
lib.dc_perform_imap_fetch(self._dc_context)
|
lib.dc_perform_imap_fetch(self._dc_context)
|
||||||
lib.dc_perform_imap_idle(self._dc_context)
|
lib.dc_perform_imap_idle(self._dc_context)
|
||||||
|
print("IMAP_THREAD finished")
|
||||||
|
|
||||||
def smtp_thread_run(self):
|
def smtp_thread_run(self):
|
||||||
while not self._thread_quitflag:
|
while not self._thread_quitflag:
|
||||||
lib.dc_perform_smtp_jobs(self._dc_context)
|
lib.dc_perform_smtp_jobs(self._dc_context)
|
||||||
lib.dc_perform_smtp_idle(self._dc_context)
|
lib.dc_perform_smtp_idle(self._dc_context)
|
||||||
|
print("SMTP_THREAD finished")
|
||||||
|
|
||||||
|
|
||||||
class EventLogger:
|
class EventLogger:
|
||||||
@@ -414,7 +431,7 @@ class EventLogger:
|
|||||||
raise ValueError("{}({!r},{!r})".format(*ev))
|
raise ValueError("{}({!r},{!r})".format(*ev))
|
||||||
return ev
|
return ev
|
||||||
|
|
||||||
def get_matching(self, event_name_regex):
|
def get_matching(self, event_name_regex, check_error=True):
|
||||||
self._log("-- waiting for event with regex: {} --".format(event_name_regex))
|
self._log("-- waiting for event with regex: {} --".format(event_name_regex))
|
||||||
rex = re.compile("(?:{}).*".format(event_name_regex))
|
rex = re.compile("(?:{}).*".format(event_name_regex))
|
||||||
while 1:
|
while 1:
|
||||||
|
|||||||
@@ -16,12 +16,23 @@ def pytest_addoption(parser):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.hookimpl(trylast=True)
|
||||||
|
def pytest_runtest_call(item):
|
||||||
|
# perform early finalization because we otherwise get cloberred
|
||||||
|
# output from concurrent threads printing between execution
|
||||||
|
# of the test function and the teardown phase of that test function
|
||||||
|
if "acfactory" in item.funcargs:
|
||||||
|
print("*"*30, "finalizing", "*"*30)
|
||||||
|
acfactory = item.funcargs["acfactory"]
|
||||||
|
acfactory.finalize()
|
||||||
|
|
||||||
|
|
||||||
def pytest_report_header(config, startdir):
|
def pytest_report_header(config, startdir):
|
||||||
t = tempfile.mktemp()
|
t = tempfile.mktemp()
|
||||||
try:
|
try:
|
||||||
ac = Account(t)
|
ac = Account(t, eventlogging=False)
|
||||||
info = ac.get_info()
|
info = ac.get_info()
|
||||||
del ac
|
ac.shutdown()
|
||||||
finally:
|
finally:
|
||||||
os.remove(t)
|
os.remove(t)
|
||||||
return "Deltachat core={} sqlite={}".format(
|
return "Deltachat core={} sqlite={}".format(
|
||||||
@@ -52,7 +63,6 @@ def acfactory(pytestconfig, tmpdir, request):
|
|||||||
self.live_count = 0
|
self.live_count = 0
|
||||||
self.offline_count = 0
|
self.offline_count = 0
|
||||||
self._finalizers = []
|
self._finalizers = []
|
||||||
request.addfinalizer(self.finalize)
|
|
||||||
self.init_time = time.time()
|
self.init_time = time.time()
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
@@ -78,6 +88,7 @@ def acfactory(pytestconfig, tmpdir, request):
|
|||||||
ac = Account(tmpdb.strpath, logid="ac{}".format(self.offline_count))
|
ac = Account(tmpdb.strpath, logid="ac{}".format(self.offline_count))
|
||||||
ac._evlogger.init_time = self.init_time
|
ac._evlogger.init_time = self.init_time
|
||||||
ac._evlogger.set_timeout(2)
|
ac._evlogger.set_timeout(2)
|
||||||
|
self._finalizers.append(ac.shutdown)
|
||||||
return ac
|
return ac
|
||||||
|
|
||||||
def get_configured_offline_account(self):
|
def get_configured_offline_account(self):
|
||||||
@@ -103,7 +114,7 @@ def acfactory(pytestconfig, tmpdir, request):
|
|||||||
ac._evlogger.set_timeout(30)
|
ac._evlogger.set_timeout(30)
|
||||||
ac.configure(**configdict)
|
ac.configure(**configdict)
|
||||||
ac.start_threads()
|
ac.start_threads()
|
||||||
self._finalizers.append(lambda: ac.stop_threads(wait=False))
|
self._finalizers.append(ac.shutdown)
|
||||||
return ac
|
return ac
|
||||||
|
|
||||||
def clone_online_account(self, account):
|
def clone_online_account(self, account):
|
||||||
@@ -114,7 +125,7 @@ def acfactory(pytestconfig, tmpdir, request):
|
|||||||
ac._evlogger.set_timeout(30)
|
ac._evlogger.set_timeout(30)
|
||||||
ac.configure(addr=account.get_config("addr"), mail_pw=account.get_config("mail_pw"))
|
ac.configure(addr=account.get_config("addr"), mail_pw=account.get_config("mail_pw"))
|
||||||
ac.start_threads()
|
ac.start_threads()
|
||||||
self._finalizers.append(lambda: ac.stop_threads(wait=False))
|
self._finalizers.append(ac.shutdown)
|
||||||
return ac
|
return ac
|
||||||
|
|
||||||
return AccountMaker()
|
return AccountMaker()
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import pytest
|
import pytest
|
||||||
from deltachat import capi, Account, const
|
from deltachat import capi, Account, const, set_context_callback, clear_context_callback
|
||||||
|
from deltachat.capi import ffi
|
||||||
|
from deltachat.account import EventLogger
|
||||||
|
|
||||||
|
|
||||||
def test_empty_context():
|
def test_empty_context():
|
||||||
@@ -8,6 +10,26 @@ def test_empty_context():
|
|||||||
capi.lib.dc_close(ctx)
|
capi.lib.dc_close(ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_None2int():
|
||||||
|
ctx = capi.lib.dc_context_new(capi.lib.py_dc_callback, ffi.NULL, ffi.NULL)
|
||||||
|
set_context_callback(ctx, lambda *args: None)
|
||||||
|
capi.lib.dc_close(ctx)
|
||||||
|
clear_context_callback(ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def test_dc_close_events():
|
||||||
|
ctx = capi.lib.dc_context_new(capi.lib.py_dc_callback, ffi.NULL, ffi.NULL)
|
||||||
|
evlog = EventLogger(ctx)
|
||||||
|
evlog.set_timeout(5)
|
||||||
|
set_context_callback(ctx, lambda ctx, evt_name, data1, data2: evlog(evt_name, data1, data2))
|
||||||
|
capi.lib.dc_close(ctx)
|
||||||
|
# test that we get events from dc_close
|
||||||
|
print(evlog.get_matching("DC_EVENT_INFO", check_error=False))
|
||||||
|
print(evlog.get_matching("DC_EVENT_INFO", check_error=False))
|
||||||
|
print(evlog.get_matching("DC_EVENT_INFO", check_error=False))
|
||||||
|
print(evlog.get_matching("DC_EVENT_INFO", check_error=False))
|
||||||
|
|
||||||
|
|
||||||
def test_wrong_db(tmpdir):
|
def test_wrong_db(tmpdir):
|
||||||
tmpdir.join("hello.db").write("123")
|
tmpdir.join("hello.db").write("123")
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ commands =
|
|||||||
python_files = tests/test_*.py
|
python_files = tests/test_*.py
|
||||||
norecursedirs = .tox
|
norecursedirs = .tox
|
||||||
xfail_strict=true
|
xfail_strict=true
|
||||||
|
timeout = 60
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
|
|||||||
+8
-2
@@ -135,7 +135,7 @@ pub fn dc_context_new(
|
|||||||
userdata: *mut libc::c_void,
|
userdata: *mut libc::c_void,
|
||||||
os_name: *const libc::c_char,
|
os_name: *const libc::c_char,
|
||||||
) -> Context {
|
) -> Context {
|
||||||
Context {
|
let context = Context {
|
||||||
blobdir: Arc::new(RwLock::new(std::ptr::null_mut())),
|
blobdir: Arc::new(RwLock::new(std::ptr::null_mut())),
|
||||||
dbfile: Arc::new(RwLock::new(std::ptr::null_mut())),
|
dbfile: Arc::new(RwLock::new(std::ptr::null_mut())),
|
||||||
inbox: Arc::new(RwLock::new({
|
inbox: Arc::new(RwLock::new({
|
||||||
@@ -179,7 +179,8 @@ pub fn dc_context_new(
|
|||||||
))),
|
))),
|
||||||
probe_imap_network: Arc::new(RwLock::new(0)),
|
probe_imap_network: Arc::new(RwLock::new(0)),
|
||||||
perform_inbox_jobs_needed: Arc::new(RwLock::new(0)),
|
perform_inbox_jobs_needed: Arc::new(RwLock::new(0)),
|
||||||
}
|
};
|
||||||
|
context
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn cb_receive_imf(
|
unsafe fn cb_receive_imf(
|
||||||
@@ -284,13 +285,17 @@ pub unsafe fn dc_context_unref(context: &mut Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_close(context: &Context) {
|
pub unsafe fn dc_close(context: &Context) {
|
||||||
|
println!("disconnecting inbox watch yooaa");
|
||||||
|
info!(context, 0, "disconnecting INBOX-watch",);
|
||||||
context.inbox.read().unwrap().disconnect(context);
|
context.inbox.read().unwrap().disconnect(context);
|
||||||
|
info!(context, 0, "disconnecting sentbox-thread",);
|
||||||
context
|
context
|
||||||
.sentbox_thread
|
.sentbox_thread
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.imap
|
.imap
|
||||||
.disconnect(context);
|
.disconnect(context);
|
||||||
|
info!(context, 0, "disconnecting mvbox-thread",);
|
||||||
context
|
context
|
||||||
.mvbox_thread
|
.mvbox_thread
|
||||||
.read()
|
.read()
|
||||||
@@ -298,6 +303,7 @@ pub unsafe fn dc_close(context: &Context) {
|
|||||||
.imap
|
.imap
|
||||||
.disconnect(context);
|
.disconnect(context);
|
||||||
|
|
||||||
|
info!(context, 0, "disconnecting SMTP");
|
||||||
context.smtp.clone().lock().unwrap().disconnect();
|
context.smtp.clone().lock().unwrap().disconnect();
|
||||||
|
|
||||||
context.sql.close(context);
|
context.sql.close(context);
|
||||||
|
|||||||
+27
-35
@@ -114,11 +114,10 @@ pub unsafe fn dc_stop_ongoing_process(context: &Context) {
|
|||||||
pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_job_t) {
|
pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_job_t) {
|
||||||
let flags: libc::c_int;
|
let flags: libc::c_int;
|
||||||
let mut current_block: u64;
|
let mut current_block: u64;
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success = false;
|
||||||
let mut imap_connected_here: libc::c_int = 0i32;
|
let mut imap_connected_here = false;
|
||||||
let mut smtp_connected_here: libc::c_int = 0i32;
|
let mut smtp_connected_here = false;
|
||||||
let mut ongoing_allocated_here: libc::c_int = 0i32;
|
let mut ongoing_allocated_here = false;
|
||||||
let mvbox_folder: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
||||||
let mut param: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t;
|
let mut param: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t;
|
||||||
/* just a pointer inside param, must not be freed! */
|
/* just a pointer inside param, must not be freed! */
|
||||||
let mut param_domain: *mut libc::c_char;
|
let mut param_domain: *mut libc::c_char;
|
||||||
@@ -126,7 +125,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
let mut param_autoconfig: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t;
|
let mut param_autoconfig: *mut dc_loginparam_t = 0 as *mut dc_loginparam_t;
|
||||||
|
|
||||||
if !(0 == dc_alloc_ongoing(context)) {
|
if !(0 == dc_alloc_ongoing(context)) {
|
||||||
ongoing_allocated_here = 1i32;
|
ongoing_allocated_here = true;
|
||||||
if !context.sql.is_open() {
|
if !context.sql.is_open() {
|
||||||
dc_log_error(
|
dc_log_error(
|
||||||
context,
|
context,
|
||||||
@@ -807,7 +806,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
r_0,
|
r_0,
|
||||||
);
|
);
|
||||||
free(r_0 as *mut libc::c_void);
|
free(r_0 as *mut libc::c_void);
|
||||||
if 0 != context
|
if context
|
||||||
.inbox
|
.inbox
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -855,7 +854,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
r_1,
|
r_1,
|
||||||
);
|
);
|
||||||
free(r_1 as *mut libc::c_void);
|
free(r_1 as *mut libc::c_void);
|
||||||
if 0 != context
|
if context
|
||||||
.inbox
|
.inbox
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -897,7 +896,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
r_2,
|
r_2,
|
||||||
);
|
);
|
||||||
free(r_2 as *mut libc::c_void);
|
free(r_2 as *mut libc::c_void);
|
||||||
if 0 != context
|
if context
|
||||||
.inbox
|
.inbox
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -950,7 +949,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
match current_block {
|
match current_block {
|
||||||
2927484062889439186 => {}
|
2927484062889439186 => {}
|
||||||
_ => {
|
_ => {
|
||||||
imap_connected_here = 1i32;
|
imap_connected_here = true;
|
||||||
if !s.shall_stop_ongoing {
|
if !s.shall_stop_ongoing {
|
||||||
context.call_cb(
|
context.call_cb(
|
||||||
Event::CONFIGURE_PROGRESS,
|
Event::CONFIGURE_PROGRESS,
|
||||||
@@ -965,7 +964,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
0i32 as uintptr_t,
|
0i32 as uintptr_t,
|
||||||
);
|
);
|
||||||
/* 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 */
|
/* 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 0 == context
|
if context
|
||||||
.smtp
|
.smtp
|
||||||
.clone()
|
.clone()
|
||||||
.lock()
|
.lock()
|
||||||
@@ -1011,7 +1010,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
r_3,
|
r_3,
|
||||||
);
|
);
|
||||||
free(r_3 as *mut libc::c_void);
|
free(r_3 as *mut libc::c_void);
|
||||||
if 0 == context
|
if context
|
||||||
.smtp
|
.smtp
|
||||||
.clone()
|
.clone()
|
||||||
.lock()
|
.lock()
|
||||||
@@ -1065,7 +1064,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
free(r_4
|
free(r_4
|
||||||
as
|
as
|
||||||
*mut libc::c_void);
|
*mut libc::c_void);
|
||||||
if 0 == context
|
if context
|
||||||
.smtp
|
.smtp
|
||||||
.clone()
|
.clone()
|
||||||
.lock()
|
.lock()
|
||||||
@@ -1094,7 +1093,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
match current_block {
|
match current_block {
|
||||||
2927484062889439186 => {}
|
2927484062889439186 => {}
|
||||||
_ => {
|
_ => {
|
||||||
smtp_connected_here = 1i32;
|
smtp_connected_here = true;
|
||||||
if !s.shall_stop_ongoing {
|
if !s.shall_stop_ongoing {
|
||||||
context.call_cb(Event::CONFIGURE_PROGRESS,
|
context.call_cb(Event::CONFIGURE_PROGRESS,
|
||||||
(if 900i32
|
(if 900i32
|
||||||
@@ -1205,14 +1204,8 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
as
|
as
|
||||||
uintptr_t);
|
uintptr_t);
|
||||||
dc_ensure_secret_key_exists(context);
|
dc_ensure_secret_key_exists(context);
|
||||||
success = 1i32;
|
success = true;
|
||||||
dc_log_info(context,
|
info!(context, 0, "Configure completed.");
|
||||||
0i32,
|
|
||||||
b"Configure completed.\x00"
|
|
||||||
as
|
|
||||||
*const u8
|
|
||||||
as
|
|
||||||
*const libc::c_char);
|
|
||||||
if !s.shall_stop_ongoing
|
if !s.shall_stop_ongoing
|
||||||
{
|
{
|
||||||
context.call_cb(Event::CONFIGURE_PROGRESS,
|
context.call_cb(Event::CONFIGURE_PROGRESS,
|
||||||
@@ -1255,24 +1248,23 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: *mut dc_j
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 != imap_connected_here {
|
if imap_connected_here {
|
||||||
context.inbox.read().unwrap().disconnect(context);
|
// XXX why do we want to disconnect here?
|
||||||
|
// context.inbox.read().unwrap().disconnect(context);
|
||||||
|
info!(context, 0, "Skipping INBOX/IMAP disconnect");
|
||||||
}
|
}
|
||||||
if 0 != smtp_connected_here {
|
if smtp_connected_here {
|
||||||
context.smtp.clone().lock().unwrap().disconnect();
|
// XXX why do we want to disconnect here?
|
||||||
|
// context.smtp.clone().lock().unwrap().disconnect();
|
||||||
|
info!(context, 0, "Skipping SMTP disconnect");
|
||||||
}
|
}
|
||||||
dc_loginparam_unref(param);
|
dc_loginparam_unref(param);
|
||||||
dc_loginparam_unref(param_autoconfig);
|
dc_loginparam_unref(param_autoconfig);
|
||||||
free(param_addr_urlencoded as *mut libc::c_void);
|
free(param_addr_urlencoded as *mut libc::c_void);
|
||||||
if 0 != ongoing_allocated_here {
|
if ongoing_allocated_here {
|
||||||
dc_free_ongoing(context);
|
dc_free_ongoing(context);
|
||||||
}
|
}
|
||||||
free(mvbox_folder as *mut libc::c_void);
|
context.call_cb(Event::CONFIGURE_PROGRESS, if success { 1000 } else { 0 }, 0);
|
||||||
context.call_cb(
|
|
||||||
Event::CONFIGURE_PROGRESS,
|
|
||||||
(if 0 != success { 1000i32 } else { 0i32 }) as uintptr_t,
|
|
||||||
0i32 as uintptr_t,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_free_ongoing(context: &Context) {
|
pub unsafe fn dc_free_ongoing(context: &Context) {
|
||||||
@@ -1743,8 +1735,8 @@ pub unsafe fn dc_connect_to_configured_imap(context: &Context, imap: &Imap) -> l
|
|||||||
b"configured_\x00" as *const u8 as *const libc::c_char,
|
b"configured_\x00" as *const u8 as *const libc::c_char,
|
||||||
);
|
);
|
||||||
/*the trailing underscore is correct*/
|
/*the trailing underscore is correct*/
|
||||||
if !(0 == imap.connect(context, param)) {
|
if imap.connect(context, param) {
|
||||||
ret_connected = 2i32;
|
ret_connected = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dc_loginparam_unref(param);
|
dc_loginparam_unref(param);
|
||||||
|
|||||||
+7
-11
@@ -49,24 +49,18 @@ pub struct dc_job_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_perform_imap_jobs(context: &Context) {
|
pub unsafe fn dc_perform_imap_jobs(context: &Context) {
|
||||||
dc_log_info(
|
info!(context, 0, "dc_perform_imap_jobs starting.",);
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"INBOX-jobs started...\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
|
|
||||||
let probe_imap_network = *context.probe_imap_network.clone().read().unwrap();
|
let probe_imap_network = *context.probe_imap_network.clone().read().unwrap();
|
||||||
*context.probe_imap_network.write().unwrap() = 0;
|
*context.probe_imap_network.write().unwrap() = 0;
|
||||||
*context.perform_inbox_jobs_needed.write().unwrap() = 0;
|
*context.perform_inbox_jobs_needed.write().unwrap() = 0;
|
||||||
|
|
||||||
dc_job_perform(context, 100, probe_imap_network);
|
dc_job_perform(context, 100, probe_imap_network);
|
||||||
dc_log_info(
|
info!(context, 0, "dc_perform_imap_jobs ended.",);
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"INBOX-jobs ended.\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: libc::c_int) {
|
unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: libc::c_int) {
|
||||||
|
// info!(context, 0, "dc_job_perform {} {}", thread, probe_network);
|
||||||
let mut select_stmt: *mut sqlite3_stmt;
|
let mut select_stmt: *mut sqlite3_stmt;
|
||||||
let mut job = dc_job_t {
|
let mut job = dc_job_t {
|
||||||
job_id: 0,
|
job_id: 0,
|
||||||
@@ -133,6 +127,7 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network:
|
|||||||
let mut tries: libc::c_int = 0i32;
|
let mut tries: libc::c_int = 0i32;
|
||||||
while tries <= 1i32 {
|
while tries <= 1i32 {
|
||||||
job.try_again = 0i32;
|
job.try_again = 0i32;
|
||||||
|
// info!(context, 0, "dc_job_perform action {}", job.action);
|
||||||
match job.action {
|
match job.action {
|
||||||
5901 => {
|
5901 => {
|
||||||
dc_job_do_DC_JOB_SEND(context, &mut job);
|
dc_job_do_DC_JOB_SEND(context, &mut job);
|
||||||
@@ -322,7 +317,7 @@ unsafe fn dc_job_do_DC_JOB_SEND(context: &Context, job: &mut dc_job_t) {
|
|||||||
);
|
);
|
||||||
let connected = context.smtp.lock().unwrap().connect(context, loginparam);
|
let connected = context.smtp.lock().unwrap().connect(context, loginparam);
|
||||||
dc_loginparam_unref(loginparam);
|
dc_loginparam_unref(loginparam);
|
||||||
if 0 == connected {
|
if !connected {
|
||||||
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
dc_job_try_again_later(job, 3i32, 0 as *const libc::c_char);
|
||||||
current_block = 14216916617354591294;
|
current_block = 14216916617354591294;
|
||||||
} else {
|
} else {
|
||||||
@@ -1004,6 +999,7 @@ pub unsafe fn dc_job_kill_action(context: &Context, action: libc::c_int) {
|
|||||||
|
|
||||||
pub unsafe fn dc_perform_imap_fetch(context: &Context) {
|
pub unsafe fn dc_perform_imap_fetch(context: &Context) {
|
||||||
let inbox = context.inbox.read().unwrap();
|
let inbox = context.inbox.read().unwrap();
|
||||||
|
info!(context, 0, "dc_perform_imap_fetch got inbox");
|
||||||
|
|
||||||
let start: libc::clock_t = clock();
|
let start: libc::clock_t = clock();
|
||||||
if 0 == connect_to_inbox(context, &inbox) {
|
if 0 == connect_to_inbox(context, &inbox) {
|
||||||
|
|||||||
+106
-77
@@ -33,7 +33,8 @@ pub struct Imap {
|
|||||||
precheck_imf: dc_precheck_imf_t,
|
precheck_imf: dc_precheck_imf_t,
|
||||||
receive_imf: dc_receive_imf_t,
|
receive_imf: dc_receive_imf_t,
|
||||||
|
|
||||||
session: Arc<Mutex<(Option<Session>, Option<net::TcpStream>)>>,
|
session: Arc<Mutex<Option<Session>>>,
|
||||||
|
stream: Arc<RwLock<Option<net::TcpStream>>>,
|
||||||
connected: Arc<Mutex<bool>>,
|
connected: Arc<Mutex<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +352,8 @@ impl Imap {
|
|||||||
receive_imf: dc_receive_imf_t,
|
receive_imf: dc_receive_imf_t,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Imap {
|
Imap {
|
||||||
session: Arc::new(Mutex::new((None, None))),
|
session: Arc::new(Mutex::new(None)),
|
||||||
|
stream: Arc::new(RwLock::new(None)),
|
||||||
config: Arc::new(RwLock::new(ImapConfig::default())),
|
config: Arc::new(RwLock::new(ImapConfig::default())),
|
||||||
watch: Arc::new((Mutex::new(false), Condvar::new())),
|
watch: Arc::new((Mutex::new(false), Condvar::new())),
|
||||||
get_config,
|
get_config,
|
||||||
@@ -370,18 +372,18 @@ impl Imap {
|
|||||||
self.config.read().unwrap().should_reconnect
|
self.config.read().unwrap().should_reconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_handle_if_needed(&self, context: &Context) -> libc::c_int {
|
fn setup_handle_if_needed(&self, context: &Context) -> bool {
|
||||||
if self.config.read().unwrap().imap_server.is_empty() {
|
if self.config.read().unwrap().imap_server.is_empty() {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.should_reconnect() {
|
if self.should_reconnect() {
|
||||||
self.unsetup_handle(context);
|
self.unsetup_handle(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_connected() && self.session.lock().unwrap().1.is_some() {
|
if self.is_connected() && self.stream.read().unwrap().is_some() {
|
||||||
self.config.write().unwrap().should_reconnect = false;
|
self.config.write().unwrap().should_reconnect = false;
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let server_flags = self.config.read().unwrap().server_flags;
|
let server_flags = self.config.read().unwrap().server_flags;
|
||||||
@@ -425,7 +427,7 @@ impl Imap {
|
|||||||
};
|
};
|
||||||
client.authenticate("XOAUTH2", &auth)
|
client.authenticate("XOAUTH2", &auth)
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client.login(imap_user, imap_pw)
|
client.login(imap_user, imap_pw)
|
||||||
@@ -446,7 +448,7 @@ impl Imap {
|
|||||||
err
|
err
|
||||||
);
|
);
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -454,20 +456,29 @@ impl Imap {
|
|||||||
|
|
||||||
match login_res {
|
match login_res {
|
||||||
Ok((session, stream)) => {
|
Ok((session, stream)) => {
|
||||||
*self.session.lock().unwrap() = (Some(session), Some(stream));
|
*self.session.lock().unwrap() = Some(session);
|
||||||
1
|
*self.stream.write().unwrap() = Some(stream);
|
||||||
|
true
|
||||||
}
|
}
|
||||||
Err((err, _)) => {
|
Err((err, _)) => {
|
||||||
log_event!(context, Event::ERROR_NETWORK, 0, "Cannot login ({})", err);
|
log_event!(context, Event::ERROR_NETWORK, 0, "Cannot login ({})", err);
|
||||||
self.unsetup_handle(context);
|
self.unsetup_handle(context);
|
||||||
|
|
||||||
0
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsetup_handle(&self, context: &Context) {
|
fn unsetup_handle(&self, context: &Context) {
|
||||||
let session = self.session.lock().unwrap().0.take();
|
info!(context, 0, "IMAP unsetup_handle starts");
|
||||||
|
|
||||||
|
// XXX the next line currently can block even if all threads
|
||||||
|
// terminated already
|
||||||
|
let session = self.session.lock().unwrap().take();
|
||||||
|
info!(
|
||||||
|
context,
|
||||||
|
0, "IMAP unsetup_handle step1 (acquired session.lock)"
|
||||||
|
);
|
||||||
if session.is_some() {
|
if session.is_some() {
|
||||||
match session.unwrap().close() {
|
match session.unwrap().close() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@@ -476,7 +487,11 @@ impl Imap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let stream = self.session.lock().unwrap().1.take();
|
info!(
|
||||||
|
context,
|
||||||
|
0, "IMAP unsetup_handle step 2 (closing down stream)."
|
||||||
|
);
|
||||||
|
let stream = self.stream.write().unwrap().take();
|
||||||
if stream.is_some() {
|
if stream.is_some() {
|
||||||
match stream.unwrap().shutdown(net::Shutdown::Both) {
|
match stream.unwrap().shutdown(net::Shutdown::Both) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
@@ -486,10 +501,10 @@ impl Imap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut cfg = self.config.write().unwrap();
|
info!(context, 0, "IMAP unsetup_handle step 3 (clearing config).");
|
||||||
cfg.selected_folder = None;
|
self.config.write().unwrap().selected_folder = None;
|
||||||
cfg.selected_mailbox = None;
|
self.config.write().unwrap().selected_mailbox = None;
|
||||||
info!(context, 0, "IMAP disconnected.",);
|
info!(context, 0, "IMAP unsetup_handle step 4 (disconnected).",);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free_connect_params(&self) {
|
fn free_connect_params(&self) {
|
||||||
@@ -507,17 +522,17 @@ impl Imap {
|
|||||||
cfg.watch_folder = None;
|
cfg.watch_folder = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, context: &Context, lp: *const dc_loginparam_t) -> libc::c_int {
|
pub fn connect(&self, context: &Context, lp: *const dc_loginparam_t) -> bool {
|
||||||
if lp.is_null() {
|
if lp.is_null() {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
let lp = unsafe { *lp };
|
let lp = unsafe { *lp };
|
||||||
if lp.mail_server.is_null() || lp.mail_user.is_null() || lp.mail_pw.is_null() {
|
if lp.mail_server.is_null() || lp.mail_user.is_null() || lp.mail_pw.is_null() {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_connected() {
|
if self.is_connected() {
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -537,50 +552,63 @@ impl Imap {
|
|||||||
config.server_flags = server_flags;
|
config.server_flags = server_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.setup_handle_if_needed(context) == 0 {
|
if self.setup_handle_if_needed(context) {
|
||||||
self.free_connect_params();
|
self.free_connect_params();
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.session.lock().unwrap().0 {
|
let teardown: bool;
|
||||||
|
|
||||||
|
match &mut *self.session.lock().unwrap() {
|
||||||
Some(ref mut session) => {
|
Some(ref mut session) => {
|
||||||
if let Ok(caps) = session.capabilities() {
|
if let Ok(caps) = session.capabilities() {
|
||||||
let can_idle = caps.has("IDLE");
|
if !context.sql.is_open() {
|
||||||
let has_xlist = caps.has("XLIST");
|
warn!(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
"IMAP-LOGIN as {} ok but ABORTING",
|
||||||
|
as_str(lp.mail_user),
|
||||||
|
);
|
||||||
|
teardown = true;
|
||||||
|
} else {
|
||||||
|
let can_idle = caps.has("IDLE");
|
||||||
|
let has_xlist = caps.has("XLIST");
|
||||||
|
|
||||||
let caps_list = caps.iter().fold(String::new(), |mut s, c| {
|
let caps_list = caps.iter().fold(String::new(), |mut s, c| {
|
||||||
s += " ";
|
s += " ";
|
||||||
s += c;
|
s += c;
|
||||||
s
|
s
|
||||||
});
|
});
|
||||||
|
|
||||||
log_event!(
|
log_event!(
|
||||||
context,
|
context,
|
||||||
Event::IMAP_CONNECTED,
|
Event::IMAP_CONNECTED,
|
||||||
0,
|
0,
|
||||||
"IMAP-LOGIN as {} ok",
|
"IMAP-LOGIN as {}, capabilities: {}",
|
||||||
as_str(lp.mail_user),
|
as_str(lp.mail_user),
|
||||||
);
|
caps_list,
|
||||||
info!(context, 0, "IMAP-capabilities:{}", caps_list);
|
);
|
||||||
|
|
||||||
let mut config = self.config.write().unwrap();
|
self.config.write().unwrap().can_idle = can_idle;
|
||||||
config.can_idle = can_idle;
|
self.config.write().unwrap().has_xlist = has_xlist;
|
||||||
config.has_xlist = has_xlist;
|
*self.connected.lock().unwrap() = true;
|
||||||
*self.connected.lock().unwrap() = true;
|
teardown = false;
|
||||||
|
}
|
||||||
1
|
|
||||||
} else {
|
} else {
|
||||||
self.unsetup_handle(context);
|
teardown = true;
|
||||||
self.free_connect_params();
|
|
||||||
0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.unsetup_handle(context);
|
teardown = true;
|
||||||
self.free_connect_params();
|
|
||||||
0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if teardown {
|
||||||
|
self.unsetup_handle(context);
|
||||||
|
self.free_connect_params();
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn disconnect(&self, context: &Context) {
|
pub fn disconnect(&self, context: &Context) {
|
||||||
@@ -596,7 +624,7 @@ impl Imap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch(&self, context: &Context) -> libc::c_int {
|
pub fn fetch(&self, context: &Context) -> libc::c_int {
|
||||||
if !self.is_connected() {
|
if !self.is_connected() || !context.sql.is_open() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,7 +648,7 @@ impl Imap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn select_folder<S: AsRef<str>>(&self, context: &Context, folder: Option<S>) -> usize {
|
fn select_folder<S: AsRef<str>>(&self, context: &Context, folder: Option<S>) -> usize {
|
||||||
if self.session.lock().unwrap().0.is_none() {
|
if self.session.lock().unwrap().is_none() {
|
||||||
let mut cfg = self.config.write().unwrap();
|
let mut cfg = self.config.write().unwrap();
|
||||||
cfg.selected_folder = None;
|
cfg.selected_folder = None;
|
||||||
cfg.selected_folder_needs_expunge = false;
|
cfg.selected_folder_needs_expunge = false;
|
||||||
@@ -644,7 +672,7 @@ impl Imap {
|
|||||||
|
|
||||||
// A CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see
|
// A CLOSE-SELECT is considerably faster than an EXPUNGE-SELECT, see
|
||||||
// https://tools.ietf.org/html/rfc3501#section-6.4.2
|
// https://tools.ietf.org/html/rfc3501#section-6.4.2
|
||||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.close() {
|
match session.close() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -660,7 +688,7 @@ impl Imap {
|
|||||||
|
|
||||||
// select new folder
|
// select new folder
|
||||||
if let Some(ref folder) = folder {
|
if let Some(ref folder) = folder {
|
||||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.select(folder) {
|
match session.select(folder) {
|
||||||
Ok(mailbox) => {
|
Ok(mailbox) => {
|
||||||
let mut config = self.config.write().unwrap();
|
let mut config = self.config.write().unwrap();
|
||||||
@@ -766,7 +794,7 @@ impl Imap {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let list = if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
let list = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
// `FETCH <message sequence number> (UID)`
|
// `FETCH <message sequence number> (UID)`
|
||||||
let set = format!("{}", mailbox.exists);
|
let set = format!("{}", mailbox.exists);
|
||||||
match session.fetch(set, PREFETCH_FLAGS) {
|
match session.fetch(set, PREFETCH_FLAGS) {
|
||||||
@@ -810,7 +838,7 @@ impl Imap {
|
|||||||
let mut read_errors = 0;
|
let mut read_errors = 0;
|
||||||
let mut new_last_seen_uid = 0;
|
let mut new_last_seen_uid = 0;
|
||||||
|
|
||||||
let list = if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
let list = if let Some(ref mut session) = &mut *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);
|
||||||
@@ -934,7 +962,7 @@ impl Imap {
|
|||||||
|
|
||||||
let set = format!("{}", server_uid);
|
let set = format!("{}", server_uid);
|
||||||
|
|
||||||
let msgs = if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
let msgs = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.uid_fetch(set, BODY_FLAGS) {
|
match session.uid_fetch(set, BODY_FLAGS) {
|
||||||
Ok(msgs) => msgs,
|
Ok(msgs) => msgs,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -1032,9 +1060,10 @@ impl Imap {
|
|||||||
let (sender, receiver) = std::sync::mpsc::channel();
|
let (sender, receiver) = std::sync::mpsc::channel();
|
||||||
let v = self.watch.clone();
|
let v = self.watch.clone();
|
||||||
|
|
||||||
|
warn!(context, 0, "IMAP-IDLE SPAWNING");
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let &(ref lock, ref cvar) = &*v;
|
let &(ref lock, ref cvar) = &*v;
|
||||||
if let Some(ref mut session) = session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *session.lock().unwrap() {
|
||||||
let mut idle = match session.idle() {
|
let mut idle = match session.idle() {
|
||||||
Ok(idle) => idle,
|
Ok(idle) => idle,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -1146,7 +1175,7 @@ impl Imap {
|
|||||||
// check for new messages. fetch_from_single_folder() has the side-effect that messages
|
// check for new messages. fetch_from_single_folder() has the side-effect that messages
|
||||||
// are also downloaded, however, typically this would take place in the FETCH command
|
// are also downloaded, however, typically this would take place in the FETCH command
|
||||||
// following IDLE otherwise, so this seems okay here.
|
// following IDLE otherwise, so this seems okay here.
|
||||||
if self.setup_handle_if_needed(context) != 0 {
|
if self.setup_handle_if_needed(context) {
|
||||||
if let Some(ref watch_folder) = self.config.read().unwrap().watch_folder {
|
if let Some(ref watch_folder) = self.config.read().unwrap().watch_folder {
|
||||||
if 0 != self.fetch_from_single_folder(context, watch_folder) {
|
if 0 != self.fetch_from_single_folder(context, watch_folder) {
|
||||||
do_fake_idle = false;
|
do_fake_idle = false;
|
||||||
@@ -1212,7 +1241,7 @@ impl Imap {
|
|||||||
folder.as_ref()
|
folder.as_ref()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let moved = if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
let moved = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.uid_mv(&set, &dest_folder) {
|
match session.uid_mv(&set, &dest_folder) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
res = DC_SUCCESS;
|
res = DC_SUCCESS;
|
||||||
@@ -1237,7 +1266,7 @@ impl Imap {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if !moved {
|
if !moved {
|
||||||
let copied = if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
let copied = if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.uid_copy(&set, &dest_folder) {
|
match session.uid_copy(&set, &dest_folder) {
|
||||||
Ok(_) => true,
|
Ok(_) => true,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
@@ -1282,7 +1311,7 @@ impl Imap {
|
|||||||
if server_uid == 0 {
|
if server_uid == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
let set = format!("{}", server_uid);
|
let set = format!("{}", server_uid);
|
||||||
let query = format!("+FLAGS ({})", flag.as_ref());
|
let query = format!("+FLAGS ({})", flag.as_ref());
|
||||||
match session.uid_store(&set, &query) {
|
match session.uid_store(&set, &query) {
|
||||||
@@ -1394,18 +1423,18 @@ impl Imap {
|
|||||||
.expect("just selected folder");
|
.expect("just selected folder");
|
||||||
|
|
||||||
if can_create_flag {
|
if can_create_flag {
|
||||||
let fetched_msgs = if let Some(ref mut session) = self.session.lock().unwrap().0
|
let fetched_msgs =
|
||||||
{
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.uid_fetch(set, FETCH_FLAGS) {
|
match session.uid_fetch(set, FETCH_FLAGS) {
|
||||||
Ok(res) => Some(res),
|
Ok(res) => Some(res),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("fetch error: {:?}", err);
|
eprintln!("fetch error: {:?}", err);
|
||||||
None
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
unreachable!();
|
||||||
unreachable!();
|
};
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(msgs) = fetched_msgs {
|
if let Some(msgs) = fetched_msgs {
|
||||||
let flag_set = msgs
|
let flag_set = msgs
|
||||||
@@ -1486,7 +1515,7 @@ impl Imap {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let set = format!("{}", server_uid);
|
let set = format!("{}", server_uid);
|
||||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.uid_fetch(set, PREFETCH_FLAGS) {
|
match session.uid_fetch(set, PREFETCH_FLAGS) {
|
||||||
Ok(msgs) => {
|
Ok(msgs) => {
|
||||||
if msgs.is_empty()
|
if msgs.is_empty()
|
||||||
@@ -1568,7 +1597,7 @@ impl Imap {
|
|||||||
if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) {
|
if mvbox_folder.is_none() && 0 != (flags as usize & DC_CREATE_MVBOX) {
|
||||||
info!(context, 0, "Creating MVBOX-folder \"DeltaChat\"...",);
|
info!(context, 0, "Creating MVBOX-folder \"DeltaChat\"...",);
|
||||||
|
|
||||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
match session.create("DeltaChat") {
|
match session.create("DeltaChat") {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
mvbox_folder = Some("DeltaChat".into());
|
mvbox_folder = Some("DeltaChat".into());
|
||||||
@@ -1634,7 +1663,7 @@ impl Imap {
|
|||||||
&self,
|
&self,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
) -> Option<imap::types::ZeroCopy<Vec<imap::types::Name>>> {
|
) -> Option<imap::types::ZeroCopy<Vec<imap::types::Name>>> {
|
||||||
if let Some(ref mut session) = self.session.lock().unwrap().0 {
|
if let Some(ref mut session) = &mut *self.session.lock().unwrap() {
|
||||||
// TODO: use xlist when available
|
// TODO: use xlist when available
|
||||||
match session.list(Some(""), Some("*")) {
|
match session.list(Some(""), Some("*")) {
|
||||||
Ok(list) => {
|
Ok(list) => {
|
||||||
|
|||||||
+7
-7
@@ -47,14 +47,14 @@ impl Smtp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Connect using the provided login params
|
/// Connect using the provided login params
|
||||||
pub fn connect(&mut self, context: &Context, lp: *const dc_loginparam_t) -> usize {
|
pub fn connect(&mut self, context: &Context, lp: *const dc_loginparam_t) -> bool {
|
||||||
if lp.is_null() {
|
if lp.is_null() {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_connected() {
|
if self.is_connected() {
|
||||||
warn!(context, 0, "SMTP already connected.");
|
warn!(context, 0, "SMTP already connected.");
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe because we checked for null pointer above.
|
// Safe because we checked for null pointer above.
|
||||||
@@ -78,7 +78,7 @@ impl Smtp {
|
|||||||
|
|
||||||
if self.from.is_none() {
|
if self.from.is_none() {
|
||||||
// TODO: print error
|
// TODO: print error
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let domain = unsafe {
|
let domain = unsafe {
|
||||||
@@ -103,7 +103,7 @@ impl Smtp {
|
|||||||
let send_pw = as_str(lp.send_pw);
|
let send_pw = as_str(lp.send_pw);
|
||||||
let access_token = dc_get_oauth2_access_token(context, addr, send_pw, 0);
|
let access_token = dc_get_oauth2_access_token(context, addr, send_pw, 0);
|
||||||
if access_token.is_none() {
|
if access_token.is_none() {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
let user = as_str(lp.send_user);
|
let user = as_str(lp.send_user);
|
||||||
|
|
||||||
@@ -137,11 +137,11 @@ impl Smtp {
|
|||||||
"SMTP-LOGIN as {} ok",
|
"SMTP-LOGIN as {} ok",
|
||||||
as_str(lp.send_user),
|
as_str(lp.send_user),
|
||||||
);
|
);
|
||||||
1
|
true
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(context, 0, "SMTP: failed to establish connection {:?}", err);
|
warn!(context, 0, "SMTP: failed to establish connection {:?}", err);
|
||||||
0
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user