Browse Source

MailFetcher: Flag message as seen only when tracim rest request success

Guénaël Muller 6 years ago
parent
commit
ef63bbe0da
1 changed files with 36 additions and 14 deletions
  1. 36 14
      tracim/tracim/lib/email_fetcher.py

+ 36 - 14
tracim/tracim/lib/email_fetcher.py View File

@@ -22,9 +22,16 @@ CONTENT_TYPE_TEXT_PLAIN = 'text/plain'
22 22
 CONTENT_TYPE_TEXT_HTML = 'text/html'
23 23
 
24 24
 
25
+class MessageContainer(object):
26
+    def __init__(self, message: Message, uid: int) -> None:
27
+        self.message = message
28
+        self.uid = uid
29
+
30
+
25 31
 class DecodedMail(object):
26
-    def __init__(self, message: Message) -> None:
32
+    def __init__(self, message: Message, uid: int=None) -> None:
27 33
         self._message = message
34
+        self.uid = uid
28 35
 
29 36
     def _decode_header(self, header_title: str) -> typing.Optional[str]:
30 37
         # FIXME : Handle exception
@@ -186,10 +193,8 @@ class MailFetcher(object):
186 193
             try:
187 194
                 self._connect()
188 195
                 messages = self._fetch()
189
-                # TODO - G.M -  2017-11-22 retry sending unsended mail
190
-                # These mails are return by _notify_tracim, flag them with "unseen" # nopep8
191
-                # or store them until new _notify_tracim call
192
-                cleaned_mails = [DecodedMail(msg) for msg in messages]
196
+                cleaned_mails = [DecodedMail(m.message, m.uid)
197
+                                 for m in messages]
193 198
                 self._notify_tracim(cleaned_mails)
194 199
                 self._disconnect()
195 200
             except Exception as e:
@@ -237,7 +242,7 @@ class MailFetcher(object):
237 242
             self._connection.logout()
238 243
             self._connection = None
239 244
 
240
-    def _fetch(self) -> typing.List[Message]:
245
+    def _fetch(self) -> typing.List[MessageContainer]:
241 246
         """
242 247
         Get news message from mailbox
243 248
         :return: list of new mails
@@ -266,21 +271,22 @@ class MailFetcher(object):
266 271
                 logger.debug(self, 'Found {} unseen mails'.format(
267 272
                     len(data[0].split()),
268 273
                 ))
269
-                for num in data[0].split():
270
-                    # INFO - G.M - 2017-11-23 - Fetch (RFC288) to retrieve all
271
-                    # complete mails see example : https://docs.python.org/fr/3.5/library/imaplib.html#imap4-example .  # nopep8
272
-                    # Be careful, This method remove also mails from Unseen
273
-                    # mails
274
+                for uid in data[0].split():
275
+                    # INFO - G.M - 2017-12-08 - Fetch BODY.PEEK[]
276
+                    # Retrieve all mail(body and header) but don't set mail
277
+                    # as seen because of PEEK
278
+                    # see rfc3501
274 279
                     logger.debug(self, 'Fetch mail "{}"'.format(
275
-                        num,
280
+                        uid,
276 281
                     ))
277
-                    rv, data = self._connection.fetch(num, '(RFC822)')
282
+                    rv, data = self._connection.fetch(uid, 'BODY.PEEK[]')
278 283
                     logger.debug(self, 'Response status {}'.format(
279 284
                         rv,
280 285
                     ))
281 286
                     if rv == 'OK':
282 287
                         msg = message_from_bytes(data[0][1])
283
-                        messages.append(msg)
288
+                        msg_container = MessageContainer(msg, uid)
289
+                        messages.append(msg_container)
284 290
                     else:
285 291
                         log = 'IMAP : Unable to get mail : {}'
286 292
                         logger.error(self, log.format(str(rv)))
@@ -335,6 +341,8 @@ class MailFetcher(object):
335 341
                         str(r.status_code),
336 342
                         details,
337 343
                     ))
344
+                else:
345
+                    self._set_flag(mail.uid)
338 346
             # TODO - G.M - Verify exception correctly works
339 347
             except requests.exceptions.Timeout as e:
340 348
                 log = 'Timeout error to transmit fetched mail to tracim : {}'
@@ -345,3 +353,17 @@ class MailFetcher(object):
345 353
                 logger.error(self, log.format(str(e)))
346 354
 
347 355
         return unsended_mails
356
+
357
+    def _set_flag(self, uid):
358
+        assert uid is not None
359
+        rv, data = self._connection.store(
360
+            uid,
361
+            '+FLAGS',
362
+            '\\Seen'
363
+        )
364
+        if rv == 'OK':
365
+            log = 'Message {} set as seen.'.format(uid)
366
+            logger.debug(self, log)
367
+        else:
368
+            log = 'Can not set Message {} as seen : {}'.format(uid, rv)
369
+            logger.error(self, log)