<s> '''<STR_LIT>''' <EOL> import socket <EOL> import re <EOL> import email . Utils <EOL> import base64 <EOL> import hmac <EOL> from email . base64MIME import encode as encode_base64 <EOL> from sys import stderr <EOL> __all__ = [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> SMTP_PORT = <NUM_LIT> <EOL> CRLF = "<STR_LIT:\r\n>" <EOL> OLDSTYLE_AUTH = re . compile ( r"<STR_LIT>" , re . I ) <EOL> class SMTPException ( Exception ) : <EOL> """<STR_LIT>""" <EOL> class SMTPServerDisconnected ( SMTPException ) : <EOL> """<STR_LIT>""" <EOL> class SMTPResponseException ( SMTPException ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , code , msg ) : <EOL> self . smtp_code = code <EOL> self . smtp_error = msg <EOL> self . args = ( code , msg ) <EOL> class SMTPSenderRefused ( SMTPResponseException ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , code , msg , sender ) : <EOL> self . smtp_code = code <EOL> self . smtp_error = msg <EOL> self . sender = sender <EOL> self . args = ( code , msg , sender ) <EOL> class SMTPRecipientsRefused ( SMTPException ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , recipients ) : <EOL> self . recipients = recipients <EOL> self . args = ( recipients , ) <EOL> class SMTPDataError ( SMTPResponseException ) : <EOL> """<STR_LIT>""" <EOL> class SMTPConnectError ( SMTPResponseException ) : <EOL> """<STR_LIT>""" <EOL> class SMTPHeloError ( SMTPResponseException ) : <EOL> """<STR_LIT>""" <EOL> class SMTPAuthenticationError ( SMTPResponseException ) : <EOL> """<STR_LIT>""" <EOL> class SSLFakeSocket : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , realsock , sslobj ) : <EOL> self . realsock = realsock <EOL> self . sslobj = sslobj <EOL> def send ( self , str ) : <EOL> self . sslobj . write ( str ) <EOL> return len ( str ) <EOL> sendall = send <EOL> def close ( self ) : <EOL> self . realsock . close ( ) <EOL> class SSLFakeFile : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , sslobj ) : <EOL> self . sslobj = sslobj <EOL> def readline ( self ) : <EOL> str = "<STR_LIT>" <EOL> chr = None <EOL> while chr != "<STR_LIT:\n>" : <EOL> chr = self . sslobj . read ( <NUM_LIT:1> ) <EOL> str += chr <EOL> return str <EOL> def close ( self ) : <EOL> pass <EOL> def quoteaddr ( addr ) : <EOL> """<STR_LIT>""" <EOL> m = ( None , None ) <EOL> try : <EOL> m = email . Utils . parseaddr ( addr ) [ <NUM_LIT:1> ] <EOL> except AttributeError : <EOL> pass <EOL> if m == ( None , None ) : <EOL> return "<STR_LIT>" % addr <EOL> elif m is None : <EOL> return "<STR_LIT>" <EOL> else : <EOL> return "<STR_LIT>" % m <EOL> def quotedata ( data ) : <EOL> """<STR_LIT>""" <EOL> return re . sub ( r'<STR_LIT>' , '<STR_LIT:..>' , <EOL> re . sub ( r'<STR_LIT>' , CRLF , data ) ) <EOL> class SMTP : <EOL> """<STR_LIT>""" <EOL> debuglevel = <NUM_LIT:0> <EOL> file = None <EOL> helo_resp = None <EOL> ehlo_resp = None <EOL> does_esmtp = <NUM_LIT:0> <EOL> def __init__ ( self , host = '<STR_LIT>' , port = <NUM_LIT:0> , local_hostname = None ) : <EOL> """<STR_LIT>""" <EOL> self . esmtp_features = { } <EOL> if host : <EOL> ( code , msg ) = self . connect ( host , port ) <EOL> if code != <NUM_LIT> : <EOL> raise SMTPConnectError ( code , msg ) <EOL> if local_hostname is not None : <EOL> self . local_hostname = local_hostname <EOL> else : <EOL> fqdn = socket . getfqdn ( ) <EOL> if '<STR_LIT:.>' in fqdn : <EOL> self . local_hostname = fqdn <EOL> else : <EOL> addr = '<STR_LIT:127.0.0.1>' <EOL> try : <EOL> addr = socket . gethostbyname ( socket . gethostname ( ) ) <EOL> except socket . gaierror : <EOL> pass <EOL> self . local_hostname = '<STR_LIT>' % addr <EOL> def set_debuglevel ( self , debuglevel ) : <EOL> """<STR_LIT>""" <EOL> self . debuglevel = debuglevel <EOL> def connect ( self , host = '<STR_LIT:localhost>' , port = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> if not port and ( host . find ( '<STR_LIT::>' ) == host . rfind ( '<STR_LIT::>' ) ) : <EOL> i = host . rfind ( '<STR_LIT::>' ) <EOL> if i >= <NUM_LIT:0> : <EOL> host , port = host [ : i ] , host [ i + <NUM_LIT:1> : ] <EOL> try : port = int ( port ) <EOL> except ValueError : <EOL> raise socket . error , "<STR_LIT>" <EOL> if not port : port = SMTP_PORT <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , '<STR_LIT>' , ( host , port ) <EOL> msg = "<STR_LIT>" <EOL> self . sock = None <EOL> for res in socket . getaddrinfo ( host , port , <NUM_LIT:0> , socket . SOCK_STREAM ) : <EOL> af , socktype , proto , canonname , sa = res <EOL> try : <EOL> self . sock = socket . socket ( af , socktype , proto ) <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , '<STR_LIT>' , sa <EOL> self . sock . connect ( sa ) <EOL> except socket . error , msg : <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , '<STR_LIT>' , msg <EOL> if self . sock : <EOL> self . sock . close ( ) <EOL> self . sock = None <EOL> continue <EOL> break <EOL> if not self . sock : <EOL> raise socket . error , msg <EOL> ( code , msg ) = self . getreply ( ) <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , "<STR_LIT>" , msg <EOL> return ( code , msg ) <EOL> def send ( self , str ) : <EOL> """<STR_LIT>""" <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , '<STR_LIT>' , repr ( str ) <EOL> if self . sock : <EOL> try : <EOL> self . sock . sendall ( str ) <EOL> except socket . error : <EOL> self . close ( ) <EOL> raise SMTPServerDisconnected ( '<STR_LIT>' ) <EOL> else : <EOL> raise SMTPServerDisconnected ( '<STR_LIT>' ) <EOL> def putcmd ( self , cmd , args = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> if args == "<STR_LIT>" : <EOL> str = '<STR_LIT>' % ( cmd , CRLF ) <EOL> else : <EOL> str = '<STR_LIT>' % ( cmd , args , CRLF ) <EOL> self . send ( str ) <EOL> def getreply ( self ) : <EOL> """<STR_LIT>""" <EOL> resp = [ ] <EOL> if self . file is None : <EOL> self . file = self . sock . makefile ( '<STR_LIT:rb>' ) <EOL> while <NUM_LIT:1> : <EOL> line = self . file . readline ( ) <EOL> if line == '<STR_LIT>' : <EOL> self . close ( ) <EOL> raise SMTPServerDisconnected ( "<STR_LIT>" ) <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , '<STR_LIT>' , repr ( line ) <EOL> resp . append ( line [ <NUM_LIT:4> : ] . strip ( ) ) <EOL> code = line [ : <NUM_LIT:3> ] <EOL> try : <EOL> errcode = int ( code ) <EOL> except ValueError : <EOL> errcode = - <NUM_LIT:1> <EOL> break <EOL> if line [ <NUM_LIT:3> : <NUM_LIT:4> ] != "<STR_LIT:->" : <EOL> break <EOL> errmsg = "<STR_LIT:\n>" . join ( resp ) <EOL> if self . debuglevel > <NUM_LIT:0> : <EOL> print >> stderr , '<STR_LIT>' % ( errcode , errmsg ) <EOL> return errcode , errmsg <EOL> def docmd ( self , cmd , args = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> self . putcmd ( cmd , args ) <EOL> return self . getreply ( ) <EOL> def helo ( self , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> self . putcmd ( "<STR_LIT>" , name or self . local_hostname ) <EOL> ( code , msg ) = self . getreply ( ) <EOL> self . helo_resp = msg <EOL> return ( code , msg ) <EOL> def ehlo ( self , name = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> self . esmtp_features = { } <EOL> self . putcmd ( "<STR_LIT>" , name or self . local_hostname ) <EOL> ( code , msg ) = self . getreply ( ) <EOL> if code == - <NUM_LIT:1> and len ( msg ) == <NUM_LIT:0> : <EOL> self . close ( ) <EOL> raise SMTPServerDisconnected ( "<STR_LIT>" ) <EOL> self . ehlo_resp = msg <EOL> if code != <NUM_LIT> : <EOL> return ( code , msg ) <EOL> self . does_esmtp = <NUM_LIT:1> <EOL> resp = self . ehlo_resp . split ( '<STR_LIT:\n>' ) <EOL> del resp [ <NUM_LIT:0> ] <EOL> for each in resp : <EOL> auth_match = OLDSTYLE_AUTH . match ( each ) <EOL> if auth_match : <EOL> self . esmtp_features [ "<STR_LIT>" ] = self . esmtp_features . get ( "<STR_LIT>" , "<STR_LIT>" ) + "<STR_LIT:U+0020>" + auth_match . groups ( <NUM_LIT:0> ) [ <NUM_LIT:0> ] <EOL> continue <EOL> m = re . match ( r'<STR_LIT>' , each ) <EOL> if m : <EOL> feature = m . group ( "<STR_LIT>" ) . lower ( ) <EOL> params = m . string [ m . end ( "<STR_LIT>" ) : ] . strip ( ) <EOL> if feature == "<STR_LIT>" : <EOL> self . esmtp_features [ feature ] = self . esmtp_features . get ( feature , "<STR_LIT>" ) + "<STR_LIT:U+0020>" + params <EOL> else : <EOL> self . esmtp_features [ feature ] = params <EOL> return ( code , msg ) <EOL> def has_extn ( self , opt ) : <EOL> """<STR_LIT>""" <EOL> return opt . lower ( ) in self . esmtp_features <EOL> def help ( self , args = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> self . putcmd ( "<STR_LIT>" , args ) <EOL> return self . getreply ( ) [ <NUM_LIT:1> ] <EOL> def rset ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . docmd ( "<STR_LIT>" ) <EOL> def noop ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . docmd ( "<STR_LIT>" ) <EOL> def mail ( self , sender , options = [ ] ) : <EOL> """<STR_LIT>""" <EOL> optionlist = '<STR_LIT>' <EOL> if options and self . does_esmtp : <EOL> optionlist = '<STR_LIT:U+0020>' + '<STR_LIT:U+0020>' . join ( options ) <EOL> self . putcmd ( "<STR_LIT>" , "<STR_LIT>" % ( quoteaddr ( sender ) , optionlist ) ) <EOL> return self . getreply ( ) <EOL> def rcpt ( self , recip , options = [ ] ) : <EOL> """<STR_LIT>""" <EOL> optionlist = '<STR_LIT>' <EOL> if options and self . does_esmtp : <EOL> optionlist = '<STR_LIT:U+0020>' + '<STR_LIT:U+0020>' . join ( options ) <EOL> self . putcmd ( "<STR_LIT>" , "<STR_LIT>" % ( quoteaddr ( recip ) , optionlist ) ) <EOL> return self . getreply ( ) <EOL> def data ( self , msg ) : <EOL> """<STR_LIT>""" <EOL> self . putcmd ( "<STR_LIT:data>" ) <EOL> ( code , repl ) = self . getreply ( ) <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , "<STR_LIT>" , ( code , repl ) <EOL> if code != <NUM_LIT> : <EOL> raise SMTPDataError ( code , repl ) <EOL> else : <EOL> q = quotedata ( msg ) <EOL> if q [ - <NUM_LIT:2> : ] != CRLF : <EOL> q = q + CRLF <EOL> q = q + "<STR_LIT:.>" + CRLF <EOL> self . send ( q ) <EOL> ( code , msg ) = self . getreply ( ) <EOL> if self . debuglevel > <NUM_LIT:0> : print >> stderr , "<STR_LIT>" , ( code , msg ) <EOL> return ( code , msg ) <EOL> def verify ( self , address ) : <EOL> """<STR_LIT>""" <EOL> self . putcmd ( "<STR_LIT>" , quoteaddr ( address ) ) <EOL> return self . getreply ( ) <EOL> vrfy = verify <EOL> def expn ( self , address ) : <EOL> """<STR_LIT>""" <EOL> self . putcmd ( "<STR_LIT>" , quoteaddr ( address ) ) <EOL> return self . getreply ( ) <EOL> def login ( self , user , password ) : <EOL> """<STR_LIT>""" <EOL> def encode_cram_md5 ( challenge , user , password ) : <EOL> challenge = base64 . decodestring ( challenge ) <EOL> response = user + "<STR_LIT:U+0020>" + hmac . HMAC ( password , challenge ) . hexdigest ( ) <EOL> return encode_base64 ( response , eol = "<STR_LIT>" ) <EOL> def encode_plain ( user , password ) : <EOL> return encode_base64 ( "<STR_LIT>" % ( user , password ) , eol = "<STR_LIT>" ) <EOL> AUTH_PLAIN = "<STR_LIT>" <EOL> AUTH_CRAM_MD5 = "<STR_LIT>" <EOL> AUTH_LOGIN = "<STR_LIT>" <EOL> if self . helo_resp is None and self . ehlo_resp is None : <EOL> if not ( <NUM_LIT:200> <= self . ehlo ( ) [ <NUM_LIT:0> ] <= <NUM_LIT> ) : <EOL> ( code , resp ) = self . helo ( ) <EOL> if not ( <NUM_LIT:200> <= code <= <NUM_LIT> ) : <EOL> raise SMTPHeloError ( code , resp ) <EOL> if not self . has_extn ( "<STR_LIT>" ) : <EOL> raise SMTPException ( "<STR_LIT>" ) <EOL> authlist = self . esmtp_features [ "<STR_LIT>" ] . split ( ) <EOL> preferred_auths = [ AUTH_CRAM_MD5 , AUTH_PLAIN , AUTH_LOGIN ] <EOL> authmethod = None <EOL> for method in preferred_auths : <EOL> if method in authlist : <EOL> authmethod = method <EOL> break <EOL> if authmethod == AUTH_CRAM_MD5 : <EOL> ( code , resp ) = self . docmd ( "<STR_LIT>" , AUTH_CRAM_MD5 ) <EOL> if code == <NUM_LIT> : <EOL> return ( code , resp ) <EOL> ( code , resp ) = self . docmd ( encode_cram_md5 ( resp , user , password ) ) <EOL> elif authmethod == AUTH_PLAIN : <EOL> ( code , resp ) = self . docmd ( "<STR_LIT>" , <EOL> AUTH_PLAIN + "<STR_LIT:U+0020>" + encode_plain ( user , password ) ) <EOL> elif authmethod == AUTH_LOGIN : <EOL> ( code , resp ) = self . docmd ( "<STR_LIT>" , <EOL> "<STR_LIT>" % ( AUTH_LOGIN , encode_base64 ( user , eol = "<STR_LIT>" ) ) ) <EOL> if code != <NUM_LIT> : <EOL> raise SMTPAuthenticationError ( code , resp ) <EOL> ( code , resp ) = self . docmd ( encode_base64 ( password , eol = "<STR_LIT>" ) ) <EOL> elif authmethod is None : <EOL> raise SMTPException ( "<STR_LIT>" ) <EOL> if code not in ( <NUM_LIT> , <NUM_LIT> ) : <EOL> raise SMTPAuthenticationError ( code , resp ) <EOL> return ( code , resp ) <EOL> def starttls ( self , keyfile = None , certfile = None ) : <EOL> """<STR_LIT>""" <EOL> ( resp , reply ) = self . docmd ( "<STR_LIT>" ) <EOL> if resp == <NUM_LIT> : <EOL> sslobj = socket . ssl ( self . sock , keyfile , certfile ) <EOL> self . sock = SSLFakeSocket ( self . sock , sslobj ) <EOL> self . file = SSLFakeFile ( sslobj ) <EOL> self . helo_resp = None <EOL> self . ehlo_resp = None <EOL> self . esmtp_features = { } <EOL> self . does_esmtp = <NUM_LIT:0> <EOL> return ( resp , reply ) <EOL> def sendmail ( self , from_addr , to_addrs , msg , mail_options = [ ] , <EOL> rcpt_options = [ ] ) : <EOL> """<STR_LIT>""" <EOL> if self . helo_resp is None and self . ehlo_resp is None : <EOL> if not ( <NUM_LIT:200> <= self . ehlo ( ) [ <NUM_LIT:0> ] <= <NUM_LIT> ) : <EOL> ( code , resp ) = self . helo ( ) <EOL> if not ( <NUM_LIT:200> <= code <= <NUM_LIT> ) : <EOL> raise SMTPHeloError ( code , resp ) <EOL> esmtp_opts = [ ] <EOL> if self . does_esmtp : <EOL> if self . has_extn ( '<STR_LIT:size>' ) : <EOL> esmtp_opts . append ( "<STR_LIT>" % len ( msg ) ) <EOL> for option in mail_options : <EOL> esmtp_opts . append ( option ) <EOL> ( code , resp ) = self . mail ( from_addr , esmtp_opts ) <EOL> if code != <NUM_LIT> : <EOL> self . rset ( ) <EOL> raise SMTPSenderRefused ( code , resp , from_addr ) <EOL> senderrs = { } <EOL> if isinstance ( to_addrs , basestring ) : <EOL> to_addrs = [ to_addrs ] <EOL> for each in to_addrs : <EOL> ( code , resp ) = self . rcpt ( each , rcpt_options ) <EOL> if ( code != <NUM_LIT> ) and ( code != <NUM_LIT> ) : <EOL> senderrs [ each ] = ( code , resp ) <EOL> if len ( senderrs ) == len ( to_addrs ) : <EOL> self . rset ( ) <EOL> raise SMTPRecipientsRefused ( senderrs ) <EOL> ( code , resp ) = self . data ( msg ) <EOL> if code != <NUM_LIT> : <EOL> self . rset ( ) <EOL> raise SMTPDataError ( code , resp ) <EOL> return senderrs <EOL> def close ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . file : <EOL> self . file . close ( ) <EOL> self . file = None <EOL> if self . sock : <EOL> self . sock . close ( ) <EOL> self . sock = None <EOL> def quit ( self ) : <EOL> """<STR_LIT>""" <EOL> self . docmd ( "<STR_LIT>" ) <EOL> self . close ( ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> import sys <EOL> def prompt ( prompt ) : <EOL> sys . stdout . write ( prompt + "<STR_LIT>" ) <EOL> return sys . stdin . readline ( ) . strip ( ) <EOL> fromaddr = prompt ( "<STR_LIT>" ) <EOL> toaddrs = prompt ( "<STR_LIT>" ) . split ( '<STR_LIT:U+002C>' ) <EOL> print "<STR_LIT>" <EOL> msg = '<STR_LIT>' <EOL> while <NUM_LIT:1> : <EOL> line = sys . stdin . readline ( ) <EOL> if not line : <EOL> break <EOL> msg = msg + line <EOL> print "<STR_LIT>" % len ( msg ) <EOL> server = SMTP ( '<STR_LIT:localhost>' ) <EOL> server . set_debuglevel ( <NUM_LIT:1> ) <EOL> server . sendmail ( fromaddr , toaddrs , msg ) <EOL> server . quit ( ) </s>
