Sfoglia il codice sorgente

Email_Fetcher : Close properly connections and better error handler

Guénaël Muller 6 anni fa
parent
commit
bdd133cca2
1 ha cambiato i file con 48 aggiunte e 8 eliminazioni
  1. 48 8
      tracim/tracim/lib/email_fetcher.py

+ 48 - 8
tracim/tracim/lib/email_fetcher.py Vedi File

@@ -25,9 +25,15 @@ CONTENT_TYPE_TEXT_HTML = 'text/html'
25 25
 
26 26
 IMAP_SEEN_FLAG = SEEN
27 27
 IMAP_CHECKED_FLAG = FLAGGED
28
+
28 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 38
 class MessageContainer(object):
33 39
     def __init__(self, message: Message, uid: int) -> None:
@@ -195,27 +201,49 @@ class MailFetcher(object):
195 201
     def run(self) -> None:
196 202
         logger.info(self, 'Starting MailFetcher')
197 203
         while self._is_active:
204
+
205
+            # login/connection
198 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 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 222
                 logger.debug(self, 'Select folder {}'.format(
203 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 229
                 while time.time() < deadline:
230
+                    # check for new mails
207 231
                     self._check_mail(imapc)
208 232
 
209 233
                     if IDLE_MODE and imapc.has_capability('IDLE'):
234
+                        # IDLE_mode: wait until event from server
210 235
                         logger.debug(self, 'wail for event(IDLE)')
211 236
                         imapc.idle()
212 237
                         imapc.idle_check(
213
-                            timeout=MAIL_FETCHER_CONNECTION_TIMEOUT
238
+                            timeout=MAIL_FETCHER_IDLE_RESPONSE_TIMEOUT
214 239
                         )
215 240
                         imapc.idle_done()
216 241
                     else:
242
+                        # normal polling mode : sleep a define duration
217 243
                         logger.debug(self, 'sleep for {}'.format(self.delay))
218 244
                         time.sleep(self.delay)
245
+
246
+                logger.debug(self,"Lifetime limit excess, Renew connection")
219 247
             except filelock.Timeout as e:
220 248
                 log = 'Mail Fetcher Lock Timeout {}'
221 249
                 logger.warning(self, log.format(e.__str__()))
@@ -223,7 +251,20 @@ class MailFetcher(object):
223 251
                 log = 'Mail Fetcher error {}'
224 252
                 logger.error(self, log.format(e.__str__()))
225 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 269
     def _check_mail(self, imapc: IMAPClient) -> None:
229 270
         with self.lock.acquire(
@@ -244,7 +285,6 @@ class MailFetcher(object):
244 285
         """
245 286
         messages = []
246 287
 
247
-        imapc.select_folder(self.folder)
248 288
         logger.debug(self, 'Fetch unseen messages')
249 289
         uids = imapc.search(['UNSEEN'])
250 290
         logger.debug(self, 'Found {} unseen mails'.format(