Просмотр исходного кода

Merge pull request #334 from tracim/fix/278/log_notification_metadata

Damien Accorsi 7 лет назад
Родитель
Сommit
a2e4b27d49

+ 1 - 0
tracim/development.ini.base Просмотреть файл

@@ -184,6 +184,7 @@ website.base_url = http://127.0.0.1:8080
184 184
 website.server_name = 127.0.0.1
185 185
 
186 186
 email.notification.activated = False
187
+# email.notification.log_file_path = /tmp/mail-notifications.log
187 188
 # email notifications can be sent with the user_id added as an identifier
188 189
 # this way email clients like Thunderbird will be able to distinguish
189 190
 # notifications generated by a user or another one

+ 1 - 0
tracim/test.ini Просмотреть файл

@@ -15,6 +15,7 @@ radicale.server.filesystem.folder = /tmp/tracim_tests_radicale_fs
15 15
 radicale.client.base_url.host = http://localhost:15232
16 16
 radicale.client.base_url.prefix = /
17 17
 email.notification.activated = false
18
+email.notification.log_file_path = /tmp/mail-notifications-test.log
18 19
 
19 20
 [server:main]
20 21
 use = egg:gearbox#wsgiref

+ 4 - 0
tracim/tracim/config/app_cfg.py Просмотреть файл

@@ -339,6 +339,10 @@ class CFG(object):
339 339
         self.EMAIL_NOTIFICATION_SMTP_PASSWORD = tg.config.get(
340 340
             'email.notification.smtp.password',
341 341
         )
342
+        self.EMAIL_NOTIFICATION_LOG_FILE_PATH = tg.config.get(
343
+            'email.notification.log_file_path',
344
+            None,
345
+        )
342 346
 
343 347
         self.TRACKER_JS_PATH = tg.config.get(
344 348
             'js_tracker_path',

+ 9 - 6
tracim/tracim/lib/email.py Просмотреть файл

@@ -1,17 +1,16 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import smtplib
3
+import typing
3 4
 from email.message import Message
4 5
 from email.mime.multipart import MIMEMultipart
5 6
 from email.mime.text import MIMEText
6 7
 
7
-import typing
8 8
 from mako.template import Template
9 9
 from tg.i18n import ugettext as _
10 10
 
11 11
 from tracim.lib.base import logger
12
-from tracim.model import User
13
-
14 12
 from tracim.lib.utils import get_rq_queue
13
+from tracim.model import User
15 14
 
16 15
 
17 16
 def send_email_through(
@@ -53,7 +52,6 @@ class SmtpConfiguration(object):
53 52
         self.password = password
54 53
 
55 54
 
56
-
57 55
 class EmailSender(object):
58 56
     """
59 57
     this class allow to send emails and has no relations with SQLAlchemy and other tg HTTP request environment
@@ -86,14 +84,19 @@ class EmailSender(object):
86 84
             self._smtp_connection.quit()
87 85
             logger.info(self, 'Connection closed.')
88 86
 
89
-
90 87
     def send_mail(self, message: MIMEMultipart):
91 88
         if not self._is_active:
92 89
             logger.info(self, 'Not sending email to {} (service desactivated)'.format(message['To']))
93 90
         else:
94
-            self.connect() # Acutally, this connects to SMTP only if required
91
+            self.connect()  # Acutally, this connects to SMTP only if required
95 92
             logger.info(self, 'Sending email to {}'.format(message['To']))
96 93
             self._smtp_connection.send_message(message)
94
+            from tracim.lib.notifications import EmailNotifier
95
+            EmailNotifier.log_notification(
96
+                action='   SENT',
97
+                recipient=message['To'],
98
+                subject=message['Subject'],
99
+            )
97 100
 
98 101
 
99 102
 class EmailManager(object):

+ 38 - 8
tracim/tracim/lib/notifications.py Просмотреть файл

@@ -1,29 +1,31 @@
1 1
 # -*- coding: utf-8 -*-
2
+import datetime
3
+import typing
2 4
 
3 5
 from email.header import Header
4 6
 from email.mime.multipart import MIMEMultipart
5 7
 from email.mime.text import MIMEText
6 8
 
7
-import lxml
8 9
 from lxml.html.diff import htmldiff
9 10
 
10 11
 from mako.template import Template
11 12
 
12 13
 from tracim.lib.base import logger
14
+from tracim.lib.email import EmailSender
13 15
 from tracim.lib.email import SmtpConfiguration
14 16
 from tracim.lib.email import send_email_through
15
-from tracim.lib.email import EmailSender
16 17
 from tracim.lib.user import UserApi
17
-from tracim.lib.workspace import WorkspaceApi
18 18
 from tracim.lib.utils import lazy_ugettext as l_
19
-from tracim.model.serializers import Context
19
+from tracim.lib.workspace import WorkspaceApi
20
+from tracim.model.auth import User
21
+from tracim.model.data import ActionDescription
22
+from tracim.model.data import Content
23
+from tracim.model.data import ContentType
24
+from tracim.model.data import UserRoleInWorkspace
20 25
 from tracim.model.serializers import CTX
26
+from tracim.model.serializers import Context
21 27
 from tracim.model.serializers import DictLikeClass
22 28
 
23
-from tracim.model.data import Content, UserRoleInWorkspace, ContentType, \
24
-    ActionDescription
25
-from tracim.model.auth import User
26
-
27 29
 
28 30
 class INotifier(object):
29 31
     """
@@ -210,6 +212,29 @@ class EmailNotifier(object):
210 212
             email_address = email_address
211 213
         )
212 214
 
215
+    @staticmethod
216
+    def log_notification(
217
+            action: str,
218
+            recipient: typing.Optional[str],
219
+            subject: typing.Optional[str],
220
+    ) -> None:
221
+        """Log notification metadata."""
222
+        from tracim.config.app_cfg import CFG
223
+        log_path = CFG.get_instance().EMAIL_NOTIFICATION_LOG_FILE_PATH
224
+        if log_path:
225
+            # TODO - A.P - 2017-09-06 - file logging inefficiency
226
+            # Updating a document with 100 users to notify will leads to open
227
+            # and close the file 100 times.
228
+            with open(log_path, 'a') as log_file:
229
+                print(
230
+                    datetime.datetime.now(),
231
+                    action,
232
+                    recipient,
233
+                    subject,
234
+                    sep='|',
235
+                    file=log_file,
236
+                )
237
+
213 238
     def notify_content_update(self, event_actor_id: int, event_content_id: int):
214 239
         """
215 240
         Look for all users to be notified about the new content and send them an individual email
@@ -277,6 +302,11 @@ class EmailNotifier(object):
277 302
             message.attach(part1)
278 303
             message.attach(part2)
279 304
 
305
+            self.log_notification(
306
+                action='CREATED',
307
+                recipient=message['To'],
308
+                subject=message['Subject'],
309
+            )
280 310
             send_email_through(async_email_sender.send_mail, message)
281 311
 
282 312
     def _build_email_body(self, mako_template_filepath: str, role: UserRoleInWorkspace, content: Content, actor: User) -> str:

+ 41 - 8
tracim/tracim/tests/library/test_notification.py Просмотреть файл

@@ -1,12 +1,9 @@
1 1
 # -*- coding: utf-8 -*-
2
+import os
3
+import re
2 4
 
3 5
 from nose.tools import eq_
4 6
 from nose.tools import ok_
5
-from nose.tools import raises
6
-
7
-from sqlalchemy.orm.exc import NoResultFound
8
-
9
-import transaction
10 7
 
11 8
 from tracim.config.app_cfg import CFG
12 9
 from tracim.lib.notifications import DummyNotifier
@@ -16,7 +13,6 @@ from tracim.lib.notifications import NotifierFactory
16 13
 from tracim.lib.notifications import RealNotifier
17 14
 from tracim.model.auth import User
18 15
 from tracim.model.data import Content
19
-
20 16
 from tracim.tests import TestStandard
21 17
 
22 18
 
@@ -43,7 +39,7 @@ class TestDummyNotifier(TestStandard):
43 39
     def test_email_subject_tag_list(self):
44 40
         tags = EST.all()
45 41
 
46
-        eq_(4,len(tags))
42
+        eq_(4, len(tags))
47 43
         ok_('{website_title}' in tags)
48 44
         ok_('{workspace_label}' in tags)
49 45
         ok_('{content_label}' in tags)
@@ -51,6 +47,44 @@ class TestDummyNotifier(TestStandard):
51 47
 
52 48
 
53 49
 class TestEmailNotifier(TestStandard):
50
+
51
+    def test_unit__log_notification(self):
52
+        """Check file and format of notification log."""
53
+        log_path = CFG.get_instance().EMAIL_NOTIFICATION_LOG_FILE_PATH
54
+        pattern = '\|{act}\|{rec}\|{subj}$\\n'
55
+        line_1_act = 'CREATED'
56
+        line_1_rec = 'user 1 <us.er@o.ne>'
57
+        line_1_subj = 'notification 1'
58
+        line_1_pattern = pattern.format(
59
+            act=line_1_act,
60
+            rec=line_1_rec,
61
+            subj=line_1_subj,
62
+        )
63
+        line_2_act = '   SENT'
64
+        line_2_rec = 'user 2 <us.er@t.wo>'
65
+        line_2_subj = 'notification 2'
66
+        line_2_pattern = pattern.format(
67
+            act=line_2_act,
68
+            rec=line_2_rec,
69
+            subj=line_2_subj,
70
+        )
71
+        EmailNotifier.log_notification(
72
+            action=line_1_act,
73
+            recipient=line_1_rec,
74
+            subject=line_1_subj,
75
+        )
76
+        EmailNotifier.log_notification(
77
+            action=line_2_act,
78
+            recipient=line_2_rec,
79
+            subject=line_2_subj,
80
+        )
81
+        with open(log_path, 'rt') as log_file:
82
+            line_1 = log_file.readline()
83
+            line_2 = log_file.readline()
84
+        os.remove(path=log_path)
85
+        ok_(re.search(pattern=line_1_pattern, string=line_1))
86
+        ok_(re.search(pattern=line_2_pattern, string=line_2))
87
+
54 88
     def test_email_notifier__build_name_with_user_id(self):
55 89
         u = User()
56 90
         u.user_id = 3
@@ -95,4 +129,3 @@ class TestEmailNotifier(TestStandard):
95 129
         notifier = EmailNotifier(smtp_config=None, global_config=config)
96 130
         email = notifier._get_sender()
97 131
         eq_('Robot <noreply@tracim.io>', email)
98
-