Merged revisions 88501 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r88501 | giampaolo.rodola | 2011-02-22 16:56:20 +0100 (mar, 22 feb 2011) | 1 line

  smtlib.py PEP8 normalization via pep8.py script.
........
This commit is contained in:
Giampaolo Rodolà 2011-02-24 20:25:11 +00:00
parent 8edd2e9720
commit f4977d2f50
1 changed files with 73 additions and 63 deletions

View File

@ -52,15 +52,15 @@ import hmac
from email.base64mime import body_encode as encode_base64 from email.base64mime import body_encode as encode_base64
from sys import stderr from sys import stderr
__all__ = ["SMTPException","SMTPServerDisconnected","SMTPResponseException", __all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException",
"SMTPSenderRefused","SMTPRecipientsRefused","SMTPDataError", "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError",
"SMTPConnectError","SMTPHeloError","SMTPAuthenticationError", "SMTPConnectError", "SMTPHeloError", "SMTPAuthenticationError",
"quoteaddr","quotedata","SMTP"] "quoteaddr", "quotedata", "SMTP"]
SMTP_PORT = 25 SMTP_PORT = 25
SMTP_SSL_PORT = 465 SMTP_SSL_PORT = 465
CRLF="\r\n" CRLF = "\r\n"
bCRLF=b"\r\n" bCRLF = b"\r\n"
OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
@ -113,7 +113,7 @@ class SMTPRecipientsRefused(SMTPException):
def __init__(self, recipients): def __init__(self, recipients):
self.recipients = recipients self.recipients = recipients
self.args = ( recipients,) self.args = (recipients,)
class SMTPDataError(SMTPResponseException): class SMTPDataError(SMTPResponseException):
@ -142,7 +142,7 @@ def quoteaddr(addr):
m = email.utils.parseaddr(addr)[1] m = email.utils.parseaddr(addr)[1]
except AttributeError: except AttributeError:
pass pass
if m == (None, None): # Indicates parse failure or AttributeError if m == (None, None): # Indicates parse failure or AttributeError
# something weird here.. punt -ddm # something weird here.. punt -ddm
return "<%s>" % addr return "<%s>" % addr
elif m is None: elif m is None:
@ -185,7 +185,8 @@ else:
chr = None chr = None
while chr != b"\n": while chr != b"\n":
chr = self.sslobj.read(1) chr = self.sslobj.read(1)
if not chr: break if not chr:
break
str += chr str += chr
return str return str
@ -280,10 +281,11 @@ class SMTP:
def _get_socket(self, host, port, timeout): def _get_socket(self, host, port, timeout):
# This makes it simpler for SMTP_SSL to use the SMTP connect code # This makes it simpler for SMTP_SSL to use the SMTP connect code
# and just alter the socket connection bit. # and just alter the socket connection bit.
if self.debuglevel > 0: print('connect:', (host, port), file=stderr) if self.debuglevel > 0:
print('connect:', (host, port), file=stderr)
return socket.create_connection((host, port), timeout) return socket.create_connection((host, port), timeout)
def connect(self, host='localhost', port = 0): def connect(self, host='localhost', port=0):
"""Connect to a host on a given port. """Connect to a host on a given port.
If the hostname ends with a colon (`:') followed by a number, and If the hostname ends with a colon (`:') followed by a number, and
@ -297,20 +299,25 @@ class SMTP:
if not port and (host.find(':') == host.rfind(':')): if not port and (host.find(':') == host.rfind(':')):
i = host.rfind(':') i = host.rfind(':')
if i >= 0: if i >= 0:
host, port = host[:i], host[i+1:] host, port = host[:i], host[i + 1:]
try: port = int(port) try:
port = int(port)
except ValueError: except ValueError:
raise socket.error("nonnumeric port") raise socket.error("nonnumeric port")
if not port: port = self.default_port if not port:
if self.debuglevel > 0: print('connect:', (host, port), file=stderr) port = self.default_port
if self.debuglevel > 0:
print('connect:', (host, port), file=stderr)
self.sock = self._get_socket(host, port, self.timeout) self.sock = self._get_socket(host, port, self.timeout)
(code, msg) = self.getreply() (code, msg) = self.getreply()
if self.debuglevel > 0: print("connect:", msg, file=stderr) if self.debuglevel > 0:
print("connect:", msg, file=stderr)
return (code, msg) return (code, msg)
def send(self, s): def send(self, s):
"""Send `s' to the server.""" """Send `s' to the server."""
if self.debuglevel > 0: print('send:', repr(s), file=stderr) if self.debuglevel > 0:
print('send:', repr(s), file=stderr)
if hasattr(self, 'sock') and self.sock: if hasattr(self, 'sock') and self.sock:
if isinstance(s, str): if isinstance(s, str):
s = s.encode("ascii") s = s.encode("ascii")
@ -343,7 +350,7 @@ class SMTP:
Raises SMTPServerDisconnected if end-of-file is reached. Raises SMTPServerDisconnected if end-of-file is reached.
""" """
resp=[] resp = []
if self.file is None: if self.file is None:
self.file = self.sock.makefile('rb') self.file = self.sock.makefile('rb')
while 1: while 1:
@ -354,9 +361,10 @@ class SMTP:
if not line: if not line:
self.close() self.close()
raise SMTPServerDisconnected("Connection unexpectedly closed") raise SMTPServerDisconnected("Connection unexpectedly closed")
if self.debuglevel > 0: print('reply:', repr(line), file=stderr) if self.debuglevel > 0:
print('reply:', repr(line), file=stderr)
resp.append(line[4:].strip(b' \t\r\n')) resp.append(line[4:].strip(b' \t\r\n'))
code=line[:3] code = line[:3]
# Check that the error code is syntactically correct. # Check that the error code is syntactically correct.
# Don't attempt to read a continuation line if it is broken. # Don't attempt to read a continuation line if it is broken.
try: try:
@ -370,12 +378,12 @@ class SMTP:
errmsg = b"\n".join(resp) errmsg = b"\n".join(resp)
if self.debuglevel > 0: if self.debuglevel > 0:
print('reply: retcode (%s); Msg: %s' % (errcode,errmsg), file=stderr) print('reply: retcode (%s); Msg: %s' % (errcode, errmsg), file=stderr)
return errcode, errmsg return errcode, errmsg
def docmd(self, cmd, args=""): def docmd(self, cmd, args=""):
"""Send a command, and return its response code.""" """Send a command, and return its response code."""
self.putcmd(cmd,args) self.putcmd(cmd, args)
return self.getreply() return self.getreply()
# std smtp commands # std smtp commands
@ -385,9 +393,9 @@ class SMTP:
host. host.
""" """
self.putcmd("helo", name or self.local_hostname) self.putcmd("helo", name or self.local_hostname)
(code,msg)=self.getreply() (code, msg) = self.getreply()
self.helo_resp=msg self.helo_resp = msg
return (code,msg) return (code, msg)
def ehlo(self, name=''): def ehlo(self, name=''):
""" SMTP 'ehlo' command. """ SMTP 'ehlo' command.
@ -396,20 +404,20 @@ class SMTP:
""" """
self.esmtp_features = {} self.esmtp_features = {}
self.putcmd(self.ehlo_msg, name or self.local_hostname) self.putcmd(self.ehlo_msg, name or self.local_hostname)
(code,msg)=self.getreply() (code, msg) = self.getreply()
# According to RFC1869 some (badly written) # According to RFC1869 some (badly written)
# MTA's will disconnect on an ehlo. Toss an exception if # MTA's will disconnect on an ehlo. Toss an exception if
# that happens -ddm # that happens -ddm
if code == -1 and len(msg) == 0: if code == -1 and len(msg) == 0:
self.close() self.close()
raise SMTPServerDisconnected("Server not connected") raise SMTPServerDisconnected("Server not connected")
self.ehlo_resp=msg self.ehlo_resp = msg
if code != 250: if code != 250:
return (code,msg) return (code, msg)
self.does_esmtp=1 self.does_esmtp = 1
#parse the ehlo response -ddm #parse the ehlo response -ddm
assert isinstance(self.ehlo_resp, bytes), repr(self.ehlo_resp) assert isinstance(self.ehlo_resp, bytes), repr(self.ehlo_resp)
resp=self.ehlo_resp.decode("latin-1").split('\n') resp = self.ehlo_resp.decode("latin-1").split('\n')
del resp[0] del resp[0]
for each in resp: for each in resp:
# To be able to communicate with as many SMTP servers as possible, # To be able to communicate with as many SMTP servers as possible,
@ -429,16 +437,16 @@ class SMTP:
# It's actually stricter, in that only spaces are allowed between # It's actually stricter, in that only spaces are allowed between
# parameters, but were not going to check for that here. Note # parameters, but were not going to check for that here. Note
# that the space isn't present if there are no parameters. # that the space isn't present if there are no parameters.
m=re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?',each) m = re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?', each)
if m: if m:
feature=m.group("feature").lower() feature = m.group("feature").lower()
params=m.string[m.end("feature"):].strip() params = m.string[m.end("feature"):].strip()
if feature == "auth": if feature == "auth":
self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \ self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \
+ " " + params + " " + params
else: else:
self.esmtp_features[feature]=params self.esmtp_features[feature] = params
return (code,msg) return (code, msg)
def has_extn(self, opt): def has_extn(self, opt):
"""Does the server support a given SMTP service extension?""" """Does the server support a given SMTP service extension?"""
@ -458,23 +466,23 @@ class SMTP:
"""SMTP 'noop' command -- doesn't do anything :>""" """SMTP 'noop' command -- doesn't do anything :>"""
return self.docmd("noop") return self.docmd("noop")
def mail(self,sender,options=[]): def mail(self, sender, options=[]):
"""SMTP 'mail' command -- begins mail xfer session.""" """SMTP 'mail' command -- begins mail xfer session."""
optionlist = '' optionlist = ''
if options and self.does_esmtp: if options and self.does_esmtp:
optionlist = ' ' + ' '.join(options) optionlist = ' ' + ' '.join(options)
self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender) ,optionlist)) self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist))
return self.getreply() return self.getreply()
def rcpt(self,recip,options=[]): def rcpt(self, recip, options=[]):
"""SMTP 'rcpt' command -- indicates 1 recipient for this mail.""" """SMTP 'rcpt' command -- indicates 1 recipient for this mail."""
optionlist = '' optionlist = ''
if options and self.does_esmtp: if options and self.does_esmtp:
optionlist = ' ' + ' '.join(options) optionlist = ' ' + ' '.join(options)
self.putcmd("rcpt","TO:%s%s" % (quoteaddr(recip),optionlist)) self.putcmd("rcpt", "TO:%s%s" % (quoteaddr(recip), optionlist))
return self.getreply() return self.getreply()
def data(self,msg): def data(self, msg):
"""SMTP 'DATA' command -- sends message data to server. """SMTP 'DATA' command -- sends message data to server.
Automatically quotes lines beginning with a period per rfc821. Automatically quotes lines beginning with a period per rfc821.
@ -485,10 +493,11 @@ class SMTP:
'\r\n' characters. If msg is bytes, it is transmitted as is. '\r\n' characters. If msg is bytes, it is transmitted as is.
""" """
self.putcmd("data") self.putcmd("data")
(code,repl)=self.getreply() (code, repl) = self.getreply()
if self.debuglevel >0 : print("data:", (code,repl), file=stderr) if self.debuglevel > 0:
print("data:", (code, repl), file=stderr)
if code != 354: if code != 354:
raise SMTPDataError(code,repl) raise SMTPDataError(code, repl)
else: else:
if isinstance(msg, str): if isinstance(msg, str):
msg = _fix_eols(msg).encode('ascii') msg = _fix_eols(msg).encode('ascii')
@ -497,16 +506,17 @@ class SMTP:
q = q + bCRLF q = q + bCRLF
q = q + b"." + bCRLF q = q + b"." + bCRLF
self.send(q) self.send(q)
(code,msg)=self.getreply() (code, msg) = self.getreply()
if self.debuglevel >0 : print("data:", (code,msg), file=stderr) if self.debuglevel > 0:
return (code,msg) print("data:", (code, msg), file=stderr)
return (code, msg)
def verify(self, address): def verify(self, address):
"""SMTP 'verify' command -- checks for address validity.""" """SMTP 'verify' command -- checks for address validity."""
self.putcmd("vrfy", quoteaddr(address)) self.putcmd("vrfy", quoteaddr(address))
return self.getreply() return self.getreply()
# a.k.a. # a.k.a.
vrfy=verify vrfy = verify
def expn(self, address): def expn(self, address):
"""SMTP 'expn' command -- expands a mailing list.""" """SMTP 'expn' command -- expands a mailing list."""
@ -564,7 +574,6 @@ class SMTP:
s = "\0%s\0%s" % (user, password) s = "\0%s\0%s" % (user, password)
return encode_base64(s.encode('ascii'), eol='') return encode_base64(s.encode('ascii'), eol='')
AUTH_PLAIN = "PLAIN" AUTH_PLAIN = "PLAIN"
AUTH_CRAM_MD5 = "CRAM-MD5" AUTH_CRAM_MD5 = "CRAM-MD5"
AUTH_LOGIN = "LOGIN" AUTH_LOGIN = "LOGIN"
@ -613,7 +622,7 @@ class SMTP:
# We could not login sucessfully. Return result of last attempt. # We could not login sucessfully. Return result of last attempt.
raise SMTPAuthenticationError(code, resp) raise SMTPAuthenticationError(code, resp)
def starttls(self, keyfile = None, certfile = None): def starttls(self, keyfile=None, certfile=None):
"""Puts the connection to the SMTP server into TLS mode. """Puts the connection to the SMTP server into TLS mode.
If there has been no previous EHLO or HELO command this session, this If there has been no previous EHLO or HELO command this session, this
@ -721,22 +730,22 @@ class SMTP:
esmtp_opts.append("size=%d" % len(msg)) esmtp_opts.append("size=%d" % len(msg))
for option in mail_options: for option in mail_options:
esmtp_opts.append(option) esmtp_opts.append(option)
(code,resp) = self.mail(from_addr, esmtp_opts) (code, resp) = self.mail(from_addr, esmtp_opts)
if code != 250: if code != 250:
self.rset() self.rset()
raise SMTPSenderRefused(code, resp, from_addr) raise SMTPSenderRefused(code, resp, from_addr)
senderrs={} senderrs = {}
if isinstance(to_addrs, str): if isinstance(to_addrs, str):
to_addrs = [to_addrs] to_addrs = [to_addrs]
for each in to_addrs: for each in to_addrs:
(code,resp)=self.rcpt(each, rcpt_options) (code, resp) = self.rcpt(each, rcpt_options)
if (code != 250) and (code != 251): if (code != 250) and (code != 251):
senderrs[each]=(code,resp) senderrs[each] = (code, resp)
if len(senderrs)==len(to_addrs): if len(senderrs) == len(to_addrs):
# the server refused all our recipients # the server refused all our recipients
self.rset() self.rset()
raise SMTPRecipientsRefused(senderrs) raise SMTPRecipientsRefused(senderrs)
(code,resp) = self.data(msg) (code, resp) = self.data(msg)
if code != 250: if code != 250:
self.rset() self.rset()
raise SMTPDataError(code, resp) raise SMTPDataError(code, resp)
@ -770,7 +779,6 @@ class SMTP:
return self.sendmail(from_addr, to_addrs, flatmsg, mail_options, return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
rcpt_options) rcpt_options)
def close(self): def close(self):
"""Close the connection to the SMTP server.""" """Close the connection to the SMTP server."""
if self.file: if self.file:
@ -780,7 +788,6 @@ class SMTP:
self.sock.close() self.sock.close()
self.sock = None self.sock = None
def quit(self): def quit(self):
"""Terminate the SMTP session.""" """Terminate the SMTP session."""
res = self.docmd("quit") res = self.docmd("quit")
@ -806,7 +813,8 @@ if _have_ssl:
self.default_port = SMTP_SSL_PORT self.default_port = SMTP_SSL_PORT
def _get_socket(self, host, port, timeout): def _get_socket(self, host, port, timeout):
if self.debuglevel > 0: print('connect:', (host, port), file=stderr) if self.debuglevel > 0:
print('connect:', (host, port), file=stderr)
new_socket = socket.create_connection((host, port), timeout) new_socket = socket.create_connection((host, port), timeout)
new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile) new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
self.file = SSLFakeFile(new_socket) self.file = SSLFakeFile(new_socket)
@ -834,11 +842,11 @@ class LMTP(SMTP):
ehlo_msg = "lhlo" ehlo_msg = "lhlo"
def __init__(self, host = '', port = LMTP_PORT, local_hostname = None): def __init__(self, host='', port=LMTP_PORT, local_hostname=None):
"""Initialize a new instance.""" """Initialize a new instance."""
SMTP.__init__(self, host, port, local_hostname) SMTP.__init__(self, host, port, local_hostname)
def connect(self, host = 'localhost', port = 0): def connect(self, host='localhost', port=0):
"""Connect to the LMTP daemon, on either a Unix or a TCP socket.""" """Connect to the LMTP daemon, on either a Unix or a TCP socket."""
if host[0] != '/': if host[0] != '/':
return SMTP.connect(self, host, port) return SMTP.connect(self, host, port)
@ -848,13 +856,15 @@ class LMTP(SMTP):
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self.sock.connect(host) self.sock.connect(host)
except socket.error as msg: except socket.error as msg:
if self.debuglevel > 0: print('connect fail:', host, file=stderr) if self.debuglevel > 0:
print('connect fail:', host, file=stderr)
if self.sock: if self.sock:
self.sock.close() self.sock.close()
self.sock = None self.sock = None
raise socket.error(msg) raise socket.error(msg)
(code, msg) = self.getreply() (code, msg) = self.getreply()
if self.debuglevel > 0: print('connect:', msg, file=stderr) if self.debuglevel > 0:
print('connect:', msg, file=stderr)
return (code, msg) return (code, msg)
@ -868,7 +878,7 @@ if __name__ == '__main__':
return sys.stdin.readline().strip() return sys.stdin.readline().strip()
fromaddr = prompt("From") fromaddr = prompt("From")
toaddrs = prompt("To").split(',') toaddrs = prompt("To").split(',')
print("Enter message, end with ^D:") print("Enter message, end with ^D:")
msg = '' msg = ''
while 1: while 1: