Guénaël Muller 6 år sedan
förälder
incheckning
b1c4767274
1 ändrade filer med 34 tillägg och 19 borttagningar
  1. 34 19
      tracim/tracim/lib/email_fetcher.py

+ 34 - 19
tracim/tracim/lib/email_fetcher.py Visa fil

@@ -26,7 +26,8 @@ CONTENT_TYPE_TEXT_HTML = 'text/html'
26 26
 IMAP_SEEN_FLAG = SEEN
27 27
 IMAP_CHECKED_FLAG = FLAGGED
28 28
 MAIL_FETCHER_FILELOCK_TIMEOUT = 10
29
-
29
+MAIL_FETCHER_CONNECTION_TIMEOUT = 60*9
30
+IDLE_MODE = True
30 31
 
31 32
 class MessageContainer(object):
32 33
     def __init__(self, message: Message, uid: int) -> None:
@@ -196,16 +197,25 @@ class MailFetcher(object):
196 197
         while self._is_active:
197 198
             try:
198 199
                 imapc = IMAPClient(self.host, ssl=self.use_ssl)
199
-                logger.debug(self, 'sleep for {}'.format(self.delay))
200
-                time.sleep(self.delay)
201 200
                 imapc.login(self.user, self.password)
202
-                with self.lock.acquire(
203
-                        timeout=MAIL_FETCHER_FILELOCK_TIMEOUT
204
-                ):
205
-                    messages = self._fetch(imapc)
206
-                    cleaned_mails = [DecodedMail(m.message, m.uid)
207
-                                     for m in messages]
208
-                    self._notify_tracim(cleaned_mails, imapc)
201
+                # select mailbox
202
+                logger.debug(self, 'Select folder {}'.format(
203
+                    self.folder,
204
+                ))
205
+                deadline = time.time() + MAIL_FETCHER_CONNECTION_TIMEOUT
206
+                while time.time() < deadline:
207
+                    self._check_mail(imapc)
208
+
209
+                    if IDLE_MODE and imapc.has_capability('IDLE'):
210
+                        logger.debug(self, 'wail for event(IDLE)')
211
+                        imapc.idle()
212
+                        imapc.idle_check(
213
+                            timeout=MAIL_FETCHER_CONNECTION_TIMEOUT
214
+                        )
215
+                        imapc.idle_done()
216
+                    else:
217
+                        logger.debug(self, 'sleep for {}'.format(self.delay))
218
+                        time.sleep(self.delay)
209 219
             except filelock.Timeout as e:
210 220
                 log = 'Mail Fetcher Lock Timeout {}'
211 221
                 logger.warning(self, log.format(e.__str__()))
@@ -215,31 +225,36 @@ class MailFetcher(object):
215 225
             finally:
216 226
                 imapc.logout()
217 227
 
228
+    def _check_mail(self, imapc: IMAPClient) -> None:
229
+        with self.lock.acquire(
230
+                timeout=MAIL_FETCHER_FILELOCK_TIMEOUT
231
+        ):
232
+            messages = self._fetch(imapc)
233
+            cleaned_mails = [DecodedMail(m.message, m.uid)
234
+                             for m in messages]
235
+            self._notify_tracim(cleaned_mails, imapc)
236
+
218 237
     def stop(self) -> None:
219 238
         self._is_active = False
220 239
 
221
-    def _fetch(self, imapclient: IMAPClient) -> typing.List[MessageContainer]:
240
+    def _fetch(self, imapc: IMAPClient) -> typing.List[MessageContainer]:
222 241
         """
223 242
         Get news message from mailbox
224 243
         :return: list of new mails
225 244
         """
226 245
         messages = []
227
-        # select mailbox
228
-        logger.debug(self, 'Fetch messages from folder {}'.format(
229
-            self.folder,
230
-        ))
231 246
 
232
-        imapclient.select_folder(self.folder)
247
+        imapc.select_folder(self.folder)
233 248
         logger.debug(self, 'Fetch unseen messages')
234
-        uids = imapclient.search(['UNSEEN'])
249
+        uids = imapc.search(['UNSEEN'])
235 250
         logger.debug(self, 'Found {} unseen mails'.format(
236 251
             len(uids),
237 252
         ))
238
-        imapclient.add_flags(uids, IMAP_SEEN_FLAG)
253
+        imapc.add_flags(uids, IMAP_SEEN_FLAG)
239 254
         logger.debug(self, 'Temporary Flag {} mails as seen'.format(
240 255
             len(uids),
241 256
         ))
242
-        for msgid, data in imapclient.fetch(uids, ['BODY.PEEK[]']).items():
257
+        for msgid, data in imapc.fetch(uids, ['BODY.PEEK[]']).items():
243 258
             # INFO - G.M - 2017-12-08 - Fetch BODY.PEEK[]
244 259
             # Retrieve all mail(body and header) but don't set mail
245 260
             # as seen because of PEEK