diff --git a/docs/MANUAL.rst b/docs/MANUAL.rst index 62b0d3b..26f31a6 100644 --- a/docs/MANUAL.rst +++ b/docs/MANUAL.rst @@ -288,6 +288,17 @@ KNOWN BUGS last stable version and send us a report to the mailing list including the full log. +* IDLE support is incomplete and experimental. Bugs may be encountered. + + * No hook exists for "run after an IDLE response". Email will + show up, but may not be processed until the next refresh cycle. + + * nametrans may not be supported correctly. + + * IMAP IDLE <-> IMAP IDLE doesn't work yet. + + * IDLE may only work "once" per refresh. If you encounter this bug, + please send a report to the list! SEE ALSO ======== diff --git a/offlineimap.conf b/offlineimap.conf index 33a0810..9329c66 100644 --- a/offlineimap.conf +++ b/offlineimap.conf @@ -364,6 +364,23 @@ remoteuser = username # # reference = Mail +# In between synchronisations, OfflineIMAP can monitor mailboxes for new +# messages using the IDLE command. If you want to enable this, specify here +# the folders you wish to monitor. Note that the IMAP protocol requires a +# separate connection for each folder monitored in this way, so setting +# this option will force settings for: +# maxconnections - to be at least the number of folders you give +# holdconnectionopen - to be true +# keepalive - to be 29 minutes unless you specify otherwise +# +# This feature isn't complete and may well have problems. BE AWARE THIS +# IS EXPERIMENTAL STUFF. See the manual for more details. +# +# This option should return a Python list. For example +# +# idlefolders = ['INBOX', 'INBOX.Alerts'] +# + # OfflineIMAP can use multiple connections to the server in order # to perform multiple synchronization actions simultaneously. # This may place a higher burden on the server. In most cases, diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py index 7703879..58e7e57 100644 --- a/offlineimap/imapserver.py +++ b/offlineimap/imapserver.py @@ -43,7 +43,7 @@ class IMAPServer: username = None, password = None, hostname = None, port = None, ssl = 1, maxconnections = 1, tunnel = None, reference = '""', sslclientcert = None, sslclientkey = None, - sslcacertfile= None): + sslcacertfile = None, idlefolders = []): self.ui = getglobalui() self.reposname = reposname self.config = config @@ -72,6 +72,7 @@ class IMAPServer: self.semaphore = BoundedSemaphore(self.maxconnections) self.connectionlock = Lock() self.reference = reference + self.idlefolders = idlefolders self.gss_step = self.GSS_STATE_STEP self.gss_vc = None self.gssapi = False @@ -386,6 +387,7 @@ class ConfigedIMAPServer(IMAPServer): sslclientkey = self.repos.getsslclientkey() sslcacertfile = self.repos.getsslcacertfile() reference = self.repos.getreference() + idlefolders = self.repos.getidlefolders() server = None password = None @@ -397,6 +399,7 @@ class ConfigedIMAPServer(IMAPServer): IMAPServer.__init__(self, self.config, self.repos.getname(), tunnel = usetunnel, reference = reference, + idlefolders = idlefolders, maxconnections = self.repos.getmaxconnections()) else: if not password: @@ -405,6 +408,7 @@ class ConfigedIMAPServer(IMAPServer): user, password, host, port, ssl, self.repos.getmaxconnections(), reference = reference, + idlefolders = idlefolders, sslclientcert = sslclientcert, sslclientkey = sslclientkey, sslcacertfile = sslcacertfile) diff --git a/offlineimap/repository/IMAP.py b/offlineimap/repository/IMAP.py index 0bc84eb..1d40a8f 100644 --- a/offlineimap/repository/IMAP.py +++ b/offlineimap/repository/IMAP.py @@ -79,9 +79,13 @@ class IMAPRepository(BaseRepository): self.imapserver.close() def getholdconnectionopen(self): + if self.getidlefolders(): + return 1 return self.getconfboolean("holdconnectionopen", 0) def getkeepalive(self): + if self.getidlefolders(): + return 29*60 return self.getconfint("keepalive", 0) def getsep(self): @@ -163,8 +167,14 @@ class IMAPRepository(BaseRepository): def getreference(self): return self.getconf('reference', '""') + def getidlefolders(self): + localeval = self.localeval + return localeval.eval(self.getconf('idlefolders', '[]')) + def getmaxconnections(self): - return self.getconfint('maxconnections', 1) + num1 = len(self.getidlefolders()) + num2 = self.getconfint('maxconnections', 1) + return max(num1, num2) def getexpunge(self): return self.getconfboolean('expunge', 1)