##// END OF EJS Templates
mail: correct typo in variable name
Christian Ebert -
r7195:9fabcb1f default
parent child Browse files
Show More
@@ -1,170 +1,170 b''
1 1 # mail.py - mail sending bits for mercurial
2 2 #
3 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from i18n import _
9 9 import os, smtplib, socket
10 10 import email.Header, email.MIMEText, email.Utils
11 11 import util
12 12
13 13 def _smtp(ui):
14 14 '''build an smtp connection and return a function to send mail'''
15 15 local_hostname = ui.config('smtp', 'local_hostname')
16 16 s = smtplib.SMTP(local_hostname=local_hostname)
17 17 mailhost = ui.config('smtp', 'host')
18 18 if not mailhost:
19 19 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
20 20 mailport = int(ui.config('smtp', 'port', 25))
21 21 ui.note(_('sending mail: smtp host %s, port %s\n') %
22 22 (mailhost, mailport))
23 23 s.connect(host=mailhost, port=mailport)
24 24 if ui.configbool('smtp', 'tls'):
25 25 if not hasattr(socket, 'ssl'):
26 26 raise util.Abort(_("can't use TLS: Python SSL support "
27 27 "not installed"))
28 28 ui.note(_('(using tls)\n'))
29 29 s.ehlo()
30 30 s.starttls()
31 31 s.ehlo()
32 32 username = ui.config('smtp', 'username')
33 33 password = ui.config('smtp', 'password')
34 34 if username and not password:
35 35 password = ui.getpass()
36 36 if username and password:
37 37 ui.note(_('(authenticating to mail server as %s)\n') %
38 38 (username))
39 39 s.login(username, password)
40 40
41 41 def send(sender, recipients, msg):
42 42 try:
43 43 return s.sendmail(sender, recipients, msg)
44 44 except smtplib.SMTPRecipientsRefused, inst:
45 45 recipients = [r[1] for r in inst.recipients.values()]
46 46 raise util.Abort('\n' + '\n'.join(recipients))
47 47 except smtplib.SMTPException, inst:
48 48 raise util.Abort(inst)
49 49
50 50 return send
51 51
52 52 def _sendmail(ui, sender, recipients, msg):
53 53 '''send mail using sendmail.'''
54 54 program = ui.config('email', 'method')
55 55 cmdline = '%s -f %s %s' % (program, util.email(sender),
56 56 ' '.join(map(util.email, recipients)))
57 57 ui.note(_('sending mail: %s\n') % cmdline)
58 58 fp = util.popen(cmdline, 'w')
59 59 fp.write(msg)
60 60 ret = fp.close()
61 61 if ret:
62 62 raise util.Abort('%s %s' % (
63 63 os.path.basename(program.split(None, 1)[0]),
64 64 util.explain_exit(ret)[0]))
65 65
66 66 def connect(ui):
67 67 '''make a mail connection. return a function to send mail.
68 68 call as sendmail(sender, list-of-recipients, msg).'''
69 69 if ui.config('email', 'method', 'smtp') == 'smtp':
70 70 return _smtp(ui)
71 71 return lambda s, r, m: _sendmail(ui, s, r, m)
72 72
73 73 def sendmail(ui, sender, recipients, msg):
74 74 send = connect(ui)
75 75 return send(sender, recipients, msg)
76 76
77 77 def validateconfig(ui):
78 78 '''determine if we have enough config data to try sending email.'''
79 79 method = ui.config('email', 'method', 'smtp')
80 80 if method == 'smtp':
81 81 if not ui.config('smtp', 'host'):
82 82 raise util.Abort(_('smtp specified as email transport, '
83 83 'but no smtp host configured'))
84 84 else:
85 85 if not util.find_exe(method):
86 86 raise util.Abort(_('%r specified as email transport, '
87 87 'but not in PATH') % method)
88 88
89 89 def mimetextpatch(s, subtype='plain', display=False):
90 90 '''If patch in utf-8 transfer-encode it.'''
91 91 if not display:
92 92 for cs in ('us-ascii', 'utf-8'):
93 93 try:
94 94 s.decode(cs)
95 95 return email.MIMEText.MIMEText(s, subtype, cs)
96 96 except UnicodeDecodeError:
97 97 pass
98 98 return email.MIMEText.MIMEText(s, subtype)
99 99
100 100 def _charsets(ui):
101 101 '''Obtains charsets to send mail parts not containing patches.'''
102 102 charsets = [cs.lower() for cs in ui.configlist('email', 'charsets')]
103 103 fallbacks = [util._fallbackencoding.lower(),
104 104 util._encoding.lower(), 'utf-8']
105 105 for cs in fallbacks: # util.unique does not keep order
106 106 if cs not in charsets:
107 107 charsets.append(cs)
108 108 return [cs for cs in charsets if not cs.endswith('ascii')]
109 109
110 110 def _encode(ui, s, charsets):
111 111 '''Returns (converted) string, charset tuple.
112 112 Finds out best charset by cycling through sendcharsets in descending
113 113 order. Tries both _encoding and _fallbackencoding for input. Only as
114 114 last resort send as is in fake ascii.
115 115 Caveat: Do not use for mail parts containing patches!'''
116 116 try:
117 117 s.decode('ascii')
118 118 except UnicodeDecodeError:
119 119 sendcharsets = charsets or _charsets(ui)
120 120 for ics in (util._encoding, util._fallbackencoding):
121 121 try:
122 122 u = s.decode(ics)
123 123 except UnicodeDecodeError:
124 124 continue
125 125 for ocs in sendcharsets:
126 126 try:
127 127 return u.encode(ocs), ocs
128 128 except UnicodeEncodeError:
129 129 pass
130 130 except LookupError:
131 ui.warn(_('ignoring invalid sendcharset: %s\n') % cs)
131 ui.warn(_('ignoring invalid sendcharset: %s\n') % ocs)
132 132 # if ascii, or all conversion attempts fail, send (broken) ascii
133 133 return s, 'us-ascii'
134 134
135 135 def headencode(ui, s, charsets=None, display=False):
136 136 '''Returns RFC-2047 compliant header from given string.'''
137 137 if not display:
138 138 # split into words?
139 139 s, cs = _encode(ui, s, charsets)
140 140 return str(email.Header.Header(s, cs))
141 141 return s
142 142
143 143 def addressencode(ui, address, charsets=None, display=False):
144 144 '''Turns address into RFC-2047 compliant header.'''
145 145 if display or not address:
146 146 return address or ''
147 147 name, addr = email.Utils.parseaddr(address)
148 148 name = headencode(ui, name, charsets)
149 149 try:
150 150 acc, dom = addr.split('@')
151 151 acc = acc.encode('ascii')
152 152 dom = dom.encode('idna')
153 153 addr = '%s@%s' % (acc, dom)
154 154 except UnicodeDecodeError:
155 155 raise util.Abort(_('invalid email address: %s') % addr)
156 156 except ValueError:
157 157 try:
158 158 # too strict?
159 159 addr = addr.encode('ascii')
160 160 except UnicodeDecodeError:
161 161 raise util.Abort(_('invalid local address: %s') % addr)
162 162 return email.Utils.formataddr((name, addr))
163 163
164 164 def mimeencode(ui, s, charsets=None, display=False):
165 165 '''creates mime text object, encodes it if needed, and sets
166 166 charset and transfer-encoding accordingly.'''
167 167 cs = 'us-ascii'
168 168 if not display:
169 169 s, cs = _encode(ui, s, charsets)
170 170 return email.MIMEText.MIMEText(s, 'plain', cs)
General Comments 0
You need to be logged in to leave comments. Login now