comparison mercurial/mail.py @ 28935:a4c5c23de1d3

mail: retain hostname for sslutil.wrapsocket (issue5203) SMTPS + STARTTLS need to provide serverhostname, and we can't store it in sslkwargs because that breaks something involving the https protocol.
author timeless <timeless@mozdev.org>
date Fri, 15 Apr 2016 17:43:47 +0000
parents 8286f551b7ee
children bac14dbbbfab
comparison
equal deleted inserted replaced
28934:c4040a35b5d9 28935:a4c5c23de1d3
46 class STARTTLS(smtplib.SMTP): 46 class STARTTLS(smtplib.SMTP):
47 '''Derived class to verify the peer certificate for STARTTLS. 47 '''Derived class to verify the peer certificate for STARTTLS.
48 48
49 This class allows to pass any keyword arguments to SSL socket creation. 49 This class allows to pass any keyword arguments to SSL socket creation.
50 ''' 50 '''
51 def __init__(self, sslkwargs, **kwargs): 51 def __init__(self, sslkwargs, host=None, **kwargs):
52 smtplib.SMTP.__init__(self, **kwargs) 52 smtplib.SMTP.__init__(self, **kwargs)
53 self._sslkwargs = sslkwargs 53 self._sslkwargs = sslkwargs
54 self._host = host
54 55
55 def starttls(self, keyfile=None, certfile=None): 56 def starttls(self, keyfile=None, certfile=None):
56 if not self.has_extn("starttls"): 57 if not self.has_extn("starttls"):
57 msg = "STARTTLS extension not supported by server" 58 msg = "STARTTLS extension not supported by server"
58 raise smtplib.SMTPException(msg) 59 raise smtplib.SMTPException(msg)
59 (resp, reply) = self.docmd("STARTTLS") 60 (resp, reply) = self.docmd("STARTTLS")
60 if resp == 220: 61 if resp == 220:
61 self.sock = sslutil.wrapsocket(self.sock, keyfile, certfile, 62 self.sock = sslutil.wrapsocket(self.sock, keyfile, certfile,
63 serverhostname=self._host,
62 **self._sslkwargs) 64 **self._sslkwargs)
63 self.file = smtplib.SSLFakeFile(self.sock) 65 self.file = smtplib.SSLFakeFile(self.sock)
64 self.helo_resp = None 66 self.helo_resp = None
65 self.ehlo_resp = None 67 self.ehlo_resp = None
66 self.esmtp_features = {} 68 self.esmtp_features = {}
70 class SMTPS(smtplib.SMTP): 72 class SMTPS(smtplib.SMTP):
71 '''Derived class to verify the peer certificate for SMTPS. 73 '''Derived class to verify the peer certificate for SMTPS.
72 74
73 This class allows to pass any keyword arguments to SSL socket creation. 75 This class allows to pass any keyword arguments to SSL socket creation.
74 ''' 76 '''
75 def __init__(self, sslkwargs, keyfile=None, certfile=None, **kwargs): 77 def __init__(self, sslkwargs, keyfile=None, certfile=None, host=None,
78 **kwargs):
76 self.keyfile = keyfile 79 self.keyfile = keyfile
77 self.certfile = certfile 80 self.certfile = certfile
78 smtplib.SMTP.__init__(self, **kwargs) 81 smtplib.SMTP.__init__(self, **kwargs)
82 self._host = host
79 self.default_port = smtplib.SMTP_SSL_PORT 83 self.default_port = smtplib.SMTP_SSL_PORT
80 self._sslkwargs = sslkwargs 84 self._sslkwargs = sslkwargs
81 85
82 def _get_socket(self, host, port, timeout): 86 def _get_socket(self, host, port, timeout):
83 if self.debuglevel > 0: 87 if self.debuglevel > 0:
84 print('connect:', (host, port), file=sys.stderr) 88 print('connect:', (host, port), file=sys.stderr)
85 new_socket = socket.create_connection((host, port), timeout) 89 new_socket = socket.create_connection((host, port), timeout)
86 new_socket = sslutil.wrapsocket(new_socket, 90 new_socket = sslutil.wrapsocket(new_socket,
87 self.keyfile, self.certfile, 91 self.keyfile, self.certfile,
92 serverhostname=self._host,
88 **self._sslkwargs) 93 **self._sslkwargs)
89 self.file = smtplib.SSLFakeFile(new_socket) 94 self.file = smtplib.SSLFakeFile(new_socket)
90 return new_socket 95 return new_socket
91 96
92 def _smtp(ui): 97 def _smtp(ui):
112 else: 117 else:
113 # 'ui' is required by sslutil.wrapsocket() and set by sslkwargs() 118 # 'ui' is required by sslutil.wrapsocket() and set by sslkwargs()
114 sslkwargs = {'ui': ui} 119 sslkwargs = {'ui': ui}
115 if smtps: 120 if smtps:
116 ui.note(_('(using smtps)\n')) 121 ui.note(_('(using smtps)\n'))
117 s = SMTPS(sslkwargs, local_hostname=local_hostname) 122 s = SMTPS(sslkwargs, local_hostname=local_hostname, host=mailhost)
118 elif starttls: 123 elif starttls:
119 s = STARTTLS(sslkwargs, local_hostname=local_hostname) 124 s = STARTTLS(sslkwargs, local_hostname=local_hostname, host=mailhost)
120 else: 125 else:
121 s = smtplib.SMTP(local_hostname=local_hostname) 126 s = smtplib.SMTP(local_hostname=local_hostname)
122 if smtps: 127 if smtps:
123 defaultport = 465 128 defaultport = 465
124 else: 129 else: