home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_2778 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  13.1 KB  |  489 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import sys
  5. import os
  6. import errno
  7. import getopt
  8. import time
  9. import socket
  10. import asyncore
  11. import asynchat
  12. __all__ = [
  13.     'SMTPServer',
  14.     'DebuggingServer',
  15.     'PureProxy',
  16.     'MailmanProxy']
  17. program = sys.argv[0]
  18. __version__ = 'Python SMTP proxy version 0.2'
  19.  
  20. class Devnull:
  21.     
  22.     def write(self, msg):
  23.         pass
  24.  
  25.     
  26.     def flush(self):
  27.         pass
  28.  
  29.  
  30. DEBUGSTREAM = Devnull()
  31. NEWLINE = '\n'
  32. EMPTYSTRING = ''
  33. COMMASPACE = ', '
  34.  
  35. def usage(code, msg = ''):
  36.     print >>sys.stderr, __doc__ % globals()
  37.     if msg:
  38.         print >>sys.stderr, msg
  39.     
  40.     sys.exit(code)
  41.  
  42.  
  43. class SMTPChannel(asynchat.async_chat):
  44.     COMMAND = 0
  45.     DATA = 1
  46.     
  47.     def __init__(self, server, conn, addr):
  48.         asynchat.async_chat.__init__(self, conn)
  49.         self._SMTPChannel__server = server
  50.         self._SMTPChannel__conn = conn
  51.         self._SMTPChannel__addr = addr
  52.         self._SMTPChannel__line = []
  53.         self._SMTPChannel__state = self.COMMAND
  54.         self._SMTPChannel__greeting = 0
  55.         self._SMTPChannel__mailfrom = None
  56.         self._SMTPChannel__rcpttos = []
  57.         self._SMTPChannel__data = ''
  58.         self._SMTPChannel__fqdn = socket.getfqdn()
  59.         self._SMTPChannel__peer = conn.getpeername()
  60.         print >>DEBUGSTREAM, 'Peer:', repr(self._SMTPChannel__peer)
  61.         self.push('220 %s %s' % (self._SMTPChannel__fqdn, __version__))
  62.         self.set_terminator('\r\n')
  63.  
  64.     
  65.     def push(self, msg):
  66.         asynchat.async_chat.push(self, msg + '\r\n')
  67.  
  68.     
  69.     def collect_incoming_data(self, data):
  70.         self._SMTPChannel__line.append(data)
  71.  
  72.     
  73.     def found_terminator(self):
  74.         line = EMPTYSTRING.join(self._SMTPChannel__line)
  75.         print >>DEBUGSTREAM, 'Data:', repr(line)
  76.         self._SMTPChannel__line = []
  77.         if self._SMTPChannel__state == self.COMMAND:
  78.             if not line:
  79.                 self.push('500 Error: bad syntax')
  80.                 return None
  81.             method = None
  82.             i = line.find(' ')
  83.             if i < 0:
  84.                 command = line.upper()
  85.                 arg = None
  86.             else:
  87.                 command = line[:i].upper()
  88.                 arg = line[i + 1:].strip()
  89.             method = getattr(self, 'smtp_' + command, None)
  90.             if not method:
  91.                 self.push('502 Error: command "%s" not implemented' % command)
  92.                 return None
  93.             method(arg)
  94.             return None
  95.         if self._SMTPChannel__state != self.DATA:
  96.             self.push('451 Internal confusion')
  97.             return None
  98.         data = []
  99.         for text in line.split('\r\n'):
  100.             if text and text[0] == '.':
  101.                 data.append(text[1:])
  102.                 continue
  103.             self._SMTPChannel__state != self.DATA
  104.             data.append(text)
  105.         
  106.         self._SMTPChannel__data = NEWLINE.join(data)
  107.         status = self._SMTPChannel__server.process_message(self._SMTPChannel__peer, self._SMTPChannel__mailfrom, self._SMTPChannel__rcpttos, self._SMTPChannel__data)
  108.         self._SMTPChannel__rcpttos = []
  109.         self._SMTPChannel__mailfrom = None
  110.         self._SMTPChannel__state = self.COMMAND
  111.         self.set_terminator('\r\n')
  112.         if not status:
  113.             self.push('250 Ok')
  114.         else:
  115.             self.push(status)
  116.  
  117.     
  118.     def smtp_HELO(self, arg):
  119.         if not arg:
  120.             self.push('501 Syntax: HELO hostname')
  121.             return None
  122.         if self._SMTPChannel__greeting:
  123.             self.push('503 Duplicate HELO/EHLO')
  124.         else:
  125.             self._SMTPChannel__greeting = arg
  126.             self.push('250 %s' % self._SMTPChannel__fqdn)
  127.  
  128.     
  129.     def smtp_NOOP(self, arg):
  130.         if arg:
  131.             self.push('501 Syntax: NOOP')
  132.         else:
  133.             self.push('250 Ok')
  134.  
  135.     
  136.     def smtp_QUIT(self, arg):
  137.         self.push('221 Bye')
  138.         self.close_when_done()
  139.  
  140.     
  141.     def __getaddr(self, keyword, arg):
  142.         address = None
  143.         keylen = len(keyword)
  144.         if arg[:keylen].upper() == keyword:
  145.             address = arg[keylen:].strip()
  146.             if not address:
  147.                 pass
  148.             elif address[0] == '<' and address[-1] == '>' and address != '<>':
  149.                 address = address[1:-1]
  150.             
  151.         
  152.         return address
  153.  
  154.     
  155.     def smtp_MAIL(self, arg):
  156.         print >>DEBUGSTREAM, '===> MAIL', arg
  157.         address = None if arg else None
  158.         if not address:
  159.             self.push('501 Syntax: MAIL FROM:<address>')
  160.             return None
  161.         if self._SMTPChannel__mailfrom:
  162.             self.push('503 Error: nested MAIL command')
  163.             return None
  164.         self._SMTPChannel__mailfrom = address
  165.         print >>DEBUGSTREAM, 'sender:', self._SMTPChannel__mailfrom
  166.         self.push('250 Ok')
  167.  
  168.     
  169.     def smtp_RCPT(self, arg):
  170.         print >>DEBUGSTREAM, '===> RCPT', arg
  171.         if not self._SMTPChannel__mailfrom:
  172.             self.push('503 Error: need MAIL command')
  173.             return None
  174.         address = self._SMTPChannel__mailfrom if arg else None
  175.         if not address:
  176.             self.push('501 Syntax: RCPT TO: <address>')
  177.             return None
  178.         self._SMTPChannel__rcpttos.append(address)
  179.         print >>DEBUGSTREAM, 'recips:', self._SMTPChannel__rcpttos
  180.         self.push('250 Ok')
  181.  
  182.     
  183.     def smtp_RSET(self, arg):
  184.         if arg:
  185.             self.push('501 Syntax: RSET')
  186.             return None
  187.         self._SMTPChannel__mailfrom = None
  188.         self._SMTPChannel__rcpttos = []
  189.         self._SMTPChannel__data = ''
  190.         self._SMTPChannel__state = self.COMMAND
  191.         self.push('250 Ok')
  192.  
  193.     
  194.     def smtp_DATA(self, arg):
  195.         if not self._SMTPChannel__rcpttos:
  196.             self.push('503 Error: need RCPT command')
  197.             return None
  198.         if arg:
  199.             self.push('501 Syntax: DATA')
  200.             return None
  201.         self._SMTPChannel__state = self.DATA
  202.         self.set_terminator('\r\n.\r\n')
  203.         self.push('354 End data with <CR><LF>.<CR><LF>')
  204.  
  205.  
  206.  
  207. class SMTPServer(asyncore.dispatcher):
  208.     
  209.     def __init__(self, localaddr, remoteaddr):
  210.         self._localaddr = localaddr
  211.         self._remoteaddr = remoteaddr
  212.         asyncore.dispatcher.__init__(self)
  213.         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  214.         self.set_reuse_addr()
  215.         self.bind(localaddr)
  216.         self.listen(5)
  217.         print >>DEBUGSTREAM, '%s started at %s\n\tLocal addr: %s\n\tRemote addr:%s' % (self.__class__.__name__, time.ctime(time.time()), localaddr, remoteaddr)
  218.  
  219.     
  220.     def handle_accept(self):
  221.         (conn, addr) = self.accept()
  222.         print >>DEBUGSTREAM, 'Incoming connection from %s' % repr(addr)
  223.         channel = SMTPChannel(self, conn, addr)
  224.  
  225.     
  226.     def process_message(self, peer, mailfrom, rcpttos, data):
  227.         raise NotImplementedError
  228.  
  229.  
  230.  
  231. class DebuggingServer(SMTPServer):
  232.     
  233.     def process_message(self, peer, mailfrom, rcpttos, data):
  234.         inheaders = 1
  235.         lines = data.split('\n')
  236.         print '---------- MESSAGE FOLLOWS ----------'
  237.         for line in lines:
  238.             if inheaders and not line:
  239.                 print 'X-Peer:', peer[0]
  240.                 inheaders = 0
  241.             
  242.             print line
  243.         
  244.         print '------------ END MESSAGE ------------'
  245.  
  246.  
  247.  
  248. class PureProxy(SMTPServer):
  249.     
  250.     def process_message(self, peer, mailfrom, rcpttos, data):
  251.         lines = data.split('\n')
  252.         i = 0
  253.         for line in lines:
  254.             if not line:
  255.                 break
  256.             
  257.             i += 1
  258.         
  259.         lines.insert(i, 'X-Peer: %s' % peer[0])
  260.         data = NEWLINE.join(lines)
  261.         refused = self._deliver(mailfrom, rcpttos, data)
  262.         print >>DEBUGSTREAM, 'we got some refusals:', refused
  263.  
  264.     
  265.     def _deliver(self, mailfrom, rcpttos, data):
  266.         import smtplib
  267.         refused = { }
  268.         
  269.         try:
  270.             s = smtplib.SMTP()
  271.             s.connect(self._remoteaddr[0], self._remoteaddr[1])
  272.             
  273.             try:
  274.                 refused = s.sendmail(mailfrom, rcpttos, data)
  275.             finally:
  276.                 s.quit()
  277.  
  278.         except smtplib.SMTPRecipientsRefused:
  279.             e = None
  280.             print >>DEBUGSTREAM, 'got SMTPRecipientsRefused'
  281.             refused = e.recipients
  282.         except (socket.error, smtplib.SMTPException):
  283.             e = None
  284.             print >>DEBUGSTREAM, 'got', e.__class__
  285.             errcode = getattr(e, 'smtp_code', -1)
  286.             errmsg = getattr(e, 'smtp_error', 'ignore')
  287.             for r in rcpttos:
  288.                 refused[r] = (errcode, errmsg)
  289.             
  290.  
  291.         return refused
  292.  
  293.  
  294.  
  295. class MailmanProxy(PureProxy):
  296.     
  297.     def process_message(self, peer, mailfrom, rcpttos, data):
  298.         StringIO = StringIO
  299.         import cStringIO
  300.         Utils = Utils
  301.         import Mailman
  302.         Message = Message
  303.         import Mailman
  304.         MailList = MailList
  305.         import Mailman
  306.         listnames = []
  307.         for rcpt in rcpttos:
  308.             local = rcpt.lower().split('@')[0]
  309.             parts = local.split('-')
  310.             if len(parts) > 2:
  311.                 continue
  312.             
  313.             listname = parts[0]
  314.             if len(parts) == 2:
  315.                 command = parts[1]
  316.             else:
  317.                 command = ''
  318.             if not Utils.list_exists(listname) or command not in ('', 'admin', 'owner', 'request', 'join', 'leave'):
  319.                 continue
  320.             
  321.             listnames.append((rcpt, listname, command))
  322.         
  323.         for rcpt, listname, command in listnames:
  324.             rcpttos.remove(rcpt)
  325.         
  326.         print >>DEBUGSTREAM, 'forwarding recips:', ' '.join(rcpttos)
  327.         if rcpttos:
  328.             refused = self._deliver(mailfrom, rcpttos, data)
  329.             print >>DEBUGSTREAM, 'we got refusals:', refused
  330.         
  331.         mlists = { }
  332.         s = StringIO(data)
  333.         msg = Message.Message(s)
  334.         if not msg.getheader('from'):
  335.             msg['From'] = mailfrom
  336.         
  337.         if not msg.getheader('date'):
  338.             msg['Date'] = time.ctime(time.time())
  339.         
  340.         for rcpt, listname, command in listnames:
  341.             print >>DEBUGSTREAM, 'sending message to', rcpt
  342.             mlist = mlists.get(listname)
  343.             if not mlist:
  344.                 mlist = MailList.MailList(listname, lock = 0)
  345.                 mlists[listname] = mlist
  346.             
  347.             if command == '':
  348.                 msg.Enqueue(mlist, tolist = 1)
  349.                 continue
  350.             if command == 'admin':
  351.                 msg.Enqueue(mlist, toadmin = 1)
  352.                 continue
  353.             if command == 'owner':
  354.                 msg.Enqueue(mlist, toowner = 1)
  355.                 continue
  356.             if command == 'request':
  357.                 msg.Enqueue(mlist, torequest = 1)
  358.                 continue
  359.             if command in ('join', 'leave'):
  360.                 if command == 'join':
  361.                     msg['Subject'] = 'subscribe'
  362.                 else:
  363.                     msg['Subject'] = 'unsubscribe'
  364.                 msg.Enqueue(mlist, torequest = 1)
  365.                 continue
  366.         
  367.  
  368.  
  369.  
  370. class Options:
  371.     setuid = 1
  372.     classname = 'PureProxy'
  373.  
  374.  
  375. def parseargs():
  376.     global DEBUGSTREAM
  377.     
  378.     try:
  379.         (opts, args) = getopt.getopt(sys.argv[1:], 'nVhc:d', [
  380.             'class=',
  381.             'nosetuid',
  382.             'version',
  383.             'help',
  384.             'debug'])
  385.     except getopt.error:
  386.         e = None
  387.         usage(1, e)
  388.  
  389.     options = Options()
  390.     for opt, arg in opts:
  391.         if opt in ('-h', '--help'):
  392.             usage(0)
  393.             continue
  394.         if opt in ('-V', '--version'):
  395.             print >>sys.stderr, __version__
  396.             sys.exit(0)
  397.             continue
  398.         if opt in ('-n', '--nosetuid'):
  399.             options.setuid = 0
  400.             continue
  401.         if opt in ('-c', '--class'):
  402.             options.classname = arg
  403.             continue
  404.         if opt in ('-d', '--debug'):
  405.             DEBUGSTREAM = sys.stderr
  406.             continue
  407.     
  408.     if len(args) < 1:
  409.         localspec = 'localhost:8025'
  410.         remotespec = 'localhost:25'
  411.     elif len(args) < 2:
  412.         localspec = args[0]
  413.         remotespec = 'localhost:25'
  414.     elif len(args) < 3:
  415.         localspec = args[0]
  416.         remotespec = args[1]
  417.     else:
  418.         usage(1, 'Invalid arguments: %s' % COMMASPACE.join(args))
  419.     i = localspec.find(':')
  420.     if i < 0:
  421.         usage(1, 'Bad local spec: %s' % localspec)
  422.     
  423.     options.localhost = localspec[:i]
  424.     
  425.     try:
  426.         options.localport = int(localspec[i + 1:])
  427.     except ValueError:
  428.         usage(1, 'Bad local port: %s' % localspec)
  429.  
  430.     i = remotespec.find(':')
  431.     if i < 0:
  432.         usage(1, 'Bad remote spec: %s' % remotespec)
  433.     
  434.     options.remotehost = remotespec[:i]
  435.     
  436.     try:
  437.         options.remoteport = int(remotespec[i + 1:])
  438.     except ValueError:
  439.         usage(1, 'Bad remote port: %s' % remotespec)
  440.  
  441.     return options
  442.  
  443. if __name__ == '__main__':
  444.     options = parseargs()
  445.     if options.setuid:
  446.         
  447.         try:
  448.             import pwd
  449.         except ImportError:
  450.             print >>sys.stderr, 'Cannot import module "pwd"; try running with -n option.'
  451.             sys.exit(1)
  452.  
  453.         nobody = pwd.getpwnam('nobody')[2]
  454.         
  455.         try:
  456.             os.setuid(nobody)
  457.         except OSError:
  458.             e = None
  459.             if e.errno != errno.EPERM:
  460.                 raise 
  461.             e.errno != errno.EPERM
  462.             print >>sys.stderr, 'Cannot setuid "nobody"; try running with -n option.'
  463.             sys.exit(1)
  464.         except:
  465.             None<EXCEPTION MATCH>OSError
  466.         
  467.  
  468.     None<EXCEPTION MATCH>OSError
  469.     classname = options.classname
  470.     if '.' in classname:
  471.         lastdot = classname.rfind('.')
  472.         mod = __import__(classname[:lastdot], globals(), locals(), [
  473.             ''])
  474.         classname = classname[lastdot + 1:]
  475.     else:
  476.         import __main__ as mod
  477.     class_ = getattr(mod, classname)
  478.     proxy = class_((options.localhost, options.localport), (options.remotehost, options.remoteport))
  479.     
  480.     try:
  481.         asyncore.loop()
  482.     except KeyboardInterrupt:
  483.         pass
  484.     except:
  485.         None<EXCEPTION MATCH>KeyboardInterrupt
  486.     
  487.  
  488. None<EXCEPTION MATCH>KeyboardInterrupt
  489.