Index: Lib/smtplib.py =================================================================== --- Lib/smtplib.py (revision 87813) +++ Lib/smtplib.py (working copy) @@ -303,6 +303,7 @@ raise socket.error("nonnumeric port") if not port: port = self.default_port if self.debuglevel > 0: print('connect:', (host, port), file=stderr) + self.host = host self.sock = self._get_socket(host, port, self.timeout) (code, msg) = self.getreply() if self.debuglevel > 0: print("connect:", msg, file=stderr) @@ -637,7 +638,9 @@ if resp == 220: if not _have_ssl: raise RuntimeError("No SSL support included in this Python") - self.sock = ssl.wrap_socket(self.sock, keyfile, certfile) + server_hostname = self.host if ssl.HAS_SNI and self.host else None + self.sock = ssl.wrap_socket(self.sock, keyfile, certfile, + server_hostname=server_hostname) self.file = SSLFakeFile(self.sock) # RFC 3207: # The client MUST discard any knowledge obtained from @@ -808,7 +811,9 @@ def _get_socket(self, host, port, timeout): if self.debuglevel > 0: print('connect:', (host, port), file=stderr) new_socket = socket.create_connection((host, port), timeout) - new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile) + server_hostname = host if ssl.HAS_SNI and host else None + new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile, + server_hostname=server_hostname) self.file = SSLFakeFile(new_socket) return new_socket Index: Lib/imaplib.py =================================================================== --- Lib/imaplib.py (revision 87813) +++ Lib/imaplib.py (working copy) @@ -739,7 +739,8 @@ ssl_context.options |= ssl.OP_NO_SSLv2 typ, dat = self._simple_command(name) if typ == 'OK': - self.sock = ssl_context.wrap_socket(self.sock) + server_hostname = self.host if ssl.HAS_SNI and self.host else None + self.sock = ssl_context.wrap_socket(self.sock, server_hostname=server_hostname) self.file = self.sock.makefile('rb') self._tls_established = True self._get_capabilities() @@ -1195,7 +1196,9 @@ def _create_socket(self): sock = IMAP4._create_socket(self) - return ssl.wrap_socket(sock, self.keyfile, self.certfile) + server_hostname = self.host if ssl.HAS_SNI and self.host else None + return ssl.wrap_socket(sock, self.keyfile, self.certfile, + server_hostname=server_hostname) def open(self, host='', port=IMAP4_SSL_PORT): """Setup connection to remote server on "host:port". Index: Lib/ftplib.py =================================================================== --- Lib/ftplib.py (revision 87813) +++ Lib/ftplib.py (working copy) @@ -663,12 +663,15 @@ resp = self.voidcmd('AUTH TLS') else: resp = self.voidcmd('AUTH SSL') + server_hostname = self.host if ssl.HAS_SNI and self.host else None if self.context is not None: - self.sock = self.context.wrap_socket(self.sock) + self.sock = self.context.wrap_socket(self.sock, + server_hostname=server_hostname) else: self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, - ssl_version=self.ssl_version) + ssl_version=self.ssl_version, + server_hostname=server_hostname) self.file = self.sock.makefile(mode='r', encoding=self.encoding) return resp @@ -699,11 +702,13 @@ def ntransfercmd(self, cmd, rest=None): conn, size = FTP.ntransfercmd(self, cmd, rest) if self._prot_p: + server_hostname = self.host if ssl.HAS_SNI and self.host else None if self.context is not None: - conn = self.context.wrap_socket(conn) + conn = self.context.wrap_socket(conn, server_hostname=server_hostname) else: conn = ssl.wrap_socket(conn, self.keyfile, self.certfile, - ssl_version=self.ssl_version) + ssl_version=self.ssl_version, + server_hostname=server_hostname) return conn, size def retrbinary(self, cmd, callback, blocksize=8192, rest=None): Index: Lib/nntplib.py =================================================================== --- Lib/nntplib.py (revision 87813) +++ Lib/nntplib.py (working copy) @@ -272,10 +272,11 @@ if _have_ssl: - def _encrypt_on(sock, context): + def _encrypt_on(sock, context, server_hostname=None): """Wrap a socket in SSL/TLS. Arguments: - sock: Socket to wrap - context: SSL context to use for the encrypted connection + - server_hostname: The SNI server hostname to use if SNI is possible Returns: - sock: New, encrypted socket. """ @@ -284,7 +285,8 @@ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) # SSLv2 considered harmful. context.options |= ssl.OP_NO_SSLv2 - return context.wrap_socket(sock) + server_hostname = server_hostname if ssl.HAS_SNI else None + return context.wrap_socket(sock, server_hostname=server_hostname) # The classes themselves @@ -972,7 +974,7 @@ resp = self._shortcmd('STARTTLS') if resp.startswith('382'): self.file.close() - self.sock = _encrypt_on(self.sock, context) + self.sock = _encrypt_on(self.sock, context, self.host) self.file = self.sock.makefile("rwb") self.tls_on = True # Capabilities may change after TLS starts up, so ask for them Index: Lib/poplib.py =================================================================== --- Lib/poplib.py (revision 87813) +++ Lib/poplib.py (working copy) @@ -346,10 +346,12 @@ def _create_socket(self, timeout): sock = POP3._create_socket(self, timeout) + server_hostname = self.host if ssl.HAS_SNI else None if self.context is not None: - sock = self.context.wrap_socket(sock) + sock = self.context.wrap_socket(sock, server_hostname=server_hostname) else: - sock = ssl.wrap_socket(sock, self.keyfile, self.certfile) + sock = ssl.wrap_socket(sock, self.keyfile, self.certfile, + server_hostname=server_hostname) return sock __all__.append("POP3_SSL")