Browse Source

Merge pull request #365 from tracim/smtplib-with-no-auth

Damien Accorsi 7 years ago
parent
commit
403a24eba5

+ 10 - 2
tracim/tracim/controllers/admin/user.py View File

344
 
344
 
345
         api.save(user)
345
         api.save(user)
346
 
346
 
347
+        email_sent = True
347
         if send_email:
348
         if send_email:
348
             email_manager = get_email_manager()
349
             email_manager = get_email_manager()
349
-            email_manager.notify_created_account(user, password=password)
350
+            try:
351
+                email_manager.notify_created_account(user, password=password)
352
+            except Exception:
353
+                email_sent = False
350
 
354
 
351
         api.execute_created_user_actions(user)
355
         api.execute_created_user_actions(user)
352
-        tg.flash(_('User {} created.').format(user.get_display_name()), CST.STATUS_OK)
356
+        if not email_sent:
357
+            tg.flash(_('User {0} created but email was not sent to {1}').format(user.get_display_name(), user.email),
358
+                     CST.STATUS_WARNING)
359
+        else:
360
+            tg.flash(_('User {} created.').format(user.get_display_name()), CST.STATUS_OK)
353
         tg.redirect(self.url())
361
         tg.redirect(self.url())
354
 
362
 
355
     @classmethod
363
     @classmethod

BIN
tracim/tracim/i18n/en/LC_MESSAGES/tracim.mo View File


+ 38 - 16
tracim/tracim/lib/email.py View File

19
 ) -> None:
19
 ) -> None:
20
     """
20
     """
21
     Send mail encapsulation to send it in async or sync mode.
21
     Send mail encapsulation to send it in async or sync mode.
22
+
22
     TODO BS 20170126: A global mail/sender management should be a good
23
     TODO BS 20170126: A global mail/sender management should be a good
23
                       thing. Actually, this method is an fast solution.
24
                       thing. Actually, this method is an fast solution.
24
     :param sendmail_callable: A callable who get message on first parameter
25
     :param sendmail_callable: A callable who get message on first parameter
41
 
42
 
42
 
43
 
43
 class SmtpConfiguration(object):
44
 class SmtpConfiguration(object):
44
-    """
45
-    Container class for SMTP configuration used in Tracim
46
-    """
45
+    """Container class for SMTP configuration used in Tracim."""
47
 
46
 
48
     def __init__(self, server: str, port: int, login: str, password: str):
47
     def __init__(self, server: str, port: int, login: str, password: str):
49
         self.server = server
48
         self.server = server
54
 
53
 
55
 class EmailSender(object):
54
 class EmailSender(object):
56
     """
55
     """
57
-    this class allow to send emails and has no relations with SQLAlchemy and other tg HTTP request environment
58
-    This means that it can be used in any thread (even through a asyncjob_perform() call
56
+    Independent email sender class.
57
+
58
+    To allow its use in any thread, as an asyncjob_perform() call for
59
+    example, it has no dependencies on SQLAlchemy nor tg HTTP request.
59
     """
60
     """
61
+
60
     def __init__(self, config: SmtpConfiguration, really_send_messages):
62
     def __init__(self, config: SmtpConfiguration, really_send_messages):
61
         self._smtp_config = config
63
         self._smtp_config = config
62
         self._smtp_connection = None
64
         self._smtp_connection = None
64
 
66
 
65
     def connect(self):
67
     def connect(self):
66
         if not self._smtp_connection:
68
         if not self._smtp_connection:
67
-            logger.info(self, 'Connecting from SMTP server {}'.format(self._smtp_config.server))
68
-            self._smtp_connection = smtplib.SMTP(self._smtp_config.server, self._smtp_config.port)
69
+            log = 'Connecting from SMTP server {}'
70
+            logger.info(self, log.format(self._smtp_config.server))
71
+            self._smtp_connection = smtplib.SMTP(
72
+                self._smtp_config.server,
73
+                self._smtp_config.port
74
+            )
69
             self._smtp_connection.ehlo()
75
             self._smtp_connection.ehlo()
76
+
70
             if self._smtp_config.login:
77
             if self._smtp_config.login:
71
                 try:
78
                 try:
72
                     starttls_result = self._smtp_connection.starttls()
79
                     starttls_result = self._smtp_connection.starttls()
73
-                    logger.debug(self, 'SMTP start TLS result: {}'.format(starttls_result))
80
+                    log = 'SMTP start TLS result: {}'
81
+                    logger.debug(self, log.format(starttls_result))
74
                 except Exception as e:
82
                 except Exception as e:
75
-                    logger.debug(self, 'SMTP start TLS error: {}'.format(e.__str__()))
83
+                    log = 'SMTP start TLS error: {}'
84
+                    logger.debug(self, log.format(e.__str__()))
76
 
85
 
77
-            login_res = self._smtp_connection.login(self._smtp_config.login, self._smtp_config.password)
78
-            logger.debug(self, 'SMTP login result: {}'.format(login_res))
86
+            if self._smtp_config.login:
87
+                try:
88
+                    login_res = self._smtp_connection.login(
89
+                        self._smtp_config.login,
90
+                        self._smtp_config.password
91
+                    )
92
+                    log = 'SMTP login result: {}'
93
+                    logger.debug(self, log.format(login_res))
94
+                except Exception as e:
95
+                    log = 'SMTP login error: {}'
96
+                    logger.debug(self, log.format(e.__str__()))
79
             logger.info(self, 'Connection OK')
97
             logger.info(self, 'Connection OK')
80
 
98
 
81
     def disconnect(self):
99
     def disconnect(self):
82
         if self._smtp_connection:
100
         if self._smtp_connection:
83
-            logger.info(self, 'Disconnecting from SMTP server {}'.format(self._smtp_config.server))
101
+            log = 'Disconnecting from SMTP server {}'
102
+            logger.info(self, log.format(self._smtp_config.server))
84
             self._smtp_connection.quit()
103
             self._smtp_connection.quit()
85
             logger.info(self, 'Connection closed.')
104
             logger.info(self, 'Connection closed.')
86
 
105
 
87
     def send_mail(self, message: MIMEMultipart):
106
     def send_mail(self, message: MIMEMultipart):
88
         if not self._is_active:
107
         if not self._is_active:
89
-            logger.info(self, 'Not sending email to {} (service desactivated)'.format(message['To']))
108
+            log = 'Not sending email to {} (service disabled)'
109
+            logger.info(self, log.format(message['To']))
90
         else:
110
         else:
91
-            self.connect()  # Acutally, this connects to SMTP only if required
111
+            self.connect()  # Actually, this connects to SMTP only if required
92
             logger.info(self, 'Sending email to {}'.format(message['To']))
112
             logger.info(self, 'Sending email to {}'.format(message['To']))
93
             self._smtp_connection.send_message(message)
113
             self._smtp_connection.send_message(message)
94
             from tracim.lib.notifications import EmailNotifier
114
             from tracim.lib.notifications import EmailNotifier
110
             password: str,
130
             password: str,
111
     ) -> None:
131
     ) -> None:
112
         """
132
         """
113
-        Send created account email to given user
133
+        Send created account email to given user.
134
+
114
         :param password: choosed password
135
         :param password: choosed password
115
         :param user: user to notify
136
         :param user: user to notify
116
         """
137
         """
175
 
196
 
176
     def _render(self, mako_template_filepath: str, context: dict):
197
     def _render(self, mako_template_filepath: str, context: dict):
177
         """
198
         """
178
-        Render mako template with all needed current variables
199
+        Render mako template with all needed current variables.
200
+
179
         :param mako_template_filepath: file path of mako template
201
         :param mako_template_filepath: file path of mako template
180
         :param context: dict with template context
202
         :param context: dict with template context
181
         :return: template rendered string
203
         :return: template rendered string