|
@@ -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
|
+
|
|
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
|
|
-
|
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
|
|
244
|
259
|
|
245
|
260
|
|