浏览代码

Email_Fetcher : Close properly connections and better error handler

Guénaël Muller 7 年前
父节点
当前提交
bdd133cca2
共有 1 个文件被更改,包括 48 次插入8 次删除
  1. 48 8
      tracim/tracim/lib/email_fetcher.py

+ 48 - 8
tracim/tracim/lib/email_fetcher.py 查看文件

25
 
25
 
26
 IMAP_SEEN_FLAG = SEEN
26
 IMAP_SEEN_FLAG = SEEN
27
 IMAP_CHECKED_FLAG = FLAGGED
27
 IMAP_CHECKED_FLAG = FLAGGED
28
+
28
 MAIL_FETCHER_FILELOCK_TIMEOUT = 10
29
 MAIL_FETCHER_FILELOCK_TIMEOUT = 10
29
-MAIL_FETCHER_CONNECTION_TIMEOUT = 60*9
30
-IDLE_MODE = True
30
+MAIL_FETCHER_CONNECTION_TIMEOUT = 60*3
31
+MAIL_FETCHER_CONNECTION_MAX_LIFETIME = 60*10
32
+MAIL_FETCHER_IDLE_RESPONSE_TIMEOUT = 60*9   # this should be not more
33
+# that 29 minutes according to rfc2177.(server wait 30min by default)
34
+
35
+IDLE_MODE = False
36
+
31
 
37
 
32
 class MessageContainer(object):
38
 class MessageContainer(object):
33
     def __init__(self, message: Message, uid: int) -> None:
39
     def __init__(self, message: Message, uid: int) -> None:
195
     def run(self) -> None:
201
     def run(self) -> None:
196
         logger.info(self, 'Starting MailFetcher')
202
         logger.info(self, 'Starting MailFetcher')
197
         while self._is_active:
203
         while self._is_active:
204
+
205
+            # login/connection
198
             try:
206
             try:
199
-                imapc = IMAPClient(self.host, self.port, ssl=self.use_ssl)
207
+                imapc = IMAPClient(self.host,
208
+                                   self.port,
209
+                                   ssl=self.use_ssl,
210
+                                   timeout=MAIL_FETCHER_CONNECTION_TIMEOUT)
200
                 imapc.login(self.user, self.password)
211
                 imapc.login(self.user, self.password)
201
-                # select mailbox
212
+            except Exception as e:
213
+                log = 'Fail to connect to IMAP {}'
214
+                logger.error(self, log.format(e.__str__()))
215
+                logger.debug(self, 'sleep for {}'.format(self.delay))
216
+                time.sleep(self.delay)
217
+                continue
218
+
219
+            # fetching
220
+            try:
221
+                # select folder
202
                 logger.debug(self, 'Select folder {}'.format(
222
                 logger.debug(self, 'Select folder {}'.format(
203
                     self.folder,
223
                     self.folder,
204
                 ))
224
                 ))
205
-                deadline = time.time() + MAIL_FETCHER_CONNECTION_TIMEOUT
225
+                imapc.select_folder(self.folder)
226
+
227
+                # force renew connection when deadline is reached
228
+                deadline = time.time() + MAIL_FETCHER_CONNECTION_MAX_LIFETIME
206
                 while time.time() < deadline:
229
                 while time.time() < deadline:
230
+                    # check for new mails
207
                     self._check_mail(imapc)
231
                     self._check_mail(imapc)
208
 
232
 
209
                     if IDLE_MODE and imapc.has_capability('IDLE'):
233
                     if IDLE_MODE and imapc.has_capability('IDLE'):
234
+                        # IDLE_mode: wait until event from server
210
                         logger.debug(self, 'wail for event(IDLE)')
235
                         logger.debug(self, 'wail for event(IDLE)')
211
                         imapc.idle()
236
                         imapc.idle()
212
                         imapc.idle_check(
237
                         imapc.idle_check(
213
-                            timeout=MAIL_FETCHER_CONNECTION_TIMEOUT
238
+                            timeout=MAIL_FETCHER_IDLE_RESPONSE_TIMEOUT
214
                         )
239
                         )
215
                         imapc.idle_done()
240
                         imapc.idle_done()
216
                     else:
241
                     else:
242
+                        # normal polling mode : sleep a define duration
217
                         logger.debug(self, 'sleep for {}'.format(self.delay))
243
                         logger.debug(self, 'sleep for {}'.format(self.delay))
218
                         time.sleep(self.delay)
244
                         time.sleep(self.delay)
245
+
246
+                logger.debug(self,"Lifetime limit excess, Renew connection")
219
             except filelock.Timeout as e:
247
             except filelock.Timeout as e:
220
                 log = 'Mail Fetcher Lock Timeout {}'
248
                 log = 'Mail Fetcher Lock Timeout {}'
221
                 logger.warning(self, log.format(e.__str__()))
249
                 logger.warning(self, log.format(e.__str__()))
223
                 log = 'Mail Fetcher error {}'
251
                 log = 'Mail Fetcher error {}'
224
                 logger.error(self, log.format(e.__str__()))
252
                 logger.error(self, log.format(e.__str__()))
225
             finally:
253
             finally:
226
-                imapc.logout()
254
+                # INFO - G.M - 2018-01-09 - Connection closing
255
+                # Properly close connection according to
256
+                # https://github.com/mjs/imapclient/pull/279/commits/043e4bd0c5c775c5a08cb5f1baa93876a46732ee
257
+                # TODO : Use __exit__ method instead when imapclient stable will
258
+                # be 2.0+ .
259
+                logger.debug(self, 'Try logout')
260
+                try:
261
+                    imapc.logout()
262
+                except Exception:
263
+                    try:
264
+                        imapc.shutdown()
265
+                    except Exception as e:
266
+                        log = "Can't logout, connection broken ? {}"
267
+                        logger.error(self, log.format(e.__str__()))
227
 
268
 
228
     def _check_mail(self, imapc: IMAPClient) -> None:
269
     def _check_mail(self, imapc: IMAPClient) -> None:
229
         with self.lock.acquire(
270
         with self.lock.acquire(
244
         """
285
         """
245
         messages = []
286
         messages = []
246
 
287
 
247
-        imapc.select_folder(self.folder)
248
         logger.debug(self, 'Fetch unseen messages')
288
         logger.debug(self, 'Fetch unseen messages')
249
         uids = imapc.search(['UNSEEN'])
289
         uids = imapc.search(['UNSEEN'])
250
         logger.debug(self, 'Found {} unseen mails'.format(
290
         logger.debug(self, 'Found {} unseen mails'.format(