Index: Lib/smtplib.py =================================================================== --- Lib/smtplib.py (revision 83376) +++ Lib/smtplib.py (working copy) @@ -52,7 +52,7 @@ __all__ = ["SMTPException","SMTPServerDisconnected","SMTPResponseException", "SMTPSenderRefused","SMTPRecipientsRefused","SMTPDataError", "SMTPConnectError","SMTPHeloError","SMTPAuthenticationError", - "quoteaddr","quotedata","SMTP"] + "SMTPSocketConnectError", "quoteaddr","quotedata","SMTP"] SMTP_PORT = 25 SMTP_SSL_PORT = 465 @@ -118,6 +118,21 @@ class SMTPConnectError(SMTPResponseException): """Error during connection establishment.""" +class SMTPSocketConnectError(SMTPConnectError): + """Error creating a socket during connection establishment + + These exceptions are generated in some instances when there + is an error in the socket create call. The errno is stored in the + `errno' attribute of the error, and the `strerror' attribute + is set to the error message. + """ + + def __init__(self, code, msg): + self.errno = code + self.strerror = msg + self.args = (code, msg) + + class SMTPHeloError(SMTPResponseException): """The server refused our HELO reply.""" @@ -287,12 +302,17 @@ i = host.rfind(':') if i >= 0: host, port = host[:i], host[i+1:] - try: port = int(port) - except ValueError: - raise socket.error("nonnumeric port") if not port: port = self.default_port + + try: port = int(port) + except ValueError: + raise ValueError("nonnumeric port") + if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - self.sock = self._get_socket(host, port, self.timeout) + try: + self.sock = self._get_socket(host, port, self.timeout) + except socket.gaierror as msg: + raise SMTPSocketConnectError(msg.errno, msg.strerror) (code, msg) = self.getreply() if self.debuglevel > 0: print("connect:", msg, file=stderr) return (code, msg) Index: Lib/test/test_smtplib.py =================================================================== --- Lib/test/test_smtplib.py (revision 83376) +++ Lib/test/test_smtplib.py (working copy) @@ -262,13 +262,17 @@ smtp.send, 'test msg') def testNonnumericPort(self): - # check that non-numeric port raises socket.error - self.assertRaises(socket.error, smtplib.SMTP, + # check that non-numeric port raises ValueError + self.assertRaises(ValueError, smtplib.SMTP, "localhost", "bogus") - self.assertRaises(socket.error, smtplib.SMTP, + self.assertRaises(ValueError, smtplib.SMTP, "localhost:bogus") + def testIllegalDomainName(self): + self.assertRaises(smtplib.SMTPSocketConnectError, smtplib.SMTP + , "canihaz*burger?.com") + # test response of client to a non-successful HELO message @unittest.skipUnless(threading, 'Threading required for this test.') class BadHELOServerTests(unittest.TestCase):