From 06bcfc20cbeec905273e3975beddf7f509995a76 Mon Sep 17 00:00:00 2001 From: VG Date: Thu, 12 May 2016 17:34:11 +0200 Subject: add timeout for allways in idle servers ex: dovecot sends keepalives messages each 2minutes (by default) --- climl/imap.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/climl/imap.py b/climl/imap.py index 2f7cee9..30fa272 100644 --- a/climl/imap.py +++ b/climl/imap.py @@ -5,6 +5,7 @@ import imapclient import contextlib import backports.ssl import socket +import time def conf_boolean_postprocess(src): src = src.lower().strip() @@ -42,7 +43,8 @@ def connect_to_imap(conf, password): connection = imapclient.IMAPClient(host=conf.get('imap.server'), ssl=conf.get('imap.tls', True), - ssl_context=ssl_context) + ssl_context=ssl_context, + use_uid=True) if conf.get('imap.start_tls', False): connection.start_tls(ssl_context=ssl_context) print('connection succeed') @@ -83,12 +85,24 @@ def imap_waiter(connection): (general assumption is a 29minutes timeout), we try to redo idle-mode every 24 minutes. Each call to imap_waiter is a single idle iteration. Thus this function may return empty list. + + Note: on some servers, there might be events between the last search + command and the begining of idle mode. If those events represent new + mails, they will be checked at the idle timeout (it takes time to see + them, but they are not lost). + + Note2: this function use time.time to check for timeout (in case the + server returns non-real-events like dovecot 2min keepalive messages), + this function can return (in case of system clock set) lower value + than a precendent call, but the only side effect will be a shorter + timeout which is not a deal breaker. ''' print('entering idle mode...') connection.idle() print('waiting for an event') try: - while True: + tenter = time.time() + while (time.time() - tenter) <= 24*60: events = connection.idle_check(timeout=24*60) if len(events) == 1 and \ str(bytes(events[0][0]), encoding='ascii') == 'OK': @@ -102,8 +116,10 @@ def imap_waiter(connection): connection.idle_done() raise print('quitting idle mode...') - connection.idle_done() - return [i for i in events if i[1] == b'RECENT'] + command_text, idle_responses = connection.idle_done() + events.extend(idle_responses) + print('idle_done results:', command_text, idle_responses) + return events def main(callback=None): @@ -123,7 +139,7 @@ def main(callback=None): print('selecting folder', conf.get('imap.mailbox')) connection.select_folder(conf.get('imap.mailbox')) # at start, select all mails - idlist = connection.search(['SEEN']) + idlist = connection.search(['UNSEEN']) print('initial idlist: ', idlist) for oneid in idlist: print('new mail:', oneid) -- cgit v1.2.3