| 
				
			 | 
			
			
				@@ -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( 
			 |