Mercurial > hg
annotate mercurial/mail.py @ 26610:f9f82c444ff7
filemerge: only copy to backup during premerge step
The premerge might leave the original file in an unclean state. Therefore it's
important to only copy the file in the beginning.
author | Siddharth Agarwal <sid0@fb.com> |
---|---|
date | Sun, 11 Oct 2015 20:04:40 -0700 |
parents | 56b2bcea2529 |
children | ab1af5e7d734 |
rev | line source |
---|---|
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
1 # mail.py - mail sending bits for mercurial |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
2 # |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
3 # Copyright 2006 Matt Mackall <mpm@selenic.com> |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
7948
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
7 |
25957
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
8 from __future__ import absolute_import |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
9 |
19790
53f16f4aff33
mail: correct import of email module
Augie Fackler <raf@durin42.com>
parents:
19050
diff
changeset
|
10 import email |
25957
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
11 import os |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
12 import quopri |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
13 import smtplib |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
14 import socket |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
15 import sys |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
16 import time |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
17 |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
18 from .i18n import _ |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
19 from . import ( |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
20 encoding, |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
21 error, |
25957
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
22 sslutil, |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
23 util, |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
24 ) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
25 |
11542
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
26 _oldheaderinit = email.Header.Header.__init__ |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
27 def _unifiedheaderinit(self, *args, **kw): |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
28 """ |
17428
72803c8edaa4
avoid using abbreviations that look like spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
17424
diff
changeset
|
29 Python 2.7 introduces a backwards incompatible change |
11542
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
30 (Python issue1974, r70772) in email.Generator.Generator code: |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
31 pre-2.7 code passed "continuation_ws='\t'" to the Header |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
32 constructor, and 2.7 removed this parameter. |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
33 |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
34 Default argument is continuation_ws=' ', which means that the |
26098 | 35 behavior is different in <2.7 and 2.7 |
11542
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
36 |
26098 | 37 We consider the 2.7 behavior to be preferable, but need |
38 to have an unified behavior for versions 2.4 to 2.7 | |
11542
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
39 """ |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
40 # override continuation_ws |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
41 kw['continuation_ws'] = ' ' |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
42 _oldheaderinit(self, *args, **kw) |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
43 |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
44 email.Header.Header.__dict__['__init__'] = _unifiedheaderinit |
594b98846ce1
mail: ensure that Python2.4 to 2.7 use the same header format
Nicolas Dumazet <nicdumz.commits@gmail.com>
parents:
10264
diff
changeset
|
45 |
18885
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
46 class STARTTLS(smtplib.SMTP): |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
47 '''Derived class to verify the peer certificate for STARTTLS. |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
48 |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
49 This class allows to pass any keyword arguments to SSL socket creation. |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
50 ''' |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
51 def __init__(self, sslkwargs, **kwargs): |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
52 smtplib.SMTP.__init__(self, **kwargs) |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
53 self._sslkwargs = sslkwargs |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
54 |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
55 def starttls(self, keyfile=None, certfile=None): |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
56 if not self.has_extn("starttls"): |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
57 msg = "STARTTLS extension not supported by server" |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
58 raise smtplib.SMTPException(msg) |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
59 (resp, reply) = self.docmd("STARTTLS") |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
60 if resp == 220: |
25429
9d1c61715939
ssl: rename ssl_wrap_socket() to conform to our naming convention
Yuya Nishihara <yuya@tcha.org>
parents:
25205
diff
changeset
|
61 self.sock = sslutil.wrapsocket(self.sock, keyfile, certfile, |
9d1c61715939
ssl: rename ssl_wrap_socket() to conform to our naming convention
Yuya Nishihara <yuya@tcha.org>
parents:
25205
diff
changeset
|
62 **self._sslkwargs) |
18885
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
63 if not util.safehasattr(self.sock, "read"): |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
64 # using httplib.FakeSocket with Python 2.5.x or earlier |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
65 self.sock.read = self.sock.recv |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
66 self.file = smtplib.SSLFakeFile(self.sock) |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
67 self.helo_resp = None |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
68 self.ehlo_resp = None |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
69 self.esmtp_features = {} |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
70 self.does_esmtp = 0 |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
71 return (resp, reply) |
cf1304fbc184
smtp: add the class to verify the certificate of the SMTP server for STARTTLS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
17428
diff
changeset
|
72 |
18886
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
73 if util.safehasattr(smtplib.SMTP, '_get_socket'): |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
74 class SMTPS(smtplib.SMTP): |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
75 '''Derived class to verify the peer certificate for SMTPS. |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
76 |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
77 This class allows to pass any keyword arguments to SSL socket creation. |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
78 ''' |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
79 def __init__(self, sslkwargs, keyfile=None, certfile=None, **kwargs): |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
80 self.keyfile = keyfile |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
81 self.certfile = certfile |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
82 smtplib.SMTP.__init__(self, **kwargs) |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
83 self.default_port = smtplib.SMTP_SSL_PORT |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
84 self._sslkwargs = sslkwargs |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
85 |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
86 def _get_socket(self, host, port, timeout): |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
87 if self.debuglevel > 0: |
18916
6edb0e18b83c
mail: add missing import of sys
Bryan O'Sullivan <bryano@fb.com>
parents:
18888
diff
changeset
|
88 print >> sys.stderr, 'connect:', (host, port) |
18886
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
89 new_socket = socket.create_connection((host, port), timeout) |
25429
9d1c61715939
ssl: rename ssl_wrap_socket() to conform to our naming convention
Yuya Nishihara <yuya@tcha.org>
parents:
25205
diff
changeset
|
90 new_socket = sslutil.wrapsocket(new_socket, |
9d1c61715939
ssl: rename ssl_wrap_socket() to conform to our naming convention
Yuya Nishihara <yuya@tcha.org>
parents:
25205
diff
changeset
|
91 self.keyfile, self.certfile, |
9d1c61715939
ssl: rename ssl_wrap_socket() to conform to our naming convention
Yuya Nishihara <yuya@tcha.org>
parents:
25205
diff
changeset
|
92 **self._sslkwargs) |
18886
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
93 self.file = smtplib.SSLFakeFile(new_socket) |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
94 return new_socket |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
95 else: |
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
96 def SMTPS(sslkwargs, keyfile=None, certfile=None, **kwargs): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
97 raise error.Abort(_('SMTPS requires Python 2.6 or later')) |
18886
14a60a0f7122
smtp: add the class to verify the certificate of the SMTP server for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18885
diff
changeset
|
98 |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
99 def _smtp(ui): |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
100 '''build an smtp connection and return a function to send mail''' |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
101 local_hostname = ui.config('smtp', 'local_hostname') |
13244
d8f92c3a17d6
mail: fix regression when parsing unset smtp.tls option
Patrick Mezard <pmezard@gmail.com>
parents:
13201
diff
changeset
|
102 tls = ui.config('smtp', 'tls', 'none') |
13201
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
103 # backward compatible: when tls = true, we use starttls. |
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
104 starttls = tls == 'starttls' or util.parsebool(tls) |
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
105 smtps = tls == 'smtps' |
14965
194b043dfa51
mail: use safehasattr instead of hasattr
Augie Fackler <durin42@gmail.com>
parents:
14271
diff
changeset
|
106 if (starttls or smtps) and not util.safehasattr(socket, 'ssl'): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
107 raise error.Abort(_("can't use TLS: Python SSL support not installed")) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
108 mailhost = ui.config('smtp', 'host') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
109 if not mailhost: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
110 raise error.Abort(_('smtp.host not configured - cannot send mail')) |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
111 verifycert = ui.config('smtp', 'verifycert', 'strict') |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
112 if verifycert not in ['strict', 'loose']: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
113 if util.parsebool(verifycert) is not False: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
114 raise error.Abort(_('invalid smtp.verifycert configuration: %s') |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
115 % (verifycert)) |
23223
a4af6fd99fb0
mail: actually use the verifycert config value
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
19810
diff
changeset
|
116 verifycert = False |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
117 if (starttls or smtps) and verifycert: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
118 sslkwargs = sslutil.sslkwargs(ui, mailhost) |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
119 else: |
25463
03af5c2ddf75
mail: pass ui to sslutil.wrapsocket() even if verifycert is off (issue4713)
Yuya Nishihara <yuya@tcha.org>
parents:
25429
diff
changeset
|
120 # 'ui' is required by sslutil.wrapsocket() and set by sslkwargs() |
03af5c2ddf75
mail: pass ui to sslutil.wrapsocket() even if verifycert is off (issue4713)
Yuya Nishihara <yuya@tcha.org>
parents:
25429
diff
changeset
|
121 sslkwargs = {'ui': ui} |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
122 if smtps: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
123 ui.note(_('(using smtps)\n')) |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
124 s = SMTPS(sslkwargs, local_hostname=local_hostname) |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
125 elif starttls: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
126 s = STARTTLS(sslkwargs, local_hostname=local_hostname) |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
127 else: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
128 s = smtplib.SMTP(local_hostname=local_hostname) |
19050
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
129 if smtps: |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
130 defaultport = 465 |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
131 else: |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
132 defaultport = 25 |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
133 mailport = util.getport(ui.config('smtp', 'port', defaultport)) |
2964
26c8d37496c2
fix typo in mail.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2929
diff
changeset
|
134 ui.note(_('sending mail: smtp host %s, port %s\n') % |
26c8d37496c2
fix typo in mail.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2929
diff
changeset
|
135 (mailhost, mailport)) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
136 s.connect(host=mailhost, port=mailport) |
13201
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
137 if starttls: |
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
138 ui.note(_('(using starttls)\n')) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
139 s.ehlo() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
140 s.starttls() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
141 s.ehlo() |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
142 if (starttls or smtps) and verifycert: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
143 ui.note(_('(verifying remote certificate)\n')) |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
144 sslutil.validator(ui, mailhost)(s.sock, verifycert == 'strict') |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
145 username = ui.config('smtp', 'username') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
146 password = ui.config('smtp', 'password') |
5749
4fba4fee0718
Patchbomb: Prompt password when using SMTP/TLS and no password in .hgrc.
Arun Thomas <arun.thomas@gmail.com>
parents:
5472
diff
changeset
|
147 if username and not password: |
4fba4fee0718
Patchbomb: Prompt password when using SMTP/TLS and no password in .hgrc.
Arun Thomas <arun.thomas@gmail.com>
parents:
5472
diff
changeset
|
148 password = ui.getpass() |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
149 if username and password: |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
150 ui.note(_('(authenticating to mail server as %s)\n') % |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
151 (username)) |
9246
2de7d96593db
email: Catch exceptions during send.
David Soria Parra <dsp@php.net>
parents:
8343
diff
changeset
|
152 try: |
2de7d96593db
email: Catch exceptions during send.
David Soria Parra <dsp@php.net>
parents:
8343
diff
changeset
|
153 s.login(username, password) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25463
diff
changeset
|
154 except smtplib.SMTPException as inst: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
155 raise error.Abort(inst) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
156 |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
157 def send(sender, recipients, msg): |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
158 try: |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
159 return s.sendmail(sender, recipients, msg) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25463
diff
changeset
|
160 except smtplib.SMTPRecipientsRefused as inst: |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
161 recipients = [r[1] for r in inst.recipients.values()] |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
162 raise error.Abort('\n' + '\n'.join(recipients)) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25463
diff
changeset
|
163 except smtplib.SMTPException as inst: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
164 raise error.Abort(inst) |
5947
528c986f0162
Backed out changeset dc6ed2736c81
Bryan O'Sullivan <bos@serpentine.com>
parents:
5866
diff
changeset
|
165 |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
166 return send |
5947
528c986f0162
Backed out changeset dc6ed2736c81
Bryan O'Sullivan <bos@serpentine.com>
parents:
5866
diff
changeset
|
167 |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
168 def _sendmail(ui, sender, recipients, msg): |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
169 '''send mail using sendmail.''' |
25842
fa3f0301cf91
email: fix config default value inconsistency
Matt Mackall <mpm@selenic.com>
parents:
25660
diff
changeset
|
170 program = ui.config('email', 'method', 'smtp') |
5975
75d9fe70c654
templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents:
5973
diff
changeset
|
171 cmdline = '%s -f %s %s' % (program, util.email(sender), |
75d9fe70c654
templater: move email function to util
Matt Mackall <mpm@selenic.com>
parents:
5973
diff
changeset
|
172 ' '.join(map(util.email, recipients))) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
173 ui.note(_('sending mail: %s\n') % cmdline) |
6548
962eb403165b
replace usage of os.popen() with util.popen()
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
5975
diff
changeset
|
174 fp = util.popen(cmdline, 'w') |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
175 fp.write(msg) |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
176 ret = fp.close() |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
177 if ret: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
178 raise error.Abort('%s %s' % ( |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
179 os.path.basename(program.split(None, 1)[0]), |
14234
600e64004eb5
rename explain_exit to explainexit
Adrian Buehlmann <adrian@cadifra.com>
parents:
13244
diff
changeset
|
180 util.explainexit(ret)[0])) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
181 |
15560
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
182 def _mbox(mbox, sender, recipients, msg): |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
183 '''write mails to mbox''' |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
184 fp = open(mbox, 'ab+') |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
185 # Should be time.asctime(), but Windows prints 2-characters day |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
186 # of month instead of one. Make them print the same thing. |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
187 date = time.strftime('%a %b %d %H:%M:%S %Y', time.localtime()) |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
188 fp.write('From %s %s\n' % (sender, date)) |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
189 fp.write(msg) |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
190 fp.write('\n\n') |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
191 fp.close() |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
192 |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
193 def connect(ui, mbox=None): |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
194 '''make a mail connection. return a function to send mail. |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
195 call as sendmail(sender, list-of-recipients, msg).''' |
15560
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
196 if mbox: |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
197 open(mbox, 'wb').close() |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
198 return lambda s, r, m: _mbox(mbox, s, r, m) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
199 if ui.config('email', 'method', 'smtp') == 'smtp': |
5947
528c986f0162
Backed out changeset dc6ed2736c81
Bryan O'Sullivan <bos@serpentine.com>
parents:
5866
diff
changeset
|
200 return _smtp(ui) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
201 return lambda s, r, m: _sendmail(ui, s, r, m) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
202 |
15561
ca572e94d8e7
notify: add option for writing to mbox
Mads Kiilerich <mads@kiilerich.com>
parents:
15560
diff
changeset
|
203 def sendmail(ui, sender, recipients, msg, mbox=None): |
ca572e94d8e7
notify: add option for writing to mbox
Mads Kiilerich <mads@kiilerich.com>
parents:
15560
diff
changeset
|
204 send = connect(ui, mbox=mbox) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
205 return send(sender, recipients, msg) |
4489
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
206 |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
207 def validateconfig(ui): |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
208 '''determine if we have enough config data to try sending email.''' |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
209 method = ui.config('email', 'method', 'smtp') |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
210 if method == 'smtp': |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
211 if not ui.config('smtp', 'host'): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
212 raise error.Abort(_('smtp specified as email transport, ' |
4489
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
213 'but no smtp host configured')) |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
214 else: |
14271
4030630fb59c
rename util.find_exe to findexe
Adrian Buehlmann <adrian@cadifra.com>
parents:
14234
diff
changeset
|
215 if not util.findexe(method): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
216 raise error.Abort(_('%r specified as email transport, ' |
4489
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
217 'but not in PATH') % method) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
218 |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
219 def mimetextpatch(s, subtype='plain', display=False): |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
220 '''Return MIME message suitable for a patch. |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
221 Charset will be detected as utf-8 or (possibly fake) us-ascii. |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
222 Transfer encodings will be used if necessary.''' |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
223 |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
224 cs = 'us-ascii' |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
225 if not display: |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
226 try: |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
227 s.decode('us-ascii') |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
228 except UnicodeDecodeError: |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
229 try: |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
230 s.decode('utf-8') |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
231 cs = 'utf-8' |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
232 except UnicodeDecodeError: |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
233 # We'll go with us-ascii as a fallback. |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
234 pass |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
235 |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
236 return mimetextqp(s, subtype, cs) |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
237 |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
238 def mimetextqp(body, subtype, charset): |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
239 '''Return MIME message. |
17424
e7cfe3587ea4
fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
15562
diff
changeset
|
240 Quoted-printable transfer encoding will be used if necessary. |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
241 ''' |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
242 enc = None |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
243 for line in body.splitlines(): |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
244 if len(line) > 950: |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
245 body = quopri.encodestring(body) |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
246 enc = "quoted-printable" |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
247 break |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
248 |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
249 msg = email.MIMEText.MIMEText(body, subtype, charset) |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
250 if enc: |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
251 del msg['Content-Transfer-Encoding'] |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
252 msg['Content-Transfer-Encoding'] = enc |
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
253 return msg |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
254 |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
255 def _charsets(ui): |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
256 '''Obtains charsets to send mail parts not containing patches.''' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
257 charsets = [cs.lower() for cs in ui.configlist('email', 'charsets')] |
7948
de377b1a9a84
move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents:
7195
diff
changeset
|
258 fallbacks = [encoding.fallbackencoding.lower(), |
de377b1a9a84
move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents:
7195
diff
changeset
|
259 encoding.encoding.lower(), 'utf-8'] |
8343 | 260 for cs in fallbacks: # find unique charsets while keeping order |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
261 if cs not in charsets: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
262 charsets.append(cs) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
263 return [cs for cs in charsets if not cs.endswith('ascii')] |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
264 |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
265 def _encode(ui, s, charsets): |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
266 '''Returns (converted) string, charset tuple. |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
267 Finds out best charset by cycling through sendcharsets in descending |
7948
de377b1a9a84
move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents:
7195
diff
changeset
|
268 order. Tries both encoding and fallbackencoding for input. Only as |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
269 last resort send as is in fake ascii. |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
270 Caveat: Do not use for mail parts containing patches!''' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
271 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
272 s.decode('ascii') |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
273 except UnicodeDecodeError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
274 sendcharsets = charsets or _charsets(ui) |
7948
de377b1a9a84
move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents:
7195
diff
changeset
|
275 for ics in (encoding.encoding, encoding.fallbackencoding): |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
276 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
277 u = s.decode(ics) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
278 except UnicodeDecodeError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
279 continue |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
280 for ocs in sendcharsets: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
281 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
282 return u.encode(ocs), ocs |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
283 except UnicodeEncodeError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
284 pass |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
285 except LookupError: |
7195
9fabcb1fe68d
mail: correct typo in variable name
Christian Ebert <blacktrash@gmx.net>
parents:
7191
diff
changeset
|
286 ui.warn(_('ignoring invalid sendcharset: %s\n') % ocs) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
287 # if ascii, or all conversion attempts fail, send (broken) ascii |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
288 return s, 'us-ascii' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
289 |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
290 def headencode(ui, s, charsets=None, display=False): |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
291 '''Returns RFC-2047 compliant header from given string.''' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
292 if not display: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
293 # split into words? |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
294 s, cs = _encode(ui, s, charsets) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
295 return str(email.Header.Header(s, cs)) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
296 return s |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
297 |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
298 def _addressencode(ui, name, addr, charsets=None): |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
299 name = headencode(ui, name, charsets) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
300 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
301 acc, dom = addr.split('@') |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
302 acc = acc.encode('ascii') |
9715
f0e99a2eac76
patchbomb: fix handling of email addresses with Unicode domains (IDNA)
Marti Raudsepp <marti@juffo.org>
parents:
9246
diff
changeset
|
303 dom = dom.decode(encoding.encoding).encode('idna') |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
304 addr = '%s@%s' % (acc, dom) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
305 except UnicodeDecodeError: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
306 raise error.Abort(_('invalid email address: %s') % addr) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
307 except ValueError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
308 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
309 # too strict? |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
310 addr = addr.encode('ascii') |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
311 except UnicodeDecodeError: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
312 raise error.Abort(_('invalid local address: %s') % addr) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
313 return email.Utils.formataddr((name, addr)) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
314 |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
315 def addressencode(ui, address, charsets=None, display=False): |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
316 '''Turns address into RFC-2047 compliant header.''' |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
317 if display or not address: |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
318 return address or '' |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
319 name, addr = email.Utils.parseaddr(address) |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
320 return _addressencode(ui, name, addr, charsets) |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
321 |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
322 def addrlistencode(ui, addrs, charsets=None, display=False): |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
323 '''Turns a list of addresses into a list of RFC-2047 compliant headers. |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
324 A single element of input list may contain multiple addresses, but output |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
325 always has one address per item''' |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
326 if display: |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
327 return [a.strip() for a in addrs if a.strip()] |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
328 |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
329 result = [] |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
330 for name, addr in email.Utils.getaddresses(addrs): |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
331 if name or addr: |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
332 result.append(_addressencode(ui, name, addr, charsets)) |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
333 return result |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
334 |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
335 def mimeencode(ui, s, charsets=None, display=False): |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
336 '''creates mime text object, encodes it if needed, and sets |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
337 charset and transfer-encoding accordingly.''' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
338 cs = 'us-ascii' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
339 if not display: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
340 s, cs = _encode(ui, s, charsets) |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
341 return mimetextqp(s, 'plain', cs) |