Mercurial > hg
annotate mercurial/mail.py @ 42325:526750cdd02d
bookmarks: keep bookmarks in .hg/store if new config set
Bookmarks storage consists of two parts: (1) the set of bookmarks and
their positions, and (2) the current bookmark. The former can get
updated by exchange, while the latter cannot. However, they are both
stored in directly .hg/ and protected by repo.wlock(). As a result,
ugly workarounds were needed. This patch introduces a new config
option to store the set of bookmarks and their positions in .hg/store/
but still storing the current bookmark directory in .hg/. The config
option only takes effect at repo creation time. It results in a new
requirement being set.
Differential Revision: https://phab.mercurial-scm.org/D6387
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Wed, 15 May 2019 22:09:02 -0700 |
parents | 9b3be572ff0c |
children | 2cc453284d5c |
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 |
30325
f6369544bf85
mail: do not print(), use ui.debug() instead
Yuya Nishihara <yuya@tcha.org>
parents:
30089
diff
changeset
|
8 from __future__ import absolute_import |
25957
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 |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
11 import email.charset |
30072
87b8e40eb812
mail: handle renamed email.Header
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29285
diff
changeset
|
12 import email.header |
34310
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
13 import email.message |
38332
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
14 import email.parser |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
15 import io |
25957
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
16 import os |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
17 import smtplib |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
18 import socket |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
19 import time |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
20 |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
21 from .i18n import _ |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
22 from . import ( |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
23 encoding, |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
24 error, |
36047
1407c42b302c
py3: pass system string to email.message.Message.set_type()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35151
diff
changeset
|
25 pycompat, |
25957
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
26 sslutil, |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
27 util, |
ae21d51bdc43
mail: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25842
diff
changeset
|
28 ) |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36120
diff
changeset
|
29 from .utils import ( |
37120
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37084
diff
changeset
|
30 procutil, |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36120
diff
changeset
|
31 stringutil, |
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36120
diff
changeset
|
32 ) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
33 |
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
|
34 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
|
35 '''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
|
36 |
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
|
37 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
|
38 ''' |
29251
31acc78c632a
mail: remove use of sslkwargs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
39 def __init__(self, ui, host=None, **kwargs): |
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
|
40 smtplib.SMTP.__init__(self, **kwargs) |
29248
e6de6ef3e426
sslutil: remove ui from sslkwargs (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29227
diff
changeset
|
41 self._ui = ui |
28935
a4c5c23de1d3
mail: retain hostname for sslutil.wrapsocket (issue5203)
timeless <timeless@mozdev.org>
parents:
28341
diff
changeset
|
42 self._host = host |
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
|
43 |
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
|
44 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
|
45 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
|
46 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
|
47 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
|
48 (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
|
49 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
|
50 self.sock = sslutil.wrapsocket(self.sock, keyfile, certfile, |
29248
e6de6ef3e426
sslutil: remove ui from sslkwargs (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29227
diff
changeset
|
51 ui=self._ui, |
29251
31acc78c632a
mail: remove use of sslkwargs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
52 serverhostname=self._host) |
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
|
53 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
|
54 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
|
55 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
|
56 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
|
57 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
|
58 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
|
59 |
26673 | 60 class SMTPS(smtplib.SMTP): |
61 '''Derived class to verify the peer certificate for SMTPS. | |
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
|
62 |
26673 | 63 This class allows to pass any keyword arguments to SSL socket creation. |
64 ''' | |
29251
31acc78c632a
mail: remove use of sslkwargs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
65 def __init__(self, ui, keyfile=None, certfile=None, host=None, |
28935
a4c5c23de1d3
mail: retain hostname for sslutil.wrapsocket (issue5203)
timeless <timeless@mozdev.org>
parents:
28341
diff
changeset
|
66 **kwargs): |
26673 | 67 self.keyfile = keyfile |
68 self.certfile = certfile | |
69 smtplib.SMTP.__init__(self, **kwargs) | |
28935
a4c5c23de1d3
mail: retain hostname for sslutil.wrapsocket (issue5203)
timeless <timeless@mozdev.org>
parents:
28341
diff
changeset
|
70 self._host = host |
26673 | 71 self.default_port = smtplib.SMTP_SSL_PORT |
29248
e6de6ef3e426
sslutil: remove ui from sslkwargs (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29227
diff
changeset
|
72 self._ui = ui |
26673 | 73 |
74 def _get_socket(self, host, port, timeout): | |
75 if self.debuglevel > 0: | |
39028
713126389ef2
mail: fix debug print, which appears to have been broken for a long time
Augie Fackler <augie@google.com>
parents:
39026
diff
changeset
|
76 self._ui.debug('connect: %r\n' % ((host, port),)) |
26673 | 77 new_socket = socket.create_connection((host, port), timeout) |
78 new_socket = sslutil.wrapsocket(new_socket, | |
79 self.keyfile, self.certfile, | |
29248
e6de6ef3e426
sslutil: remove ui from sslkwargs (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29227
diff
changeset
|
80 ui=self._ui, |
29251
31acc78c632a
mail: remove use of sslkwargs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
81 serverhostname=self._host) |
39026
a5e70c14214a
mail: stop using the smtplib.SSLFakeFile and use socket.socket.makefile
Augie Fackler <augie@google.com>
parents:
39025
diff
changeset
|
82 self.file = new_socket.makefile(r'rb') |
26673 | 83 return new_socket |
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
|
84 |
39025
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
85 def _pyhastls(): |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
86 """Returns true iff Python has TLS support, false otherwise.""" |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
87 try: |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
88 import ssl |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
89 getattr(ssl, 'HAS_TLS', False) |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
90 return True |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
91 except ImportError: |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
92 return False |
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
93 |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
94 def _smtp(ui): |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
95 '''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
|
96 local_hostname = ui.config('smtp', 'local_hostname') |
33499
0407a51b9d8c
codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents:
32275
diff
changeset
|
97 tls = ui.config('smtp', 'tls') |
13201
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
98 # backward compatible: when tls = true, we use starttls. |
37084
f0b6fbea00cf
stringutil: bulk-replace call sites to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
36120
diff
changeset
|
99 starttls = tls == 'starttls' or stringutil.parsebool(tls) |
13201
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
100 smtps = tls == 'smtps' |
39025
569d662816de
mail: modernize check for Python-with-TLS
Augie Fackler <augie@google.com>
parents:
39024
diff
changeset
|
101 if (starttls or smtps) and not _pyhastls(): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
102 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
|
103 mailhost = ui.config('smtp', 'host') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
104 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
|
105 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
|
106 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
|
107 ui.note(_('(using smtps)\n')) |
29251
31acc78c632a
mail: remove use of sslkwargs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
108 s = SMTPS(ui, local_hostname=local_hostname, host=mailhost) |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
109 elif starttls: |
29251
31acc78c632a
mail: remove use of sslkwargs
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29248
diff
changeset
|
110 s = STARTTLS(ui, local_hostname=local_hostname, host=mailhost) |
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 else: |
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
112 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
|
113 if smtps: |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
114 defaultport = 465 |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
115 else: |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
116 defaultport = 25 |
601c1e226889
smtp: use 465 as default port for SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18916
diff
changeset
|
117 mailport = util.getport(ui.config('smtp', 'port', defaultport)) |
26778
a95c975f42e3
l10n: use %d instead of %s for numbers
timeless@mozdev.org
parents:
26673
diff
changeset
|
118 ui.note(_('sending mail: smtp host %s, port %d\n') % |
2964
26c8d37496c2
fix typo in mail.py
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
2929
diff
changeset
|
119 (mailhost, mailport)) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
120 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
|
121 if starttls: |
f05250572467
smtp: fix for server doesn't support starttls extension
Zhigang Wang <zhigang.x.wang@oracle.com>
parents:
12091
diff
changeset
|
122 ui.note(_('(using starttls)\n')) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
123 s.ehlo() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
124 s.starttls() |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
125 s.ehlo() |
29285
63a3749147af
mail: unsupport smtp.verifycert (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29251
diff
changeset
|
126 if starttls or smtps: |
18888
19d489404d79
smtp: verify the certificate of the SMTP server for STARTTLS/SMTPS
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents:
18886
diff
changeset
|
127 ui.note(_('(verifying remote certificate)\n')) |
29285
63a3749147af
mail: unsupport smtp.verifycert (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
29251
diff
changeset
|
128 sslutil.validatesocket(s.sock) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
129 username = ui.config('smtp', 'username') |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
130 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
|
131 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
|
132 password = ui.getpass() |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
133 if username and password: |
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
134 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
|
135 (username)) |
9246
2de7d96593db
email: Catch exceptions during send.
David Soria Parra <dsp@php.net>
parents:
8343
diff
changeset
|
136 try: |
2de7d96593db
email: Catch exceptions during send.
David Soria Parra <dsp@php.net>
parents:
8343
diff
changeset
|
137 s.login(username, password) |
25660
328739ea70c3
global: mass rewrite to use modern exception syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25463
diff
changeset
|
138 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
|
139 raise error.Abort(inst) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
140 |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
141 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
|
142 try: |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
143 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
|
144 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
|
145 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
|
146 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
|
147 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
|
148 raise error.Abort(inst) |
5947
528c986f0162
Backed out changeset dc6ed2736c81
Bryan O'Sullivan <bos@serpentine.com>
parents:
5866
diff
changeset
|
149 |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
150 return send |
5947
528c986f0162
Backed out changeset dc6ed2736c81
Bryan O'Sullivan <bos@serpentine.com>
parents:
5866
diff
changeset
|
151 |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
152 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
|
153 '''send mail using sendmail.''' |
33499
0407a51b9d8c
codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents:
32275
diff
changeset
|
154 program = ui.config('email', 'method') |
39031
2cf3bd4ae55e
mail: properly handle email addresses typically being unicodes
Augie Fackler <augie@google.com>
parents:
39028
diff
changeset
|
155 stremail = lambda x: stringutil.email(encoding.strtolocal(x)) |
2cf3bd4ae55e
mail: properly handle email addresses typically being unicodes
Augie Fackler <augie@google.com>
parents:
39028
diff
changeset
|
156 cmdline = '%s -f %s %s' % (program, stremail(sender), |
2cf3bd4ae55e
mail: properly handle email addresses typically being unicodes
Augie Fackler <augie@google.com>
parents:
39028
diff
changeset
|
157 ' '.join(map(stremail, recipients))) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
158 ui.note(_('sending mail: %s\n') % cmdline) |
37458
00e4bd97b095
procutil: always popen() in binary mode
Yuya Nishihara <yuya@tcha.org>
parents:
37120
diff
changeset
|
159 fp = procutil.popen(cmdline, 'wb') |
00e4bd97b095
procutil: always popen() in binary mode
Yuya Nishihara <yuya@tcha.org>
parents:
37120
diff
changeset
|
160 fp.write(util.tonativeeol(msg)) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
161 ret = fp.close() |
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
162 if ret: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
163 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
|
164 os.path.basename(program.split(None, 1)[0]), |
37463
bbd240f81ac5
procutil: make explainexit() simply return a message (API)
Yuya Nishihara <yuya@tcha.org>
parents:
37458
diff
changeset
|
165 procutil.explainexit(ret))) |
2889
20b95aef3fe0
Move ui.sendmail to mail.connect/sendmail
Matt Mackall <mpm@selenic.com>
parents:
diff
changeset
|
166 |
15560
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
167 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
|
168 '''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
|
169 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
|
170 # 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
|
171 # of month instead of one. Make them print the same thing. |
35151
b45a9d121b53
py3: make sure the first argument of time.strftime() is str
Pulkit Goyal <7895pulkit@gmail.com>
parents:
34310
diff
changeset
|
172 date = time.strftime(r'%a %b %d %H:%M:%S %Y', time.localtime()) |
39031
2cf3bd4ae55e
mail: properly handle email addresses typically being unicodes
Augie Fackler <augie@google.com>
parents:
39028
diff
changeset
|
173 fp.write('From %s %s\n' % (encoding.strtolocal(sender), |
2cf3bd4ae55e
mail: properly handle email addresses typically being unicodes
Augie Fackler <augie@google.com>
parents:
39028
diff
changeset
|
174 encoding.strtolocal(date))) |
15560
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
175 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
|
176 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
|
177 fp.close() |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
178 |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
179 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
|
180 '''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
|
181 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
|
182 if mbox: |
cc58c228503e
mail: mbox handling as a part of mail handling, refactored from patchbomb
Mads Kiilerich <mads@kiilerich.com>
parents:
14965
diff
changeset
|
183 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
|
184 return lambda s, r, m: _mbox(mbox, s, r, m) |
33499
0407a51b9d8c
codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents:
32275
diff
changeset
|
185 if ui.config('email', 'method') == 'smtp': |
5947
528c986f0162
Backed out changeset dc6ed2736c81
Bryan O'Sullivan <bos@serpentine.com>
parents:
5866
diff
changeset
|
186 return _smtp(ui) |
5973
ea77f6f77514
patchbomb: undo backout and fix bugs in the earlier patch
Matt Mackall <mpm@selenic.com>
parents:
5947
diff
changeset
|
187 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
|
188 |
15561
ca572e94d8e7
notify: add option for writing to mbox
Mads Kiilerich <mads@kiilerich.com>
parents:
15560
diff
changeset
|
189 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
|
190 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
|
191 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
|
192 |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
193 def validateconfig(ui): |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
194 '''determine if we have enough config data to try sending email.''' |
33499
0407a51b9d8c
codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents:
32275
diff
changeset
|
195 method = ui.config('email', 'method') |
4489
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
196 if method == 'smtp': |
a11e13d50645
patchbomb: Validate email config before we start prompting for info.
Bryan O'Sullivan <bos@serpentine.com>
parents:
4096
diff
changeset
|
197 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
|
198 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
|
199 '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
|
200 else: |
37120
a8a902d7176e
procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents:
37084
diff
changeset
|
201 if not procutil.findexe(method): |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
202 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
|
203 'but not in PATH') % method) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
204 |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
205 def codec2iana(cs): |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
206 '''''' |
36119
6ea7f1c10c81
py3: cast character set to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36118
diff
changeset
|
207 cs = pycompat.sysbytes(email.charset.Charset(cs).input_charset.lower()) |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
208 |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
209 # "latin1" normalizes to "iso8859-1", standard calls for "iso-8859-1" |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
210 if cs.startswith("iso") and not cs.startswith("iso-"): |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
211 return "iso-" + cs[3:] |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
212 return cs |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
213 |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
214 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
|
215 '''Return MIME message suitable for a patch. |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
216 Charset will be detected by first trying to decode as us-ascii, then utf-8, |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
217 and finally the global encodings. If all those fail, fall back to |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
218 ISO-8859-1, an encoding with that allows all byte sequences. |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
219 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
|
220 |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
221 cs = ['us-ascii', 'utf-8', encoding.encoding, encoding.fallbackencoding] |
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
222 if display: |
39037
ede768cfe83e
mail: always fall back to iso-8859-1 if us-ascii won't work (BC)
Augie Fackler <augie@google.com>
parents:
39031
diff
changeset
|
223 cs = ['us-ascii'] |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
224 for charset in cs: |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
225 try: |
36118
9e47bfbeb723
py3: cast decode() argument to system string
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36047
diff
changeset
|
226 s.decode(pycompat.sysstr(charset)) |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
227 return mimetextqp(s, subtype, codec2iana(charset)) |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
228 except UnicodeDecodeError: |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
229 pass |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
230 |
30089
040f23ed6963
mail: take --encoding and HGENCODING into account
Gábor Stefanik <gabor.stefanik@nng.com>
parents:
30072
diff
changeset
|
231 return mimetextqp(s, subtype, "iso-8859-1") |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
232 |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
233 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
|
234 '''Return MIME message. |
17424
e7cfe3587ea4
fix trivial spelling errors
Mads Kiilerich <mads@kiilerich.com>
parents:
15562
diff
changeset
|
235 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
|
236 ''' |
34310
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
237 cs = email.charset.Charset(charset) |
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
238 msg = email.message.Message() |
36047
1407c42b302c
py3: pass system string to email.message.Message.set_type()
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35151
diff
changeset
|
239 msg.set_type(pycompat.sysstr('text/' + subtype)) |
34310
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
240 |
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 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
|
242 if len(line) > 950: |
34310
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
243 cs.body_encoding = email.charset.QP |
15562
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
244 break |
a82b6038ff08
mail: use quoted-printable for mime encoding to avoid too long lines (issue3075)
Mads Kiilerich <mads@kiilerich.com>
parents:
15561
diff
changeset
|
245 |
41405
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
246 # On Python 2, this simply assigns a value. Python 3 inspects |
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
247 # body and does different things depending on whether it has |
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
248 # encode() or decode() attributes. We can get the old behavior |
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
249 # if we pass a str and charset is None and we call set_charset(). |
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
250 # But we may get into trouble later due to Python attempting to |
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
251 # encode/decode using the registered charset (or attempting to |
9b3be572ff0c
mail: document behavior of Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents:
39108
diff
changeset
|
252 # use ascii in the absence of a charset). |
34310
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
253 msg.set_payload(body, cs) |
2d0c306a88c2
mail: encode long unicode lines in emails properly (issue5687)
Igor Ippolitov <iippolitov@gmail.com>
parents:
33499
diff
changeset
|
254 |
8332
3e544c074459
patchbomb: quoted-printable encode overly long lines
Rocco Rutte <pdmef@gmx.net>
parents:
8312
diff
changeset
|
255 return msg |
7191
d14212218582
mail: mime-encode patches that are utf-8
Christian Ebert <blacktrash@gmx.net>
parents:
7114
diff
changeset
|
256 |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
257 def _charsets(ui): |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
258 '''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
|
259 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
|
260 fallbacks = [encoding.fallbackencoding.lower(), |
de377b1a9a84
move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents:
7195
diff
changeset
|
261 encoding.encoding.lower(), 'utf-8'] |
8343 | 262 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
|
263 if cs not in charsets: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
264 charsets.append(cs) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
265 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
|
266 |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
267 def _encode(ui, s, charsets): |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
268 '''Returns (converted) string, charset tuple. |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
269 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
|
270 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
|
271 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
|
272 Caveat: Do not use for mail parts containing patches!''' |
39023
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
273 sendcharsets = charsets or _charsets(ui) |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
274 if not isinstance(s, bytes): |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
275 # We have unicode data, which we need to try and encode to |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
276 # some reasonable-ish encoding. Try the encodings the user |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
277 # wants, and fall back to garbage-in-ascii. |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
278 for ocs in sendcharsets: |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
279 try: |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
280 return s.encode(pycompat.sysstr(ocs)), ocs |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
281 except UnicodeEncodeError: |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
282 pass |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
283 except LookupError: |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
284 ui.warn(_('ignoring invalid sendcharset: %s\n') % ocs) |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
285 else: |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
286 # Everything failed, ascii-armor what we've got and send it. |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
287 return s.encode('ascii', 'backslashreplace') |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
288 # We have a bytes of unknown encoding. We'll try and guess a valid |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
289 # encoding, falling back to pretending we had ascii even though we |
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
290 # know that's wrong. |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
291 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
292 s.decode('ascii') |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
293 except UnicodeDecodeError: |
7948
de377b1a9a84
move encoding bits from util to encoding
Matt Mackall <mpm@selenic.com>
parents:
7195
diff
changeset
|
294 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
|
295 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
296 u = s.decode(ics) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
297 except UnicodeDecodeError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
298 continue |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
299 for ocs in sendcharsets: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
300 try: |
39023
858fe9625dab
mail: fix _encode to be more correct on Python 3
Augie Fackler <augie@google.com>
parents:
38332
diff
changeset
|
301 return u.encode(pycompat.sysstr(ocs)), ocs |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
302 except UnicodeEncodeError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
303 pass |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
304 except LookupError: |
7195
9fabcb1fe68d
mail: correct typo in variable name
Christian Ebert <blacktrash@gmx.net>
parents:
7191
diff
changeset
|
305 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
|
306 # 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
|
307 return s, 'us-ascii' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
308 |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
309 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
|
310 '''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
|
311 if not display: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
312 # split into words? |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
313 s, cs = _encode(ui, s, charsets) |
30072
87b8e40eb812
mail: handle renamed email.Header
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29285
diff
changeset
|
314 return str(email.header.Header(s, cs)) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
315 return s |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
316 |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
317 def _addressencode(ui, name, addr, charsets=None): |
39106
ebf54a34b7b7
mail: pass in addr to _addressencode() in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39105
diff
changeset
|
318 assert isinstance(addr, bytes) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
319 name = headencode(ui, name, charsets) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
320 try: |
39106
ebf54a34b7b7
mail: pass in addr to _addressencode() in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39105
diff
changeset
|
321 acc, dom = addr.split('@') |
39107
c2327bb3505d
mail: call s.decode('ascii') explicitly to see if s is an ascii bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39106
diff
changeset
|
322 acc.decode('ascii') |
39108
d2d89d31cbb5
mail: convert encoding.encoding to sysstr
Yuya Nishihara <yuya@tcha.org>
parents:
39107
diff
changeset
|
323 dom = dom.decode(pycompat.sysstr(encoding.encoding)).encode('idna') |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
324 addr = '%s@%s' % (acc, dom) |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
325 except UnicodeDecodeError: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
326 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
|
327 except ValueError: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
328 try: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
329 # too strict? |
39107
c2327bb3505d
mail: call s.decode('ascii') explicitly to see if s is an ascii bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39106
diff
changeset
|
330 addr.decode('ascii') |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
331 except UnicodeDecodeError: |
26587
56b2bcea2529
error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
26098
diff
changeset
|
332 raise error.Abort(_('invalid local address: %s') % addr) |
39024
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
333 return pycompat.bytesurl( |
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
334 email.utils.formataddr((name, encoding.strfromlocal(addr)))) |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
335 |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
336 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
|
337 '''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
|
338 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
|
339 return address or '' |
39024
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
340 name, addr = email.utils.parseaddr(encoding.strfromlocal(address)) |
39106
ebf54a34b7b7
mail: pass in addr to _addressencode() in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39105
diff
changeset
|
341 return _addressencode(ui, name, encoding.strtolocal(addr), charsets) |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
342 |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
343 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
|
344 '''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
|
345 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
|
346 always has one address per item''' |
39024
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
347 for a in addrs: |
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
348 assert isinstance(a, bytes), (r'%r unexpectedly not a bytestr' % a) |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
349 if display: |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
350 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
|
351 |
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
352 result = [] |
39024
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
353 for name, addr in email.utils.getaddresses( |
eabdf3c25b8b
mail: cope with Py3 unicode antics on email addresses
Augie Fackler <augie@google.com>
parents:
39023
diff
changeset
|
354 [encoding.strfromlocal(a) for a in addrs]): |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
355 if name or addr: |
39106
ebf54a34b7b7
mail: pass in addr to _addressencode() in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39105
diff
changeset
|
356 r = _addressencode(ui, name, encoding.strtolocal(addr), charsets) |
ebf54a34b7b7
mail: pass in addr to _addressencode() in bytes
Yuya Nishihara <yuya@tcha.org>
parents:
39105
diff
changeset
|
357 result.append(r) |
39105
f68ad9b4a43b
mail: remove redundant bytesurl() from addrlistencode()
Yuya Nishihara <yuya@tcha.org>
parents:
39039
diff
changeset
|
358 return result |
9948
e5b44a7986d0
mail: add parseaddrlist() function for parsing many addresses at once
Marti Raudsepp <marti@juffo.org>
parents:
9715
diff
changeset
|
359 |
7114
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
360 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
|
361 '''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
|
362 charset and transfer-encoding accordingly.''' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
363 cs = 'us-ascii' |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
364 if not display: |
30e49d54c537
mail: add methods to handle non-ascii chars
Christian Ebert <blacktrash@gmx.net>
parents:
6548
diff
changeset
|
365 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
|
366 return mimetextqp(s, 'plain', cs) |
28341
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
367 |
38332
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
368 if pycompat.ispy3: |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
369 def parse(fp): |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
370 ep = email.parser.Parser() |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
371 # disable the "universal newlines" mode, which isn't binary safe. |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
372 # I have no idea if ascii/surrogateescape is correct, but that's |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
373 # what the standard Python email parser does. |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
374 fp = io.TextIOWrapper(fp, encoding=r'ascii', |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
375 errors=r'surrogateescape', newline=chr(10)) |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
376 try: |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
377 return ep.parse(fp) |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
378 finally: |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
379 fp.detach() |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
380 else: |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
381 def parse(fp): |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
382 ep = email.parser.Parser() |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
383 return ep.parse(fp) |
7b12a2d2eedc
py3: ditch email.parser.BytesParser which appears to be plain crap
Yuya Nishihara <yuya@tcha.org>
parents:
37469
diff
changeset
|
384 |
28341
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
385 def headdecode(s): |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
386 '''Decodes RFC-2047 header''' |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
387 uparts = [] |
30072
87b8e40eb812
mail: handle renamed email.Header
Pulkit Goyal <7895pulkit@gmail.com>
parents:
29285
diff
changeset
|
388 for part, charset in email.header.decode_header(s): |
28341
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
389 if charset is not None: |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
390 try: |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
391 uparts.append(part.decode(charset)) |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
392 continue |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
393 except UnicodeDecodeError: |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
394 pass |
37469
7edf68862fe3
py3: work around weird handling of bytes/unicode in decode_header()
Yuya Nishihara <yuya@tcha.org>
parents:
37463
diff
changeset
|
395 # On Python 3, decode_header() may return either bytes or unicode |
7edf68862fe3
py3: work around weird handling of bytes/unicode in decode_header()
Yuya Nishihara <yuya@tcha.org>
parents:
37463
diff
changeset
|
396 # depending on whether the header has =?<charset>? or not |
7edf68862fe3
py3: work around weird handling of bytes/unicode in decode_header()
Yuya Nishihara <yuya@tcha.org>
parents:
37463
diff
changeset
|
397 if isinstance(part, type(u'')): |
7edf68862fe3
py3: work around weird handling of bytes/unicode in decode_header()
Yuya Nishihara <yuya@tcha.org>
parents:
37463
diff
changeset
|
398 uparts.append(part) |
7edf68862fe3
py3: work around weird handling of bytes/unicode in decode_header()
Yuya Nishihara <yuya@tcha.org>
parents:
37463
diff
changeset
|
399 continue |
28341
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
400 try: |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
401 uparts.append(part.decode('UTF-8')) |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
402 continue |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
403 except UnicodeDecodeError: |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
404 pass |
8286f551b7ee
patch: when importing from email, RFC2047-decode From/Subject headers
Julien Cristau <julien.cristau@logilab.fr>
parents:
27619
diff
changeset
|
405 uparts.append(part.decode('ISO-8859-1')) |
31447
067add650129
encoding: factor out unicode variants of from/tolocal()
Yuya Nishihara <yuya@tcha.org>
parents:
30325
diff
changeset
|
406 return encoding.unitolocal(u' '.join(uparts)) |