##// END OF EJS Templates
mailer: don't use a mutable default argument
marcink -
r1408:dc932537 default
parent child Browse files
Show More
@@ -1,118 +1,118 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2013-2017 RhodeCode GmbH
3 # Copyright (C) 2013-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Simple smtp mailer used in RhodeCode
22 Simple smtp mailer used in RhodeCode
23 """
23 """
24
24
25 import time
25 import time
26 import logging
26 import logging
27 from socket import sslerror
27 from socket import sslerror
28 from email.utils import formatdate
28 from email.utils import formatdate
29 from rhodecode.lib.rcmail.message import Message
29 from rhodecode.lib.rcmail.message import Message
30 from rhodecode.lib.rcmail.utils import DNS_NAME
30 from rhodecode.lib.rcmail.utils import DNS_NAME
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
34
34
35 class SmtpMailer(object):
35 class SmtpMailer(object):
36 """SMTP mailer class
36 """SMTP mailer class
37
37
38 mailer = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth
38 mailer = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth
39 mail_port, ssl, tls)
39 mail_port, ssl, tls)
40 mailer.send(recipients, subject, body, attachment_files)
40 mailer.send(recipients, subject, body, attachment_files)
41
41
42 :param recipients might be a list of string or single string
42 :param recipients might be a list of string or single string
43 :param attachment_files is a dict of {filename:location}
43 :param attachment_files is a dict of {filename:location}
44 it tries to guess the mimetype and attach the file
44 it tries to guess the mimetype and attach the file
45
45
46 """
46 """
47
47
48 def __init__(self, mail_from, user, passwd, mail_server, smtp_auth=None,
48 def __init__(self, mail_from, user, passwd, mail_server, smtp_auth=None,
49 mail_port=None, ssl=False, tls=False, debug=False):
49 mail_port=None, ssl=False, tls=False, debug=False):
50
50
51 self.mail_from = mail_from
51 self.mail_from = mail_from
52 self.mail_server = mail_server
52 self.mail_server = mail_server
53 self.mail_port = mail_port
53 self.mail_port = mail_port
54 self.user = user
54 self.user = user
55 self.passwd = passwd
55 self.passwd = passwd
56 self.ssl = ssl
56 self.ssl = ssl
57 self.tls = tls
57 self.tls = tls
58 self.debug = debug
58 self.debug = debug
59 self.auth = smtp_auth
59 self.auth = smtp_auth
60
60
61 def _get_smptlib(self):
61 def _get_smptlib(self):
62 #patch the output
62 #patch the output
63 import smtplib
63 import smtplib
64
64
65 class StderrLogger(object):
65 class StderrLogger(object):
66
66
67 def write(self, message):
67 def write(self, message):
68 log.debug(message)
68 log.debug(message)
69
69
70 org_stderr = smtplib.stderr
70 org_stderr = smtplib.stderr
71 smtplib.stderr = StderrLogger()
71 smtplib.stderr = StderrLogger()
72 return smtplib
72 return smtplib
73
73
74 def send(self, recipients=[], subject='', body='', html='',
74 def send(self, recipients=None, subject='', body='', html='',
75 attachment_files=None):
75 attachment_files=None):
76
76 recipients = recipients or []
77 if isinstance(recipients, basestring):
77 if isinstance(recipients, basestring):
78 recipients = [recipients]
78 recipients = [recipients]
79 headers = {
79 headers = {
80 'Date': formatdate(time.time())
80 'Date': formatdate(time.time())
81 }
81 }
82 msg = Message(subject, recipients, body, html, self.mail_from,
82 msg = Message(subject, recipients, body, html, self.mail_from,
83 recipients_separator=", ", extra_headers=headers)
83 recipients_separator=", ", extra_headers=headers)
84 raw_msg = msg.to_message()
84 raw_msg = msg.to_message()
85
85
86 #patched smtplib without stderr
86 #patched smtplib without stderr
87 smtplib = self._get_smptlib()
87 smtplib = self._get_smptlib()
88 if self.ssl:
88 if self.ssl:
89 smtp_serv = smtplib.SMTP_SSL(self.mail_server, self.mail_port,
89 smtp_serv = smtplib.SMTP_SSL(self.mail_server, self.mail_port,
90 local_hostname=DNS_NAME.get_fqdn())
90 local_hostname=DNS_NAME.get_fqdn())
91 else:
91 else:
92 smtp_serv = smtplib.SMTP(self.mail_server, self.mail_port,
92 smtp_serv = smtplib.SMTP(self.mail_server, self.mail_port,
93 local_hostname=DNS_NAME.get_fqdn())
93 local_hostname=DNS_NAME.get_fqdn())
94
94
95 if self.tls:
95 if self.tls:
96 smtp_serv.ehlo()
96 smtp_serv.ehlo()
97 smtp_serv.starttls()
97 smtp_serv.starttls()
98
98
99 if self.debug:
99 if self.debug:
100 smtp_serv.set_debuglevel(1)
100 smtp_serv.set_debuglevel(1)
101
101
102 smtp_serv.ehlo()
102 smtp_serv.ehlo()
103 if self.auth:
103 if self.auth:
104 smtp_serv.esmtp_features["auth"] = self.auth
104 smtp_serv.esmtp_features["auth"] = self.auth
105
105
106 # if server requires authorization you must provide login and password
106 # if server requires authorization you must provide login and password
107 # but only if we have them
107 # but only if we have them
108 if self.user and self.passwd:
108 if self.user and self.passwd:
109 smtp_serv.login(self.user, self.passwd)
109 smtp_serv.login(self.user, self.passwd)
110
110
111 smtp_serv.sendmail(msg.sender, msg.send_to, raw_msg.as_string())
111 smtp_serv.sendmail(msg.sender, msg.send_to, raw_msg.as_string())
112 logging.info('MAIL SEND TO: %s' % recipients)
112 logging.info('MAIL SEND TO: %s' % recipients)
113
113
114 try:
114 try:
115 smtp_serv.quit()
115 smtp_serv.quit()
116 except sslerror:
116 except sslerror:
117 # sslerror is raised in tls connections on closing sometimes
117 # sslerror is raised in tls connections on closing sometimes
118 smtp_serv.close()
118 smtp_serv.close()
General Comments 0
You need to be logged in to leave comments. Login now