diff options
Diffstat (limited to 'Lib/smtplib.py')
-rwxr-xr-x | Lib/smtplib.py | 84 |
1 files changed, 57 insertions, 27 deletions
diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 9851d08..299a70d 100755 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -226,10 +226,11 @@ class SMTP: debuglevel = 0 file = None helo_resp = None + ehlo_msg = "ehlo" ehlo_resp = None does_esmtp = 0 - def __init__(self, host = '', port = 0, local_hostname = None): + def __init__(self, host='', port=0, local_hostname=None, timeout=None): """Initialize a new instance. If specified, `host' is the name of the remote host to which to @@ -240,6 +241,7 @@ class SMTP: the local hostname is found using socket.getfqdn(). """ + self.timeout = timeout self.esmtp_features = {} self.default_port = SMTP_PORT if host: @@ -273,12 +275,11 @@ class SMTP: """ self.debuglevel = debuglevel - def _get_socket(self,af, socktype, proto,sa): + def _get_socket(self, port, host, timeout): # This makes it simpler for SMTP_SSL to use the SMTP connect code # and just alter the socket connection bit. - self.sock = socket.socket(af, socktype, proto) if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - self.sock.connect(sa) + return socket.create_connection((port, host), timeout) def connect(self, host='localhost', port = 0): """Connect to a host on a given port. @@ -297,24 +298,10 @@ class SMTP: host, port = host[:i], host[i+1:] try: port = int(port) except ValueError: - raise socket.error, "nonnumeric port" + raise socket.error("nonnumeric port") if not port: port = self.default_port if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - msg = "getaddrinfo returns an empty list" - self.sock = None - for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - self._get_socket(af,socktype,proto,sa) - except socket.error as msg: - if self.debuglevel > 0: print('connect fail:', msg, file=stderr) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg + self.sock = self._get_socket(host, port, self.timeout) (code, msg) = self.getreply() if self.debuglevel > 0: print("connect:", msg, file=stderr) return (code, msg) @@ -401,7 +388,7 @@ class SMTP: host. """ self.esmtp_features = {} - self.putcmd("ehlo", name or self.local_hostname) + self.putcmd(self.ehlo_msg, name or self.local_hostname) (code,msg)=self.getreply() # According to RFC1869 some (badly written) # MTA's will disconnect on an ehlo. Toss an exception if @@ -731,21 +718,64 @@ class SMTP_SSL(SMTP): are also optional - they can contain a PEM formatted private key and certificate chain file for the SSL connection. """ - def __init__(self, host = '', port = 0, local_hostname = None, - keyfile = None, certfile = None): + def __init__(self, host='', port=0, local_hostname=None, + keyfile=None, certfile=None, timeout=None): self.keyfile = keyfile self.certfile = certfile - SMTP.__init__(self,host,port,local_hostname) + SMTP.__init__(self, host, port, local_hostname, timeout) self.default_port = SMTP_SSL_PORT - def _get_socket(self,af, socktype, proto,sa): - self.sock = socket.socket(af, socktype, proto) + def _get_socket(self, host, port, timeout): if self.debuglevel > 0: print('connect:', (host, port), file=stderr) - self.sock.connect(sa) + self.sock = socket.create_connection((host, port), timeout) sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) self.sock = SSLFakeSocket(self.sock, sslobj) self.file = SSLFakeFile(sslobj) +# +# LMTP extension +# +LMTP_PORT = 2003 + +class LMTP(SMTP): + """LMTP - Local Mail Transfer Protocol + + The LMTP protocol, which is very similar to ESMTP, is heavily based + on the standard SMTP client. It's common to use Unix sockets for LMTP, + so our connect() method must support that as well as a regular + host:port server. To specify a Unix socket, you must use an absolute + path as the host, starting with a '/'. + + Authentication is supported, using the regular SMTP mechanism. When + using a Unix socket, LMTP generally don't support or require any + authentication, but your mileage might vary.""" + + ehlo_msg = "lhlo" + + def __init__(self, host = '', port = LMTP_PORT, local_hostname = None): + """Initialize a new instance.""" + SMTP.__init__(self, host, port, local_hostname) + + def connect(self, host = 'localhost', port = 0): + """Connect to the LMTP daemon, on either a Unix or a TCP socket.""" + if host[0] != '/': + return SMTP.connect(self, host, port) + + # Handle Unix-domain sockets. + try: + self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + self.sock.connect(host) + except socket.error as msg: + if self.debuglevel > 0: print>>stderr, 'connect fail:', host + if self.sock: + self.sock.close() + self.sock = None + raise socket.error(msg) + (code, msg) = self.getreply() + if self.debuglevel > 0: print>>stderr, "connect:", msg + return (code, msg) + + # Test the sendmail method, which tests most of the others. # Note: This always sends to localhost. if __name__ == '__main__': |