<s> """<STR_LIT>""" <EOL> import os <EOL> import tempfile <EOL> from twisted . mail import smtp <EOL> from twisted . internet import reactor <EOL> from twisted . internet import protocol <EOL> from twisted . internet import defer <EOL> from twisted . python import failure <EOL> from twisted . python import log <EOL> from zope . interface import implements , Interface <EOL> def handle ( result , line , filename , lineNo ) : <EOL> """<STR_LIT>""" <EOL> parts = [ p . strip ( ) for p in line . split ( '<STR_LIT::>' , <NUM_LIT:1> ) ] <EOL> if len ( parts ) != <NUM_LIT:2> : <EOL> fmt = "<STR_LIT>" <EOL> arg = ( lineNo , filename ) <EOL> log . err ( fmt % arg ) <EOL> else : <EOL> user , alias = parts <EOL> result . setdefault ( user . strip ( ) , [ ] ) . extend ( map ( str . strip , alias . split ( '<STR_LIT:U+002C>' ) ) ) <EOL> def loadAliasFile ( domains , filename = None , fp = None ) : <EOL> """<STR_LIT>""" <EOL> result = { } <EOL> if fp is None : <EOL> fp = file ( filename ) <EOL> else : <EOL> filename = getattr ( fp , '<STR_LIT:name>' , '<STR_LIT>' ) <EOL> i = <NUM_LIT:0> <EOL> prev = '<STR_LIT>' <EOL> for line in fp : <EOL> i += <NUM_LIT:1> <EOL> line = line . rstrip ( ) <EOL> if line . lstrip ( ) . startswith ( '<STR_LIT:#>' ) : <EOL> continue <EOL> elif line . startswith ( '<STR_LIT:U+0020>' ) or line . startswith ( '<STR_LIT:\t>' ) : <EOL> prev = prev + line <EOL> else : <EOL> if prev : <EOL> handle ( result , prev , filename , i ) <EOL> prev = line <EOL> if prev : <EOL> handle ( result , prev , filename , i ) <EOL> for ( u , a ) in result . items ( ) : <EOL> result [ u ] = AliasGroup ( a , domains , u ) <EOL> return result <EOL> class IAlias ( Interface ) : <EOL> """<STR_LIT>""" <EOL> def createMessageReceiver ( ) : <EOL> """<STR_LIT>""" <EOL> class AliasBase : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , domains , original ) : <EOL> """<STR_LIT>""" <EOL> self . domains = domains <EOL> self . original = smtp . Address ( original ) <EOL> def domain ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . domains [ self . original . domain ] <EOL> def resolve ( self , aliasmap , memo = None ) : <EOL> """<STR_LIT>""" <EOL> if memo is None : <EOL> memo = { } <EOL> if str ( self ) in memo : <EOL> return None <EOL> memo [ str ( self ) ] = None <EOL> return self . createMessageReceiver ( ) <EOL> class AddressAlias ( AliasBase ) : <EOL> """<STR_LIT>""" <EOL> implements ( IAlias ) <EOL> def __init__ ( self , alias , * args ) : <EOL> """<STR_LIT>""" <EOL> AliasBase . __init__ ( self , * args ) <EOL> self . alias = smtp . Address ( alias ) <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( self . alias , ) <EOL> def createMessageReceiver ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . domain ( ) . exists ( str ( self . alias ) ) <EOL> def resolve ( self , aliasmap , memo = None ) : <EOL> """<STR_LIT>""" <EOL> if memo is None : <EOL> memo = { } <EOL> if str ( self ) in memo : <EOL> return None <EOL> memo [ str ( self ) ] = None <EOL> try : <EOL> return self . domain ( ) . exists ( smtp . User ( self . alias , None , None , None ) , memo ) ( ) <EOL> except smtp . SMTPBadRcpt : <EOL> pass <EOL> if self . alias . local in aliasmap : <EOL> return aliasmap [ self . alias . local ] . resolve ( aliasmap , memo ) <EOL> return None <EOL> class FileWrapper : <EOL> """<STR_LIT>""" <EOL> implements ( smtp . IMessage ) <EOL> def __init__ ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> self . fp = tempfile . TemporaryFile ( ) <EOL> self . finalname = filename <EOL> def lineReceived ( self , line ) : <EOL> """<STR_LIT>""" <EOL> self . fp . write ( line + '<STR_LIT:\n>' ) <EOL> def eomReceived ( self ) : <EOL> """<STR_LIT>""" <EOL> self . fp . seek ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> try : <EOL> f = file ( self . finalname , '<STR_LIT:a>' ) <EOL> except : <EOL> return defer . fail ( failure . Failure ( ) ) <EOL> f . write ( self . fp . read ( ) ) <EOL> self . fp . close ( ) <EOL> f . close ( ) <EOL> return defer . succeed ( self . finalname ) <EOL> def connectionLost ( self ) : <EOL> """<STR_LIT>""" <EOL> self . fp . close ( ) <EOL> self . fp = None <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( self . finalname , ) <EOL> class FileAlias ( AliasBase ) : <EOL> """<STR_LIT>""" <EOL> implements ( IAlias ) <EOL> def __init__ ( self , filename , * args ) : <EOL> """<STR_LIT>""" <EOL> AliasBase . __init__ ( self , * args ) <EOL> self . filename = filename <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( self . filename , ) <EOL> def createMessageReceiver ( self ) : <EOL> """<STR_LIT>""" <EOL> return FileWrapper ( self . filename ) <EOL> class ProcessAliasTimeout ( Exception ) : <EOL> """<STR_LIT>""" <EOL> class MessageWrapper : <EOL> """<STR_LIT>""" <EOL> implements ( smtp . IMessage ) <EOL> done = False <EOL> completionTimeout = <NUM_LIT> <EOL> _timeoutCallID = None <EOL> reactor = reactor <EOL> def __init__ ( self , protocol , process = None , reactor = None ) : <EOL> """<STR_LIT>""" <EOL> self . processName = process <EOL> self . protocol = protocol <EOL> self . completion = defer . Deferred ( ) <EOL> self . protocol . onEnd = self . completion <EOL> self . completion . addBoth ( self . _processEnded ) <EOL> if reactor is not None : <EOL> self . reactor = reactor <EOL> def _processEnded ( self , result ) : <EOL> """<STR_LIT>""" <EOL> self . done = True <EOL> if self . _timeoutCallID is not None : <EOL> self . _timeoutCallID . cancel ( ) <EOL> self . _timeoutCallID = None <EOL> else : <EOL> return result <EOL> def lineReceived ( self , line ) : <EOL> """<STR_LIT>""" <EOL> if self . done : <EOL> return <EOL> self . protocol . transport . write ( line + '<STR_LIT:\n>' ) <EOL> def eomReceived ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . done : <EOL> self . protocol . transport . loseConnection ( ) <EOL> self . _timeoutCallID = self . reactor . callLater ( <EOL> self . completionTimeout , self . _completionCancel ) <EOL> return self . completion <EOL> def _completionCancel ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _timeoutCallID = None <EOL> self . protocol . transport . signalProcess ( '<STR_LIT>' ) <EOL> exc = ProcessAliasTimeout ( <EOL> "<STR_LIT>" % ( self . completionTimeout , ) ) <EOL> self . protocol . onEnd = None <EOL> self . completion . errback ( failure . Failure ( exc ) ) <EOL> def connectionLost ( self ) : <EOL> """<STR_LIT>""" <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( self . processName , ) <EOL> class ProcessAliasProtocol ( protocol . ProcessProtocol ) : <EOL> """<STR_LIT>""" <EOL> onEnd = None <EOL> def processEnded ( self , reason ) : <EOL> """<STR_LIT>""" <EOL> if self . onEnd is not None : <EOL> self . onEnd . errback ( reason ) <EOL> class ProcessAlias ( AliasBase ) : <EOL> """<STR_LIT>""" <EOL> implements ( IAlias ) <EOL> reactor = reactor <EOL> def __init__ ( self , path , * args ) : <EOL> """<STR_LIT>""" <EOL> AliasBase . __init__ ( self , * args ) <EOL> self . path = path . split ( ) <EOL> self . program = self . path [ <NUM_LIT:0> ] <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( self . path , ) <EOL> def spawnProcess ( self , proto , program , path ) : <EOL> """<STR_LIT>""" <EOL> return self . reactor . spawnProcess ( proto , program , path ) <EOL> def createMessageReceiver ( self ) : <EOL> """<STR_LIT>""" <EOL> p = ProcessAliasProtocol ( ) <EOL> m = MessageWrapper ( p , self . program , self . reactor ) <EOL> self . spawnProcess ( p , self . program , self . path ) <EOL> return m <EOL> class MultiWrapper : <EOL> """<STR_LIT>""" <EOL> implements ( smtp . IMessage ) <EOL> def __init__ ( self , objs ) : <EOL> """<STR_LIT>""" <EOL> self . objs = objs <EOL> def lineReceived ( self , line ) : <EOL> """<STR_LIT>""" <EOL> for o in self . objs : <EOL> o . lineReceived ( line ) <EOL> def eomReceived ( self ) : <EOL> """<STR_LIT>""" <EOL> return defer . DeferredList ( [ <EOL> o . eomReceived ( ) for o in self . objs <EOL> ] ) <EOL> def connectionLost ( self ) : <EOL> """<STR_LIT>""" <EOL> for o in self . objs : <EOL> o . connectionLost ( ) <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( map ( str , self . objs ) , ) <EOL> class AliasGroup ( AliasBase ) : <EOL> """<STR_LIT>""" <EOL> implements ( IAlias ) <EOL> processAliasFactory = ProcessAlias <EOL> def __init__ ( self , items , * args ) : <EOL> """<STR_LIT>""" <EOL> AliasBase . __init__ ( self , * args ) <EOL> self . aliases = [ ] <EOL> while items : <EOL> addr = items . pop ( ) . strip ( ) <EOL> if addr . startswith ( '<STR_LIT::>' ) : <EOL> try : <EOL> f = file ( addr [ <NUM_LIT:1> : ] ) <EOL> except : <EOL> log . err ( "<STR_LIT>" % ( addr [ <NUM_LIT:1> : ] , ) ) <EOL> else : <EOL> addr = '<STR_LIT:U+0020>' . join ( [ l . strip ( ) for l in f ] ) <EOL> items . extend ( addr . split ( '<STR_LIT:U+002C>' ) ) <EOL> elif addr . startswith ( '<STR_LIT:|>' ) : <EOL> self . aliases . append ( self . processAliasFactory ( addr [ <NUM_LIT:1> : ] , * args ) ) <EOL> elif addr . startswith ( '<STR_LIT:/>' ) : <EOL> if os . path . isdir ( addr ) : <EOL> log . err ( "<STR_LIT>" ) <EOL> else : <EOL> self . aliases . append ( FileAlias ( addr , * args ) ) <EOL> else : <EOL> self . aliases . append ( AddressAlias ( addr , * args ) ) <EOL> def __len__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return len ( self . aliases ) <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' % ( '<STR_LIT:U+002CU+0020>' . join ( map ( str , self . aliases ) ) ) <EOL> def createMessageReceiver ( self ) : <EOL> """<STR_LIT>""" <EOL> return MultiWrapper ( [ a . createMessageReceiver ( ) for a in self . aliases ] ) <EOL> def resolve ( self , aliasmap , memo = None ) : <EOL> """<STR_LIT>""" <EOL> if memo is None : <EOL> memo = { } <EOL> r = [ ] <EOL> for a in self . aliases : <EOL> r . append ( a . resolve ( aliasmap , memo ) ) <EOL> return MultiWrapper ( filter ( None , r ) ) </s>
