summaryrefslogtreecommitdiffstats
path: root/Lib/smtplib.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/smtplib.py')
-rwxr-xr-xLib/smtplib.py84
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__':