Ϫf],dZddlZddlZddlmZddlmZmZmZddl m Z ddl m Z ddl mZmZdZdd ZGd d Zee Gd d eZee j(GddZee GddeZGddeZee j(GddZGddej4Zee GddeZee j(GddZee GddeZy)zD Support for aliases(5) configuration files. @author: Jp Calderone N) implementer)deferprotocolreactor)smtp)IAlias)failurelogcx|jddDcgc]}|j}}t|dk7rd}||f}tj||zy|\}} |j |jgj ttj| jdycc}w)a Parse a line from an aliases file. @type result: L{dict} mapping L{bytes} to L{list} of L{bytes} @param result: A dictionary mapping username to aliases to which the results of parsing the line are added. @type line: L{bytes} @param line: A line from an aliases file. @type filename: L{bytes} @param filename: The full or relative path to the aliases file. @type lineNo: L{int} @param lineNo: The position of the line within the aliases file. :z+Invalid format on line %d of alias file %s.,N) splitstriplenr err setdefaultextendmapstr) resultlinefilenamelineNoppartsfmtarguseraliass 4/usr/lib/python3/dist-packages/twisted/mail/alias.pyhandler#s"!% 3 2 31QWWY 3E 3 5zQ;x  c  e$**,+223syy%++cBR3ST 4sB7ci}d}|t|}d}n t|dd}d}d} |D]q}|dz }|j}|jj dr8|j d s|j d r||z}`|rt |||||}s |r|j  |rt |||||jD]\}} t| ||||<|S#|r|j wwxYw) a Load a file containing email aliases. Lines in the file should be formatted like so:: username: alias1, alias2, ..., aliasN Aliases beginning with a C{|} will be treated as programs, will be run, and the message will be written to their stdin. Aliases beginning with a C{:} will be treated as a file containing additional aliases for the username. Aliases beginning with a C{/} will be treated as the full pathname to a file to which the message will be appended. Aliases without a host part will be assumed to be addresses on localhost. If a username is specified multiple times, the aliases for each are joined together as if they had all been on one line. Lines beginning with a space or a tab are continuations of the previous line. Lines beginning with a C{#} are comments. @type domains: L{dict} mapping L{bytes} to L{IDomain} provider @param domains: A mapping of domain name to domain object. @type filename: L{bytes} or L{None} @param filename: The full or relative path to a file from which to load aliases. If omitted, the C{fp} parameter must be specified. @type fp: file-like object or L{None} @param fp: The file from which to load aliases. If specified, the C{filename} parameter is ignored. @rtype: L{dict} mapping L{bytes} to L{AliasGroup} @return: A mapping from username to group of aliases. FTnamez rr #  ) opengetattrrstriplstrip startswithr#closeitems AliasGroup) domainsrfprr/iprevruas r" loadAliasFiler83sRF E z (^2v{3 A D D FA;;=D{{}'',%)>d{6415   HHJ vtXq) .1q'1-q . M  HHJ s A6C++Dc$eZdZdZdZdZddZy) AliasBasez The default base class for aliases. @ivar domains: See L{__init__}. @type original: L{Address} @ivar original: The original address being aliased. cF||_tj||_y)z @type domains: L{dict} mapping L{bytes} to L{IDomain} provider @param domains: A mapping of domain name to domain object. @type original: L{bytes} @param original: The original address being aliased. N)r2rAddressoriginal)selfr2r=s r"__init__zAliasBase.__init__s  X. cH|j|jjS)z Return the domain associated with original address. @rtype: L{IDomain} provider @return: The domain for the original address. )r2r=domainr>s r"rBzAliasBase.domains||DMM0011r@Ncb|i}t||vryd|t|<|jSaY Map this alias to its ultimate destination. @type aliasmap: L{dict} mapping L{bytes} to L{AliasBase} @param aliasmap: A mapping of username to alias or group of aliases. @type memo: L{None} or L{dict} of L{AliasBase} @param memo: A record of the aliases already considered in the resolution process. If provided, C{memo} is modified to include this alias. @rtype: L{IMessage } or L{None} @return: A message receiver for the ultimate destination or None for an invalid destination. N)rcreateMessageReceiverr>aliasmapmemos r"resolvezAliasBase.resolves9 <D t9 SY))++r@N)__name__ __module__ __qualname____doc__r?rBrJr@r"r:r:{s /2,r@r:c0eZdZdZdZdefdZdZddZy) AddressAliasz An alias which translates one email address into another. @type alias : L{Address} @ivar alias: The destination address. cdtj|g|tj||_y)aQ @type alias: L{Address}, L{User}, L{bytes} or object which can be converted into L{bytes} @param alias: The destination address. @type args: 2-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain} provider, (1) L{bytes} @param args: Arguments for L{AliasBase.__init__}. N)r:r?rr<r!)r>r!argss r"r?zAddressAlias.__init__s' 4'$'\\%( r@returnc"d|jdS)z Build a string representation of this L{AddressAlias} instance. @rtype: L{bytes} @return: A string containing the destination address. z
)r!rCs r"__str__zAddressAlias.__str__s4::,a((r@cf|jjt|jS)z Create a message receiver which delivers a message to the destination address. @rtype: L{IMessage } provider @return: A message receiver. )rBexistsrr!rCs r"rFz"AddressAlias.createMessageReceivers#{{}##C O44r@Nc |i}t||vryd|t|< |jjtj|j ddd|S#tj $rYnwxYw|j j|vr)||j jj||SyrE) rrBrZrUserr! SMTPBadRcptlocalrJrGs r"rJzAddressAlias.resolves <D t9 SY V4;;='' $**dD$(OQUVX X    ::  x 'DJJ,,-55hE EsAA''A=<A=rK) rLrMrNrOr?rrXrFrJrPr@r"rRrRs" )))5r@rRc4eZdZdZdZdZdZdZdefdZ y) FileWrappera A message receiver which delivers a message to a file. @type fp: file-like object @ivar fp: A file used for temporary storage of the message. @type finalname: L{bytes} @ivar finalname: The name of the file in which the message should be stored. cDtj|_||_y)z @type filename: L{bytes} @param filename: The name of the file in which the message should be stored. N)tempfile TemporaryFiler3 finalname)r>rs r"r?zFileWrapper.__init__s ((*!r@c@|jj|dzy)z Write a received line to the temporary file. @type line: L{bytes} @param line: A received line of the message.  N)r3writer>rs r" lineReceivedzFileWrapper.lineReceiveds  dTk"r@c|jjdd t|jd}|5|j|jj|jjdddt j|jS#t$r*t j tjcYSwxYw#1swY^xYw)ac Handle end of message by writing the message to the file. @rtype: L{Deferred } which successfully results in L{bytes} @return: A deferred which succeeds with the name of the file to which the message has been stored or fails if the message cannot be saved to the file. rr7N) r3seekr*rd BaseExceptionrfailr Failurergreadr/succeed)r>fs r" eomReceivedzFileWrapper.eomReceiveds  Q 1T^^S)A  GGDGGLLN # GGMMO }}T^^,, 1::goo/0 0 1  sB!AC!0CCC cF|jjd|_y)zG Close the temporary file when the connection is lost. N)r3r/rCs r"connectionLostzFileWrapper.connectionLost-s  r@rUc"d|jdS)z Build a string representation of this L{FileWrapper} instance. @rtype: L{bytes} @return: A string containing the file name of the message. z tj|g|||_y)a" @type filename: L{bytes} @param filename: The name of the file in which to store the message. @type args: 2-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain} provider, (1) L{bytes} @param args: Arguments for L{AliasBase.__init__}. N)r:r?r)r>rrTs r"r?zFileAlias.__init__Fs 4'$'  r@rUc"d|jdS)z Build a string representation of this L{FileAlias} instance. @rtype: L{bytes} @return: A string containing the name of the file. zs !))*r@rxceZdZdZy)ProcessAliasTimeoutzb An error indicating that a timeout occurred while waiting for a process to complete. N)rLrMrNrOrPr@r"r}r}esr@r}cReZdZdZdZdZdZeZd dZdZ dZ dZ d Z d Z d efd Zy)MessageWrapperaF A message receiver which delivers a message to a child process. @type completionTimeout: L{int} or L{float} @ivar completionTimeout: The number of seconds to wait for the child process to exit before reporting the delivery as a failure. @type _timeoutCallID: L{None} or L{IDelayedCall } provider @ivar _timeoutCallID: The call used to time out delivery, started when the connection to the child process is closed. @type done: L{bool} @ivar done: A flag indicating whether the child process has exited (C{True}) or not (C{False}). @type reactor: L{IReactorTime } provider @ivar reactor: A reactor which will be used to schedule timeouts. @ivar protocol: See L{__init__}. @type processName: L{bytes} or L{None} @ivar processName: The process name. @type completion: L{Deferred } @ivar completion: The deferred which will be triggered by the protocol when the child process exits. F<Nc||_||_tj|_|j|j_|jj |j|||_yy)a @type protocol: L{ProcessAliasProtocol} @param protocol: The protocol associated with the child process. @type process: L{bytes} or L{None} @param process: The process name. @type reactor: L{None} or L{IReactorTime } provider @param reactor: A reactor which will be used to schedule timeouts. N) processNamerrDeferred completiononEndaddBoth _processEndedr)r>rprocessrs r"r?zMessageWrapper.__init__s[#  ..*"oo   2 23  "DL r@cpd|_|j"|jjd|_y|S)a Record process termination and cancel the timeout call if it is active. @type result: L{Failure } @param result: The reason the child process terminated. @rtype: L{None} or L{Failure } @return: None, if the process end is expected, or the reason the child process terminated, if the process end is unexpected. TN)done_timeoutCallIDcancel)r>rs r"rzMessageWrapper._processEndeds:    *    & & ("&D Mr@cn|jry|jjj|dzy)z Write a received line to the child process. @type line: L{bytes} @param line: A received line of the message. Nrf)rr transportrgrhs r"rizMessageWrapper.lineReceiveds* 99  %%dTk2r@c|jsY|jjj|jj |j |j|_|jS)z Disconnect from the child process and set up a timeout to wait for it to exit. @rtype: L{Deferred } @return: A deferred which will be called back when the child process exits. ) rrrloseConnectionr callLatercompletionTimeout_completionCancelrrrCs r"rrzMessageWrapper.eomReceivedsUyy MM # # 2 2 4"&,,"8"8&&(>(>#D r@c d|_|jjjdt d|j d}d|j_|jjtj|y)z Handle the expiration of the timeout for the child process to exit by terminating the child process forcefully and issuing a failure to the L{completion} deferred. NKILLzNo answer after z seconds) rrr signalProcessr}rrrerrbackr rn)r>excs r"rz MessageWrapper._completionCancelsf # --f5!$4T5K5K4LH"UV"   45r@cy)z9 Ignore notification of lost connection. NrPrCs r"rtzMessageWrapper.connectionLostsr@rUc"d|jdS)z Build a string representation of this L{MessageWrapper} instance. @rtype: L{bytes} @return: A string containing the name of the process. z} @ivar onEnd: If set, a deferred on which to errback when the process ends. NcT|j|jj|yy)z Call an errback. @type reason: L{Failure } @param reason: The reason the child process terminated. N)rr)r>reasons r" processEndedz!ProcessAliasProtocol.processEndeds% :: ! JJ  v & "r@)rLrMrNrOrrrPr@r"rrs E'r@rc2eZdZdZeZdZdefdZdZdZ y) ProcessAliasa6 An alias which is handled by the execution of a program. @type path: L{list} of L{bytes} @ivar path: The arguments to pass to the process. The first string is the executable's name. @type program: L{bytes} @ivar program: The path of the program to be executed. @type reactor: L{IReactorTime } and L{IReactorProcess } provider @ivar reactor: A reactor which will be used to create and timeout the child process. ctj|g||j|_|jd|_y)aX @type path: L{bytes} @param path: The command to invoke the program consisting of the path to the executable followed by any arguments. @type args: 2-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain} provider, (1) L{bytes} @param args: Arguments for L{AliasBase.__init__}. rN)r:r?rpathprogram)r>rrTs r"r?zProcessAlias.__init__s3 4'$'JJL yy| r@rUc"d|jdS)z Build a string representation of this L{ProcessAlias} instance. @rtype: L{bytes} @return: A string containing the command used to invoke the process. z } method on L{reactor} so that it can be customized for test purposes. @type proto: L{IProcessProtocol } provider @param proto: An object which will be notified of all events related to the created process. @type program: L{bytes} @param program: The full path name of the file to execute. @type path: L{list} of L{bytes} @param path: The arguments to pass to the process. The first string should be the executable's name. @rtype: L{IProcessTransport } provider @return: A process transport. )r spawnProcess)r>protorrs r"rzProcessAlias.spawnProcess7s0||((>>r@ct}t||j|j}|j ||j|j |S)z Launch a process and create a message receiver to pass a message to the process. @rtype: L{MessageWrapper} @return: A message receiver which delivers a message to the process. )rrrrrr)r>rms r"rFz"ProcessAlias.createMessageReceiverQsA ! " 1dllDLL 9 !T\\4995r@N) rLrMrNrOrr?rrXrrFrPr@r"rr s)"G $((?4 r@rc4eZdZdZdZdZdZdZdefdZ y) MultiWrapperz A message receiver which delivers a single message to multiple other message receivers. @ivar objs: See L{__init__}. c||_y)z @type objs: L{list} of L{IMessage } provider @param objs: Message receivers to which the incoming message should be directed. N)objs)r>rs r"r?zMultiWrapper.__init__hs  r@cH|jD]}|j|y)z Pass a received line to the message receivers. @type line: L{bytes} @param line: A line of the message. N)rri)r>ros r"rizMultiWrapper.lineReceivedps# !A NN4  !r@ctj|jDcgc]}|jc}Scc}w)aG Pass the end of message along to the message receivers. @rtype: L{DeferredList } whose successful results are L{bytes} or L{None} @return: A deferred list which triggers when all of the message receivers have finished handling their end of message. )r DeferredListrrrr>rs r"rrzMultiWrapper.eomReceivedzs-!!DII"Fq1==?"FGG"Fs<cF|jD]}|jy)zQ Inform the message receivers that the connection has been lost. N)rrtrs r"rtzMultiWrapper.connectionLosts# A    r@rUc>dtt|jdS)z Build a string representation of this L{MultiWrapper} instance. @rtype: L{bytes} @return: A string containing a list of the message receivers. zwxYw) a Create a group of aliases. Parse a list of alias strings and, for each, create an appropriate alias object. @type items: L{list} of L{bytes} @param items: Aliases. @type args: n-L{tuple} of (0) L{dict} mapping L{bytes} to L{IDomain} provider, (1) L{bytes} @param args: Arguments for L{AliasBase.__init__}. r r Nr(rzInvalid filename in alias file |/z Directory delivery not supported)r:r?aliasespoprr.r*joinrrrlr rappendprocessAliasFactoryosrisdirrxrR)r>r0rTaddrrqls r"r?zAliasGroup.__init__st 4'$' 99;$$&Ds#2T!"XA@"xxA(>q(>?@LLC1% ##$?LL'' $(>(>? ##L$=$=>')?@@%LGG=d12h\JKLs0F"!F1F FFF"$G G c,t|jS)z Return the number of aliases in the group. @rtype: L{int} @return: The number of aliases in the group. )rrrCs r"__len__zAliasGroup.__len__s4<<  r@rUcZddjtt|jzS)z Build a string representation of this L{AliasGroup} instance. @rtype: L{bytes} @return: A string containing the aliases in the group. zz, )rrrrrCs r"rXzAliasGroup.__str__s##diiC0F&GHHr@cnt|jDcgc]}|jc}Scc}w)a, Create a message receiver for each alias and return a message receiver which will pass on a message to each of those. @rtype: L{MultiWrapper} @return: A message receiver which passes a message on to message receivers for each alias in the group. )rrrF)r>r7s r"rFz AliasGroup.createMessageReceivers* M1Q446MNNMs2Nc|i}g}|jD]#}|j|j||%tt d|S)a Map each of the aliases in the group to its ultimate destination. @type aliasmap: L{dict} mapping L{bytes} to L{AliasBase} @param aliasmap: A mapping of username to alias or group of aliases. @type memo: L{None} or L{dict} of L{AliasBase} @param memo: A record of the aliases already considered in the resolution process. If provided, C{memo} is modified to include this alias. @rtype: L{MultiWrapper} @return: A message receiver which passes the message on to message receivers for the ultimate destination of each alias in the group. N)rrrJrfilter)r>rHrIrr7s r"rJzAliasGroup.resolvesN <D  0A HHQYYx. / 0F4O,,r@rK) rLrMrNrOrrr?rrrXrFrJrPr@r"r1r1s3 '$?L!II O-r@r1r)rOrrbzope.interfacertwisted.internetrrr twisted.mailrtwisted.mail.interfacesrtwisted.pythonr r r#r8r:rRIMessager`rx Exceptionr}rProcessProtocolrrrr1rPr@r"rsU  &55*'U6EP3,3,l VC9CCL T]]B1B1B1J V#* #*#*L) T]]D6D6D6N'833', VQ9QQh T]]393939l Vf-f-f-r@