Browse Source

Add logs on email fetcher

Bastien Sevajol 7 years ago
parent
commit
3de125040b
1 changed files with 59 additions and 14 deletions
  1. 59 14
      tracim/tracim/lib/email_fetcher.py

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

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 
2
 
3
-import sys
4
 import time
3
 import time
5
 import imaplib
4
 import imaplib
6
-import datetime
7
 import json
5
 import json
8
 import typing
6
 import typing
9
 from email.message import Message
7
 from email.message import Message
10
-from email.header import Header, decode_header, make_header
11
-from email.utils import parseaddr, parsedate_tz, mktime_tz
8
+from email.header import decode_header
9
+from email.header import make_header
10
+from email.utils import parseaddr
12
 from email import message_from_bytes
11
 from email import message_from_bytes
13
 
12
 
14
 import markdown
13
 import markdown
15
 import requests
14
 import requests
16
-from bs4 import BeautifulSoup, Tag
15
+from bs4 import BeautifulSoup
16
+from bs4 import Tag
17
 from email_reply_parser import EmailReplyParser
17
 from email_reply_parser import EmailReplyParser
18
 
18
 
19
 from tracim.lib.base import logger
19
 from tracim.lib.base import logger
214
         self._is_active = True
214
         self._is_active = True
215
 
215
 
216
     def run(self) -> None:
216
     def run(self) -> None:
217
+        logger.info(self, 'Starting MailFetcher')
217
         while self._is_active:
218
         while self._is_active:
219
+            logger.debug(self, 'sleep for {}'.format(self.delay))
218
             time.sleep(self.delay)
220
             time.sleep(self.delay)
219
             try:
221
             try:
220
                 self._connect()
222
                 self._connect()
237
         # TODO - G.M - 2017-11-15 Verify connection/disconnection
239
         # TODO - G.M - 2017-11-15 Verify connection/disconnection
238
         # Are old connexion properly close this way ?
240
         # Are old connexion properly close this way ?
239
         if self._connection:
241
         if self._connection:
242
+            logger.debug(self, 'Disconnect from IMAP')
240
             self._disconnect()
243
             self._disconnect()
241
         # TODO - G.M - 2017-11-23 Support for predefined SSLContext ?
244
         # TODO - G.M - 2017-11-23 Support for predefined SSLContext ?
242
         # without ssl_context param, tracim use default security configuration
245
         # without ssl_context param, tracim use default security configuration
243
         # which is great in most case.
246
         # which is great in most case.
244
         if self.use_ssl:
247
         if self.use_ssl:
248
+            logger.debug(self, 'Connect IMAP {}:{} using SSL'.format(
249
+                self.host,
250
+                self.port,
251
+            ))
245
             self._connection = imaplib.IMAP4_SSL(self.host, self.port)
252
             self._connection = imaplib.IMAP4_SSL(self.host, self.port)
246
         else:
253
         else:
254
+            logger.debug(self, 'Connect IMAP {}:{}'.format(
255
+                self.host,
256
+                self.port,
257
+            ))
247
             self._connection = imaplib.IMAP4(self.host, self.port)
258
             self._connection = imaplib.IMAP4(self.host, self.port)
248
 
259
 
249
         try:
260
         try:
261
+            logger.debug(self, 'Login IMAP with login {}'.format(
262
+                self.user,
263
+            ))
250
             self._connection.login(self.user, self.password)
264
             self._connection.login(self.user, self.password)
251
         except Exception as e:
265
         except Exception as e:
252
             log = 'IMAP login error: {}'
266
             log = 'IMAP login error: {}'
253
-            logger.warning(self, log.format(e.__str__()))
267
+            logger.error(self, log.format(e.__str__()))
254
 
268
 
255
     def _disconnect(self) -> None:
269
     def _disconnect(self) -> None:
256
         if self._connection:
270
         if self._connection:
265
         """
279
         """
266
         messages = []
280
         messages = []
267
         # select mailbox
281
         # select mailbox
282
+        logger.debug(self, 'Fetch messages from folder {}'.format(
283
+            self.folder,
284
+        ))
268
         rv, data = self._connection.select(self.folder)
285
         rv, data = self._connection.select(self.folder)
286
+        logger.debug(self, 'Response status {}'.format(
287
+            rv,
288
+        ))
269
         if rv == 'OK':
289
         if rv == 'OK':
270
             # get mails
290
             # get mails
271
             # TODO - G.M -  2017-11-15 Which files to select as new file ?
291
             # TODO - G.M -  2017-11-15 Which files to select as new file ?
272
             # Unseen file or All file from a directory (old one should be
292
             # Unseen file or All file from a directory (old one should be
273
             #  moved/ deleted from mailbox during this process) ?
293
             #  moved/ deleted from mailbox during this process) ?
294
+            logger.debug(self, 'Fetch unseen messages')
274
             rv, data = self._connection.search(None, "(UNSEEN)")
295
             rv, data = self._connection.search(None, "(UNSEEN)")
296
+            logger.debug(self, 'Response status {}'.format(
297
+                rv,
298
+            ))
275
             if rv == 'OK':
299
             if rv == 'OK':
276
                 # get mail content
300
                 # get mail content
301
+                logger.debug(self, 'Found {} unseen mails'.format(
302
+                    len(data[0].split()),
303
+                ))
277
                 for num in data[0].split():
304
                 for num in data[0].split():
278
                     # INFO - G.M - 2017-11-23 - Fetch (RFC288) to retrieve all
305
                     # INFO - G.M - 2017-11-23 - Fetch (RFC288) to retrieve all
279
                     # complete mails see example : https://docs.python.org/fr/3.5/library/imaplib.html#imap4-example .  # nopep8
306
                     # complete mails see example : https://docs.python.org/fr/3.5/library/imaplib.html#imap4-example .  # nopep8
280
                     # Be careful, This method remove also mails from Unseen
307
                     # Be careful, This method remove also mails from Unseen
281
                     # mails
308
                     # mails
309
+                    logger.debug(self, 'Fetch mail "{}"'.format(
310
+                        num,
311
+                    ))
282
                     rv, data = self._connection.fetch(num, '(RFC822)')
312
                     rv, data = self._connection.fetch(num, '(RFC822)')
313
+                    logger.debug(self, 'Response status {}'.format(
314
+                        rv,
315
+                    ))
283
                     if rv == 'OK':
316
                     if rv == 'OK':
284
                         msg = message_from_bytes(data[0][1])
317
                         msg = message_from_bytes(data[0][1])
285
                         messages.append(msg)
318
                         messages.append(msg)
286
                     else:
319
                     else:
287
                         log = 'IMAP : Unable to get mail : {}'
320
                         log = 'IMAP : Unable to get mail : {}'
288
-                        logger.debug(self, log.format(str(rv)))
321
+                        logger.error(self, log.format(str(rv)))
289
             else:
322
             else:
290
-                # FIXME : Distinct error from empty mailbox ?
291
-                pass
323
+                log = 'IMAP : Unable to get unseen mail : {}'
324
+                logger.error(self, log.format(str(rv)))
292
         else:
325
         else:
293
             log = 'IMAP : Unable to open mailbox : {}'
326
             log = 'IMAP : Unable to open mailbox : {}'
294
-            logger.debug(self, log.format(str(rv)))
327
+            logger.error(self, log.format(str(rv)))
295
         return messages
328
         return messages
296
 
329
 
297
     def _notify_tracim(
330
     def _notify_tracim(
303
         :param mails: list of mails to send
336
         :param mails: list of mails to send
304
         :return: unsended mails
337
         :return: unsended mails
305
         """
338
         """
339
+        logger.debug(self, 'Notify tracim about {} new responses'.format(
340
+            len(mails),
341
+        ))
306
         unsended_mails = []
342
         unsended_mails = []
307
         # TODO BS 20171124: Look around mail.get_from_address(), mail.get_key()
343
         # TODO BS 20171124: Look around mail.get_from_address(), mail.get_key()
308
         # , mail.get_body() etc ... for raise InvalidEmailError if missing
344
         # , mail.get_body() etc ... for raise InvalidEmailError if missing
317
                        'content': mail.get_body(),
353
                        'content': mail.get_body(),
318
                    }}
354
                    }}
319
             try:
355
             try:
356
+                logger.debug(
357
+                    self,
358
+                    'Contact API on {} with body {}'.format(
359
+                        self.endpoint,
360
+                        json.dumps(msg),
361
+                    ),
362
+                )
320
                 r = requests.post(self.endpoint, json=msg)
363
                 r = requests.post(self.endpoint, json=msg)
321
                 if r.status_code not in [200, 204]:
364
                 if r.status_code not in [200, 204]:
322
-                    log = 'bad status code response when sending mail to tracim: {}'  # nopep8
323
-                    logger.error(self, log.format(str(r.status_code)))
365
+                    details = r.json().get('msg')
366
+                    log = 'bad status code {} response when sending mail to tracim: {}'  # nopep8
367
+                    logger.error(self, log.format(
368
+                        str(r.status_code),
369
+                        details,
370
+                    ))
324
             # TODO - G.M - Verify exception correctly works
371
             # TODO - G.M - Verify exception correctly works
325
             except requests.exceptions.Timeout as e:
372
             except requests.exceptions.Timeout as e:
326
                 log = 'Timeout error to transmit fetched mail to tracim : {}'
373
                 log = 'Timeout error to transmit fetched mail to tracim : {}'
327
                 logger.error(self, log.format(str(e)))
374
                 logger.error(self, log.format(str(e)))
328
                 unsended_mails.append(mail)
375
                 unsended_mails.append(mail)
329
-                break
330
             except requests.exceptions.RequestException as e:
376
             except requests.exceptions.RequestException as e:
331
                 log = 'Fail to transmit fetched mail to tracim : {}'
377
                 log = 'Fail to transmit fetched mail to tracim : {}'
332
                 logger.error(self, log.format(str(e)))
378
                 logger.error(self, log.format(str(e)))
333
-                break
334
 
379
 
335
         return unsended_mails
380
         return unsended_mails