smtlib.py PEP8 normalization via pep8.py script.

This commit is contained in:
Giampaolo Rodolà 2011-02-24 20:43:11 +00:00
parent 2bd4795e94
commit 5c12ec6fee
1 changed files with 75 additions and 60 deletions

View File

@ -49,17 +49,18 @@ import hmac
from email.base64mime import encode as encode_base64 from email.base64mime import 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"
OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
# Exception classes used by this module. # Exception classes used by this module.
class SMTPException(Exception): class SMTPException(Exception):
"""Base class for all exceptions raised by this module.""" """Base class for all exceptions raised by this module."""
@ -109,7 +110,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):
@ -128,6 +129,7 @@ class SMTPAuthenticationError(SMTPResponseException):
combination provided. combination provided.
""" """
def quoteaddr(addr): def quoteaddr(addr):
"""Quote a subset of the email addresses defined by RFC 821. """Quote a subset of the email addresses defined by RFC 821.
@ -138,7 +140,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:
@ -175,7 +177,8 @@ else:
chr = None chr = None
while chr != "\n": while chr != "\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
@ -269,10 +272,11 @@ class SMTP:
def _get_socket(self, port, host, timeout): def _get_socket(self, port, host, 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>>stderr, 'connect:', (host, port) if self.debuglevel > 0:
print>>stderr, 'connect:', (host, port)
return socket.create_connection((port, host), timeout) return socket.create_connection((port, host), 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
@ -286,20 +290,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>>stderr, 'connect:', (host, port) port = self.default_port
if self.debuglevel > 0:
print>>stderr, 'connect:', (host, port)
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>>stderr, "connect:", msg if self.debuglevel > 0:
print>>stderr, "connect:", msg
return (code, msg) return (code, msg)
def send(self, str): def send(self, str):
"""Send `str' to the server.""" """Send `str' to the server."""
if self.debuglevel > 0: print>>stderr, 'send:', repr(str) if self.debuglevel > 0:
print>>stderr, 'send:', repr(str)
if hasattr(self, 'sock') and self.sock: if hasattr(self, 'sock') and self.sock:
try: try:
self.sock.sendall(str) self.sock.sendall(str)
@ -330,7 +339,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:
@ -341,9 +350,10 @@ class SMTP:
if line == '': if line == '':
self.close() self.close()
raise SMTPServerDisconnected("Connection unexpectedly closed") raise SMTPServerDisconnected("Connection unexpectedly closed")
if self.debuglevel > 0: print>>stderr, 'reply:', repr(line) if self.debuglevel > 0:
print>>stderr, 'reply:', repr(line)
resp.append(line[4:].strip()) resp.append(line[4:].strip())
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:
@ -352,17 +362,17 @@ class SMTP:
errcode = -1 errcode = -1
break break
# Check if multiline response. # Check if multiline response.
if line[3:4]!="-": if line[3:4] != "-":
break break
errmsg = "\n".join(resp) errmsg = "\n".join(resp)
if self.debuglevel > 0: if self.debuglevel > 0:
print>>stderr, 'reply: retcode (%s); Msg: %s' % (errcode,errmsg) print>>stderr, 'reply: retcode (%s); Msg: %s' % (errcode, errmsg)
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
@ -372,9 +382,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.
@ -383,19 +393,19 @@ 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
resp=self.ehlo_resp.split('\n') resp = self.ehlo_resp.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,
@ -415,16 +425,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?"""
@ -444,23 +454,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.
@ -469,26 +479,28 @@ class SMTP:
response code received when the all data is sent. response code received when the all data is sent.
""" """
self.putcmd("data") self.putcmd("data")
(code,repl)=self.getreply() (code, repl) = self.getreply()
if self.debuglevel >0 : print>>stderr, "data:", (code,repl) if self.debuglevel > 0:
print>>stderr, "data:", (code, repl)
if code != 354: if code != 354:
raise SMTPDataError(code,repl) raise SMTPDataError(code, repl)
else: else:
q = quotedata(msg) q = quotedata(msg)
if q[-2:] != CRLF: if q[-2:] != CRLF:
q = q + CRLF q = q + CRLF
q = q + "." + CRLF q = q + "." + CRLF
self.send(q) self.send(q)
(code,msg)=self.getreply() (code, msg) = self.getreply()
if self.debuglevel >0 : print>>stderr, "data:", (code,msg) if self.debuglevel > 0:
return (code,msg) print>>stderr, "data:", (code, msg)
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."""
@ -592,7 +604,7 @@ class SMTP:
raise SMTPAuthenticationError(code, resp) raise SMTPAuthenticationError(code, resp)
return (code, resp) return (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
@ -695,22 +707,22 @@ class SMTP:
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, basestring): if isinstance(to_addrs, basestring):
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)
@ -753,7 +765,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>>stderr, 'connect:', (host, port) if self.debuglevel > 0:
print>>stderr, 'connect:', (host, port)
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)
@ -781,11 +794,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)
@ -795,13 +808,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, msg: except socket.error, msg:
if self.debuglevel > 0: print>>stderr, 'connect fail:', host if self.debuglevel > 0:
print>>stderr, 'connect fail:', host
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>>stderr, "connect:", msg if self.debuglevel > 0:
print>>stderr, "connect:", msg
return (code, msg) return (code, msg)
@ -815,7 +830,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: