home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2012 January / maximum-cd-2012-01.iso / DiscContents / digsby_setup.exe / lib / smtplib.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-10-05  |  16.0 KB  |  605 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. import socket
  5. import re
  6. import email.utils as email
  7. import base64
  8. import hmac
  9. from email.base64mime import encode as encode_base64
  10. from sys import stderr
  11. __all__ = [
  12.     'SMTPException',
  13.     'SMTPServerDisconnected',
  14.     'SMTPResponseException',
  15.     'SMTPSenderRefused',
  16.     'SMTPRecipientsRefused',
  17.     'SMTPDataError',
  18.     'SMTPConnectError',
  19.     'SMTPHeloError',
  20.     'SMTPAuthenticationError',
  21.     'quoteaddr',
  22.     'quotedata',
  23.     'SMTP']
  24. SMTP_PORT = 25
  25. SMTP_SSL_PORT = 465
  26. CRLF = '\r\n'
  27. OLDSTYLE_AUTH = re.compile('auth=(.*)', re.I)
  28.  
  29. class SMTPException(Exception):
  30.     pass
  31.  
  32.  
  33. class SMTPServerDisconnected(SMTPException):
  34.     pass
  35.  
  36.  
  37. class SMTPResponseException(SMTPException):
  38.     
  39.     def __init__(self, code, msg):
  40.         self.smtp_code = code
  41.         self.smtp_error = msg
  42.         self.args = (code, msg)
  43.  
  44.  
  45.  
  46. class SMTPSenderRefused(SMTPResponseException):
  47.     
  48.     def __init__(self, code, msg, sender):
  49.         self.smtp_code = code
  50.         self.smtp_error = msg
  51.         self.sender = sender
  52.         self.args = (code, msg, sender)
  53.  
  54.  
  55.  
  56. class SMTPRecipientsRefused(SMTPException):
  57.     
  58.     def __init__(self, recipients):
  59.         self.recipients = recipients
  60.         self.args = (recipients,)
  61.  
  62.  
  63.  
  64. class SMTPDataError(SMTPResponseException):
  65.     pass
  66.  
  67.  
  68. class SMTPConnectError(SMTPResponseException):
  69.     pass
  70.  
  71.  
  72. class SMTPHeloError(SMTPResponseException):
  73.     pass
  74.  
  75.  
  76. class SMTPAuthenticationError(SMTPResponseException):
  77.     pass
  78.  
  79.  
  80. def quoteaddr(addr):
  81.     m = (None, None)
  82.     
  83.     try:
  84.         m = email.utils.parseaddr(addr)[1]
  85.     except AttributeError:
  86.         pass
  87.  
  88.     if m == (None, None):
  89.         return '<%s>' % addr
  90.     if m is None:
  91.         return '<>'
  92.     return '<%s>' % m
  93.  
  94.  
  95. def quotedata(data):
  96.     return re.sub('(?m)^\\.', '..', re.sub('(?:\\r\\n|\\n|\\r(?!\\n))', CRLF, data))
  97.  
  98.  
  99. try:
  100.     import ssl
  101. except ImportError:
  102.     _have_ssl = False
  103.  
  104.  
  105. class SSLFakeFile:
  106.     
  107.     def __init__(self, sslobj):
  108.         self.sslobj = sslobj
  109.  
  110.     
  111.     def readline(self):
  112.         str = ''
  113.         chr = None
  114.         while chr != '\n':
  115.             chr = self.sslobj.read(1)
  116.             if not chr:
  117.                 break
  118.             
  119.             str += chr
  120.         return str
  121.  
  122.     
  123.     def close(self):
  124.         pass
  125.  
  126.  
  127. _have_ssl = True
  128.  
  129. class SMTP:
  130.     debuglevel = 0
  131.     file = None
  132.     helo_resp = None
  133.     ehlo_msg = 'ehlo'
  134.     ehlo_resp = None
  135.     does_esmtp = 0
  136.     
  137.     def __init__(self, host = '', port = 0, local_hostname = None, timeout = socket._GLOBAL_DEFAULT_TIMEOUT):
  138.         self.timeout = timeout
  139.         self.esmtp_features = { }
  140.         self.default_port = SMTP_PORT
  141.         if host:
  142.             (code, msg) = self.connect(host, port)
  143.             if code != 220:
  144.                 raise SMTPConnectError(code, msg)
  145.             code != 220
  146.         
  147.         if local_hostname is not None:
  148.             self.local_hostname = local_hostname
  149.         else:
  150.             fqdn = socket.getfqdn()
  151.             if '.' in fqdn:
  152.                 self.local_hostname = fqdn
  153.             else:
  154.                 addr = '127.0.0.1'
  155.                 
  156.                 try:
  157.                     addr = socket.gethostbyname(socket.gethostname())
  158.                 except socket.gaierror:
  159.                     pass
  160.  
  161.                 self.local_hostname = '[%s]' % addr
  162.  
  163.     
  164.     def set_debuglevel(self, debuglevel):
  165.         self.debuglevel = debuglevel
  166.  
  167.     
  168.     def _get_socket(self, port, host, timeout):
  169.         if self.debuglevel > 0:
  170.             print >>stderr, 'connect:', (host, port)
  171.         
  172.         return socket.create_connection((port, host), timeout)
  173.  
  174.     
  175.     def connect(self, host = 'localhost', port = 0):
  176.         if not port and host.find(':') == host.rfind(':'):
  177.             i = host.rfind(':')
  178.             if i >= 0:
  179.                 host = host[:i]
  180.                 port = host[i + 1:]
  181.                 
  182.                 try:
  183.                     port = int(port)
  184.                 except ValueError:
  185.                     raise socket.error, 'nonnumeric port'
  186.                 except:
  187.                     None<EXCEPTION MATCH>ValueError
  188.                 
  189.  
  190.             None<EXCEPTION MATCH>ValueError
  191.         
  192.         if not port:
  193.             port = self.default_port
  194.         
  195.         if self.debuglevel > 0:
  196.             print >>stderr, 'connect:', (host, port)
  197.         
  198.         self.sock = self._get_socket(host, port, self.timeout)
  199.         (code, msg) = self.getreply()
  200.         if self.debuglevel > 0:
  201.             print >>stderr, 'connect:', msg
  202.         
  203.         return (code, msg)
  204.  
  205.     
  206.     def send(self, str):
  207.         if self.debuglevel > 0:
  208.             print >>stderr, 'send:', repr(str)
  209.         
  210.         if hasattr(self, 'sock') and self.sock:
  211.             
  212.             try:
  213.                 self.sock.sendall(str)
  214.             except socket.error:
  215.                 self.close()
  216.                 raise SMTPServerDisconnected('Server not connected')
  217.             except:
  218.                 None<EXCEPTION MATCH>socket.error
  219.             
  220.  
  221.         None<EXCEPTION MATCH>socket.error
  222.         raise SMTPServerDisconnected('please run connect() first')
  223.  
  224.     
  225.     def putcmd(self, cmd, args = ''):
  226.         if args == '':
  227.             str = '%s%s' % (cmd, CRLF)
  228.         else:
  229.             str = '%s %s%s' % (cmd, args, CRLF)
  230.         self.send(str)
  231.  
  232.     
  233.     def getreply(self):
  234.         resp = []
  235.         if self.file is None:
  236.             self.file = self.sock.makefile('rb')
  237.         
  238.         while None:
  239.             line = self.file.readline()
  240.             if line == '':
  241.                 self.close()
  242.                 raise SMTPServerDisconnected('Connection unexpectedly closed')
  243.             if self.debuglevel > 0:
  244.                 print >>stderr, 'reply:', repr(line)
  245.             
  246.             resp.append(line[4:].strip())
  247.             code = line[:3]
  248.             
  249.             try:
  250.                 errcode = int(code)
  251.             except ValueError:
  252.                 errcode = -1
  253.                 break
  254.  
  255.             if line[3:4] != '-':
  256.                 break
  257.                 continue
  258.             continue
  259.             errmsg = '\n'.join(resp)
  260.             if self.debuglevel > 0:
  261.                 print >>stderr, 'reply: retcode (%s); Msg: %s' % (errcode, errmsg)
  262.             
  263.         return (errcode, errmsg)
  264.  
  265.     
  266.     def docmd(self, cmd, args = ''):
  267.         self.putcmd(cmd, args)
  268.         return self.getreply()
  269.  
  270.     
  271.     def helo(self, name = ''):
  272.         if not name:
  273.             pass
  274.         self.putcmd('helo', self.local_hostname)
  275.         (code, msg) = self.getreply()
  276.         self.helo_resp = msg
  277.         return (code, msg)
  278.  
  279.     
  280.     def ehlo(self, name = ''):
  281.         self.esmtp_features = { }
  282.         if not name:
  283.             pass
  284.         self.putcmd(self.ehlo_msg, self.local_hostname)
  285.         (code, msg) = self.getreply()
  286.         if code == -1 and len(msg) == 0:
  287.             self.close()
  288.             raise SMTPServerDisconnected('Server not connected')
  289.         len(msg) == 0
  290.         self.ehlo_resp = msg
  291.         if code != 250:
  292.             return (code, msg)
  293.         self.does_esmtp = 1
  294.         resp = self.ehlo_resp.split('\n')
  295.         del resp[0]
  296.         for each in resp:
  297.             auth_match = OLDSTYLE_AUTH.match(each)
  298.             if auth_match:
  299.                 self.esmtp_features['auth'] = self.esmtp_features.get('auth', '') + ' ' + auth_match.groups(0)[0]
  300.                 continue
  301.             
  302.             m = re.match('(?P<feature>[A-Za-z0-9][A-Za-z0-9\\-]*) ?', each)
  303.             if m:
  304.                 feature = m.group('feature').lower()
  305.                 params = m.string[m.end('feature'):].strip()
  306.                 if feature == 'auth':
  307.                     self.esmtp_features[feature] = self.esmtp_features.get(feature, '') + ' ' + params
  308.                 else:
  309.                     self.esmtp_features[feature] = params
  310.             feature == 'auth'
  311.         
  312.         return (code, msg)
  313.  
  314.     
  315.     def has_extn(self, opt):
  316.         return opt.lower() in self.esmtp_features
  317.  
  318.     
  319.     def help(self, args = ''):
  320.         self.putcmd('help', args)
  321.         return self.getreply()[1]
  322.  
  323.     
  324.     def rset(self):
  325.         return self.docmd('rset')
  326.  
  327.     
  328.     def noop(self):
  329.         return self.docmd('noop')
  330.  
  331.     
  332.     def mail(self, sender, options = []):
  333.         optionlist = ''
  334.         if options and self.does_esmtp:
  335.             optionlist = ' ' + ' '.join(options)
  336.         
  337.         self.putcmd('mail', 'FROM:%s%s' % (quoteaddr(sender), optionlist))
  338.         return self.getreply()
  339.  
  340.     
  341.     def rcpt(self, recip, options = []):
  342.         optionlist = ''
  343.         if options and self.does_esmtp:
  344.             optionlist = ' ' + ' '.join(options)
  345.         
  346.         self.putcmd('rcpt', 'TO:%s%s' % (quoteaddr(recip), optionlist))
  347.         return self.getreply()
  348.  
  349.     
  350.     def data(self, msg):
  351.         self.putcmd('data')
  352.         (code, repl) = self.getreply()
  353.         if self.debuglevel > 0:
  354.             print >>stderr, 'data:', (code, repl)
  355.         
  356.         if code != 354:
  357.             raise SMTPDataError(code, repl)
  358.         code != 354
  359.         q = quotedata(msg)
  360.         if q[-2:] != CRLF:
  361.             q = q + CRLF
  362.         
  363.         q = q + '.' + CRLF
  364.         self.send(q)
  365.         (code, msg) = self.getreply()
  366.         if self.debuglevel > 0:
  367.             print >>stderr, 'data:', (code, msg)
  368.         
  369.         return (code, msg)
  370.  
  371.     
  372.     def verify(self, address):
  373.         self.putcmd('vrfy', quoteaddr(address))
  374.         return self.getreply()
  375.  
  376.     vrfy = verify
  377.     
  378.     def expn(self, address):
  379.         self.putcmd('expn', quoteaddr(address))
  380.         return self.getreply()
  381.  
  382.     
  383.     def ehlo_or_helo_if_needed(self):
  384.         if self.helo_resp is None and self.ehlo_resp is None:
  385.             if self.ehlo()[0] <= self.ehlo()[0]:
  386.                 pass
  387.             elif not self.ehlo()[0] <= 299:
  388.                 (code, resp) = self.helo()
  389.                 if code <= code:
  390.                     pass
  391.                 elif not code <= 299:
  392.                     raise SMTPHeloError(code, resp)
  393.                 
  394.             
  395.         
  396.  
  397.     
  398.     def login(self, user, password):
  399.         
  400.         def encode_cram_md5(challenge, user, password):
  401.             challenge = base64.decodestring(challenge)
  402.             response = user + ' ' + hmac.HMAC(password, challenge).hexdigest()
  403.             return encode_base64(response, eol = '')
  404.  
  405.         
  406.         def encode_plain(user, password):
  407.             return encode_base64('\x00%s\x00%s' % (user, password), eol = '')
  408.  
  409.         AUTH_PLAIN = 'PLAIN'
  410.         AUTH_CRAM_MD5 = 'CRAM-MD5'
  411.         AUTH_LOGIN = 'LOGIN'
  412.         self.ehlo_or_helo_if_needed()
  413.         if not self.has_extn('auth'):
  414.             raise SMTPException('SMTP AUTH extension not supported by server.')
  415.         self.has_extn('auth')
  416.         authlist = self.esmtp_features['auth'].split()
  417.         preferred_auths = [
  418.             AUTH_CRAM_MD5,
  419.             AUTH_PLAIN,
  420.             AUTH_LOGIN]
  421.         authmethod = None
  422.         for method in preferred_auths:
  423.             if method in authlist:
  424.                 authmethod = method
  425.                 break
  426.                 continue
  427.         
  428.         if authmethod == AUTH_CRAM_MD5:
  429.             (code, resp) = self.docmd('AUTH', AUTH_CRAM_MD5)
  430.             if code == 503:
  431.                 return (code, resp)
  432.             (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
  433.         elif authmethod == AUTH_PLAIN:
  434.             (code, resp) = self.docmd('AUTH', AUTH_PLAIN + ' ' + encode_plain(user, password))
  435.         elif authmethod == AUTH_LOGIN:
  436.             (code, resp) = self.docmd('AUTH', '%s %s' % (AUTH_LOGIN, encode_base64(user, eol = '')))
  437.             if code != 334:
  438.                 raise SMTPAuthenticationError(code, resp)
  439.             code != 334
  440.             (code, resp) = self.docmd(encode_base64(password, eol = ''))
  441.         elif authmethod is None:
  442.             raise SMTPException('No suitable authentication method found.')
  443.         
  444.         if code not in (235, 503):
  445.             raise SMTPAuthenticationError(code, resp)
  446.         code not in (235, 503)
  447.         return (code, resp)
  448.  
  449.     
  450.     def starttls(self, keyfile = None, certfile = None):
  451.         self.ehlo_or_helo_if_needed()
  452.         if not self.has_extn('starttls'):
  453.             raise SMTPException('STARTTLS extension not supported by server.')
  454.         self.has_extn('starttls')
  455.         (resp, reply) = self.docmd('STARTTLS')
  456.         if resp == 220:
  457.             if not _have_ssl:
  458.                 raise RuntimeError('No SSL support included in this Python')
  459.             _have_ssl
  460.             self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
  461.             self.file = SSLFakeFile(self.sock)
  462.             self.helo_resp = None
  463.             self.ehlo_resp = None
  464.             self.esmtp_features = { }
  465.             self.does_esmtp = 0
  466.         
  467.         return (resp, reply)
  468.  
  469.     
  470.     def sendmail(self, from_addr, to_addrs, msg, mail_options = [], rcpt_options = []):
  471.         self.ehlo_or_helo_if_needed()
  472.         esmtp_opts = []
  473.         if self.does_esmtp:
  474.             if self.has_extn('size'):
  475.                 esmtp_opts.append('size=%d' % len(msg))
  476.             
  477.             for option in mail_options:
  478.                 esmtp_opts.append(option)
  479.             
  480.         
  481.         (code, resp) = self.mail(from_addr, esmtp_opts)
  482.         if code != 250:
  483.             self.rset()
  484.             raise SMTPSenderRefused(code, resp, from_addr)
  485.         code != 250
  486.         senderrs = { }
  487.         if isinstance(to_addrs, basestring):
  488.             to_addrs = [
  489.                 to_addrs]
  490.         
  491.         for each in to_addrs:
  492.             (code, resp) = self.rcpt(each, rcpt_options)
  493.             if code != 250 and code != 251:
  494.                 senderrs[each] = (code, resp)
  495.                 continue
  496.         
  497.         if len(senderrs) == len(to_addrs):
  498.             self.rset()
  499.             raise SMTPRecipientsRefused(senderrs)
  500.         len(senderrs) == len(to_addrs)
  501.         (code, resp) = self.data(msg)
  502.         if code != 250:
  503.             self.rset()
  504.             raise SMTPDataError(code, resp)
  505.         code != 250
  506.         return senderrs
  507.  
  508.     
  509.     def close(self):
  510.         if self.file:
  511.             self.file.close()
  512.         
  513.         self.file = None
  514.         if self.sock:
  515.             self.sock.close()
  516.         
  517.         self.sock = None
  518.  
  519.     
  520.     def quit(self):
  521.         res = self.docmd('quit')
  522.         self.close()
  523.         return res
  524.  
  525.  
  526. if _have_ssl:
  527.     
  528.     class SMTP_SSL(SMTP):
  529.         
  530.         def __init__(self, host = '', port = 0, local_hostname = None, keyfile = None, certfile = None, timeout = socket._GLOBAL_DEFAULT_TIMEOUT):
  531.             self.keyfile = keyfile
  532.             self.certfile = certfile
  533.             SMTP.__init__(self, host, port, local_hostname, timeout)
  534.             self.default_port = SMTP_SSL_PORT
  535.  
  536.         
  537.         def _get_socket(self, host, port, timeout):
  538.             if self.debuglevel > 0:
  539.                 print >>stderr, 'connect:', (host, port)
  540.             
  541.             self.sock = socket.create_connection((host, port), timeout)
  542.             self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
  543.             self.file = SSLFakeFile(self.sock)
  544.  
  545.  
  546.     __all__.append('SMTP_SSL')
  547.  
  548. LMTP_PORT = 2003
  549.  
  550. class LMTP(SMTP):
  551.     ehlo_msg = 'lhlo'
  552.     
  553.     def __init__(self, host = '', port = LMTP_PORT, local_hostname = None):
  554.         SMTP.__init__(self, host, port, local_hostname)
  555.  
  556.     
  557.     def connect(self, host = 'localhost', port = 0):
  558.         if host[0] != '/':
  559.             return SMTP.connect(self, host, port)
  560.         
  561.         try:
  562.             self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
  563.             self.sock.connect(host)
  564.         except socket.error:
  565.             host[0] != '/'
  566.             msg = host[0] != '/'
  567.             if self.debuglevel > 0:
  568.                 print >>stderr, 'connect fail:', host
  569.             
  570.             if self.sock:
  571.                 self.sock.close()
  572.             
  573.             self.sock = None
  574.             raise socket.error, msg
  575.         except:
  576.             host[0] != '/'
  577.  
  578.         (code, msg) = self.getreply()
  579.         return (code, msg)
  580.  
  581.  
  582. if __name__ == '__main__':
  583.     import sys
  584.     
  585.     def prompt(prompt):
  586.         sys.stdout.write(prompt + ': ')
  587.         return sys.stdin.readline().strip()
  588.  
  589.     fromaddr = prompt('From')
  590.     toaddrs = prompt('To').split(',')
  591.     print 'Enter message, end with ^D:'
  592.     msg = ''
  593.     while None:
  594.         line = sys.stdin.readline()
  595.         if not line:
  596.             break
  597.         
  598.         msg = msg + line
  599.         continue
  600.         print 'Message length is %d' % len(msg)
  601.         server = SMTP('localhost')
  602.         server.sendmail(fromaddr, toaddrs, msg)
  603.         server.quit()
  604. __name__ == '__main__'
  605.