U
    ¸~Hjº]  ã                   @   sJ  d Z ddlZddlZddlmZ ddlmZmZmZ ddl	m
Z
 ddlmZ ddlmZmZ dd	„ Zd d
d„ZG dd„ dƒZeeƒG dd„ deƒƒZee
jƒG dd„ dƒƒZeeƒG dd„ deƒƒZG dd„ deƒZee
jƒG dd„ dƒƒZG dd„ dejƒZeeƒG dd„ deƒƒZee
jƒG dd„ dƒƒZeeƒG dd„ deƒƒZdS )!zD
Support for aliases(5) configuration files.

@author: Jp Calderone
é    N)Úimplementer)ÚdeferÚprotocolÚreactor)Úsmtp)ÚIAlias)ÚfailureÚlogc           	      C   sn   dd„ |  dd¡D ƒ}t|ƒdkr>d}||f}t || ¡ n,|\}}|  | ¡ g ¡ ttj|  d¡ƒ¡ dS )	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.
    c                 S   s   g | ]}|  ¡ ‘qS © ©Ústrip)Ú.0Úpr
   r
   ú6/tmp/pip-unpacked-wheel-ewod1tgb/twisted/mail/alias.pyÚ
<listcomp>)   s     zhandle.<locals>.<listcomp>ú:é   é   z+Invalid format on line %d of alias file %s.ú,N)	ÚsplitÚlenr	   ÚerrÚ
setdefaultr   ÚextendÚmapÚstr)	ÚresultÚlineÚfilenameZlineNoÚpartsÚfmtÚargÚuserÚaliasr
   r
   r   Úhandle   s    r$   c           
      C   sÞ   i }d}|dkrt |ƒ}d}nt|ddƒ}d}d}zd|D ]Z}|d7 }| ¡ }| ¡  d	¡r^q8q8| d
¡sr| d¡r||| }q8|rŽt||||ƒ |}q8W 5 |r¤| ¡  X |r¸t||||ƒ | ¡ D ]\}}	t|	| |ƒ||< qÀ|S )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.
    FNTÚnamez	<unknown>r   Ú r   ú#ú ú	)	ÚopenÚgetattrÚcloseÚrstripÚlstripÚ
startswithr$   ÚitemsÚ
AliasGroup)
Údomainsr   Úfpr   r,   ÚiÚprevr   ÚuÚar
   r
   r   ÚloadAliasFile3   s4    )


r8   c                   @   s*   e Zd ZdZdd„ Zdd„ Zd	dd„ZdS )
Ú	AliasBasezª
    The default base class for aliases.

    @ivar domains: See L{__init__}.

    @type original: L{Address}
    @ivar original: The original address being aliased.
    c                 C   s   || _ t |¡| _dS )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)r2   r   ÚAddressÚoriginal)Úselfr2   r;   r
   r
   r   Ú__init__…   s    zAliasBase.__init__c                 C   s   | j | jj S )z 
        Return the domain associated with original address.

        @rtype: L{IDomain} provider
        @return: The domain for the original address.
        )r2   r;   Údomain©r<   r
   r
   r   r>   �   s    zAliasBase.domainNc                 C   s0   |dkri }t | ƒ|krdS d|t | ƒ< |  ¡ S ©aY  
        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 <smtp.IMessage>} or L{None}
        @return: A message receiver for the ultimate destination or None for
            an invalid destination.
        N)r   ÚcreateMessageReceiver©r<   ÚaliasmapÚmemor
   r
   r   Úresolve™   s    zAliasBase.resolve)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r=   r>   rE   r
   r
   r
   r   r9   {   s   		r9   c                   @   s8   e Zd ZdZdd„ Zedœdd„Zdd„ Zdd
d„Zd	S )ÚAddressAliasz‹
    An alias which translates one email address into another.

    @type alias : L{Address}
    @ivar alias: The destination address.
    c                 G   s    t j| f|žŽ  t |¡| _dS )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)r9   r=   r   r:   r#   )r<   r#   Úargsr
   r
   r   r=   º   s    
zAddressAlias.__init__©Úreturnc                 C   s   d| j › d�S )z©
        Build a string representation of this L{AddressAlias} instance.

        @rtype: L{bytes}
        @return: A string containing the destination address.
        z	<Address ú>)r#   r?   r
   r
   r   Ú__str__Ç   s    zAddressAlias.__str__c                 C   s   |   ¡  t| jƒ¡S )zÃ
        Create a message receiver which delivers a message to
        the destination address.

        @rtype: L{IMessage <smtp.IMessage>} provider
        @return: A message receiver.
        )r>   Úexistsr   r#   r?   r
   r
   r   rA   Ð   s    z"AddressAlias.createMessageReceiverNc                 C   s†   |dkri }t | ƒ|krdS d|t | ƒ< z"|  ¡  t | jddd¡|¡ƒ W S  tjk
r`   Y nX | jj|kr‚|| jj  ||¡S dS r@   )	r   r>   rP   r   ZUserr#   ZSMTPBadRcptÚlocalrE   rB   r
   r
   r   rE   Ú   s    "zAddressAlias.resolve)N)	rF   rG   rH   rI   r=   r   rO   rA   rE   r
   r
   r
   r   rJ   ±   s
   	
rJ   c                   @   s>   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zed
œdd„Z	dS )Ú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.
    c                 C   s   t  ¡ | _|| _dS )z‹
        @type filename: L{bytes}
        @param filename: The name of the file in which the message should be
            stored.
        N)ÚtempfileÚTemporaryFiler3   Ú	finalname)r<   r   r
   r
   r   r=     s    
zFileWrapper.__init__c                 C   s   | j  |d ¡ dS )z‘
        Write a received line to the temporary file.

        @type line: L{bytes}
        @param line: A received line of the message.
        Ú
N)r3   Úwrite©r<   r   r
   r
   r   ÚlineReceived  s    zFileWrapper.lineReceivedc              	   C   sx   | j  dd¡ zt| jdƒ}W n" tk
r@   t t ¡ ¡ Y S X |�  | 	| j  
¡ ¡ | j  ¡  W 5 Q R X t | j¡S )ac  
        Handle end of message by writing the message to the file.

        @rtype: L{Deferred <defer.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.
        r   r7   )r3   Úseekr*   rU   ÚBaseExceptionr   Zfailr   ÚFailurerW   Úreadr,   Zsucceed)r<   Úfr
   r
   r   ÚeomReceived  s    
zFileWrapper.eomReceivedc                 C   s   | j  ¡  d| _ dS )zG
        Close the temporary file when the connection is lost.
        N)r3   r,   r?   r
   r
   r   ÚconnectionLost-  s    
zFileWrapper.connectionLostrL   c                 C   s   d| j › d�S )z­
        Build a string representation of this L{FileWrapper} instance.

        @rtype: L{bytes}
        @return: A string containing the file name of the message.
        z<FileWrapper rN   )rU   r?   r
   r
   r   rO   4  s    zFileWrapper.__str__N©
rF   rG   rH   rI   r=   rY   r_   r`   r   rO   r
   r
   r
   r   rR   ø   s   		rR   c                   @   s.   e Zd ZdZdd„ Zedœdd„Zdd„ Zd	S )
Ú	FileAliasz_
    An alias which translates an address to a file.

    @ivar filename: See L{__init__}.
    c                 G   s   t j| f|žŽ  || _dS )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)r9   r=   r   )r<   r   rK   r
   r
   r   r=   F  s    	zFileAlias.__init__rL   c                 C   s   d| j › d�S )z£
        Build a string representation of this L{FileAlias} instance.

        @rtype: L{bytes}
        @return: A string containing the name of the file.
        z<File rN   )r   r?   r
   r
   r   rO   R  s    zFileAlias.__str__c                 C   s
   t | jƒS )z¹
        Create a message receiver which delivers a message to the file.

        @rtype: L{FileWrapper}
        @return: A message receiver which writes a message to the file.
        )rR   r   r?   r
   r
   r   rA   [  s    zFileAlias.createMessageReceiverN)rF   rG   rH   rI   r=   r   rO   rA   r
   r
   r
   r   rb   >  s   	rb   c                   @   s   e Zd ZdZdS )ÚProcessAliasTimeoutzb
    An error indicating that a timeout occurred while waiting for a process
    to complete.
    N)rF   rG   rH   rI   r
   r
   r
   r   rc   e  s   rc   c                   @   s`   e Zd ZdZdZdZdZeZddd„Zdd„ Z	d	d
„ Z
dd„ Zdd„ Zdd„ Zedœdd„ZdS )Ú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 <twisted.internet.interfaces.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 <twisted.internet.interfaces.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 <defer.Deferred>}
    @ivar completion: The deferred which will be triggered by the protocol
        when the child process exits.
    Fé<   Nc                 C   s@   || _ || _t ¡ | _| j| j_| j | j¡ |dk	r<|| _dS )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
            <twisted.internet.interfaces.IReactorTime>} provider
        @param reactor: A reactor which will be used to schedule timeouts.
        N)	ÚprocessNamer   r   ZDeferredÚ
completionÚonEndZaddBothÚ_processEndedr   )r<   r   Úprocessr   r
   r
   r   r=   “  s    

zMessageWrapper.__init__c                 C   s*   d| _ | jdk	r"| j ¡  d| _n|S dS )a—  
        Record process termination and cancel the timeout call if it is active.

        @type result: L{Failure <failure.Failure>}
        @param result: The reason the child process terminated.

        @rtype: L{None} or L{Failure <failure.Failure>}
        @return: None, if the process end is expected, or the reason the child
            process terminated, if the process end is unexpected.
        TN)ÚdoneÚ_timeoutCallIDÚcancel)r<   r   r
   r
   r   ri   ¨  s
    

zMessageWrapper._processEndedc                 C   s    | j r
dS | jj |d ¡ dS )z�
        Write a received line to the child process.

        @type line: L{bytes}
        @param line: A received line of the message.
        NrV   )rk   r   Ú	transportrW   rX   r
   r
   r   rY   ¾  s    zMessageWrapper.lineReceivedc                 C   s,   | j s&| jj ¡  | j | j| j¡| _| j	S )zö
        Disconnect from the child process and set up a timeout to wait for it
        to exit.

        @rtype: L{Deferred <defer.Deferred>}
        @return: A deferred which will be called back when the child process
            exits.
        )
rk   r   rn   ZloseConnectionr   Z	callLaterÚcompletionTimeoutÚ_completionCancelrl   rg   r?   r
   r
   r   r_   É  s    	 ÿzMessageWrapper.eomReceivedc                 C   sD   d| _ | jj d¡ td| j› d�ƒ}d| j_| j t	 
|¡¡ dS )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.
        NZKILLzNo answer after z seconds)rl   r   rn   ZsignalProcessrc   ro   rh   rg   Úerrbackr   r\   )r<   Úexcr
   r
   r   rp   Ù  s
    z MessageWrapper._completionCancelc                 C   s   dS )z9
        Ignore notification of lost connection.
        Nr
   r?   r
   r
   r   r`   å  s    zMessageWrapper.connectionLostrL   c                 C   s   d| j › d�S )z«
        Build a string representation of this L{MessageWrapper} instance.

        @rtype: L{bytes}
        @return: A string containing the name of the process.
        z<ProcessWrapper rN   )rf   r?   r
   r
   r   rO   ê  s    zMessageWrapper.__str__)NN)rF   rG   rH   rI   rk   ro   rl   r   r=   ri   rY   r_   rp   r`   r   rO   r
   r
   r
   r   rd   l  s   
rd   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚProcessAliasProtocolzå
    A process protocol which errbacks a deferred when the associated
    process ends.

    @type onEnd: L{None} or L{Deferred <defer.Deferred>}
    @ivar onEnd: If set, a deferred on which to errback when the process ends.
    Nc                 C   s   | j dk	r| j  |¡ dS )z–
        Call an errback.

        @type reason: L{Failure <failure.Failure>}
        @param reason: The reason the child process terminated.
        N)rh   rq   )r<   Úreasonr
   r
   r   ÚprocessEndedÿ  s    
z!ProcessAliasProtocol.processEnded)rF   rG   rH   rI   rh   ru   r
   r
   r
   r   rs   ô  s   rs   c                   @   s:   e Zd ZdZeZdd„ Zedœdd„Zdd„ Zd	d
„ Z	dS )Ú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 <twisted.internet.interfaces.IReactorTime>}
        and L{IReactorProcess <twisted.internet.interfaces.IReactorProcess>}
        provider
    @ivar reactor: A reactor which will be used to create and timeout the
        child process.
    c                 G   s*   t j| f|žŽ  | ¡ | _| jd | _dS )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__}.
        r   N)r9   r=   r   ÚpathÚprogram)r<   rw   rK   r
   r
   r   r=     s    
zProcessAlias.__init__rL   c                 C   s   d| j › d�S )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	<Process rN   )rw   r?   r
   r
   r   rO   .  s    zProcessAlias.__str__c                 C   s   | j  |||¡S )aP  
        Spawn a process.

        This wraps the L{spawnProcess
        <twisted.internet.interfaces.IReactorProcess.spawnProcess>} method on
        L{reactor} so that it can be customized for test purposes.

        @type proto: L{IProcessProtocol
            <twisted.internet.interfaces.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
            <twisted.internet.interfaces.IProcessTransport>} provider
        @return: A process transport.
        )r   ÚspawnProcess)r<   Úprotorx   rw   r
   r
   r   ry   7  s    zProcessAlias.spawnProcessc                 C   s,   t ƒ }t|| 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.
        )rs   rd   rx   r   ry   rw   )r<   r   Úmr
   r
   r   rA   Q  s    z"ProcessAlias.createMessageReceiverN)
rF   rG   rH   rI   r   r=   r   rO   ry   rA   r
   r
   r
   r   rv   
  s   	rv   c                   @   s>   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zed
œdd„Z	dS )ÚMultiWrapperz‡
    A message receiver which delivers a single message to multiple other
    message receivers.

    @ivar objs: See L{__init__}.
    c                 C   s
   || _ dS )z²
        @type objs: L{list} of L{IMessage <smtp.IMessage>} provider
        @param objs: Message receivers to which the incoming message should be
            directed.
        N)Úobjs)r<   r}   r
   r
   r   r=   h  s    zMultiWrapper.__init__c                 C   s   | j D ]}| |¡ qdS )zŠ
        Pass a received line to the message receivers.

        @type line: L{bytes}
        @param line: A line of the message.
        N)r}   rY   )r<   r   Úor
   r
   r   rY   p  s    
zMultiWrapper.lineReceivedc                 C   s   t  dd„ | jD ƒ¡S )aG  
        Pass the end of message along to the message receivers.

        @rtype: L{DeferredList <defer.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.
        c                 S   s   g | ]}|  ¡ ‘qS r
   )r_   )r   r~   r
   r
   r   r   ƒ  s     z,MultiWrapper.eomReceived.<locals>.<listcomp>)r   ZDeferredListr}   r?   r
   r
   r   r_   z  s    	zMultiWrapper.eomReceivedc                 C   s   | j D ]}| ¡  qdS )zQ
        Inform the message receivers that the connection has been lost.
        N)r}   r`   )r<   r~   r
   r
   r   r`   …  s    
zMultiWrapper.connectionLostrL   c                 C   s   dt t| jƒ›d�S )z±
        Build a string representation of this L{MultiWrapper} instance.

        @rtype: L{bytes}
        @return: A string containing a list of the message receivers.
        z<GroupWrapper rN   )r   r   r}   r?   r
   r
   r   rO   Œ  s    zMultiWrapper.__str__Nra   r
   r
   r
   r   r|   _  s   
r|   c                   @   sD   e Zd ZdZeZdd„ Zdd„ Zedœdd„Z	d	d
„ Z
ddd„ZdS )r1   aL  
    An alias which points to multiple destination aliases.

    @type processAliasFactory: no-argument callable which returns
        L{ProcessAlias}
    @ivar processAliasFactory: A factory for process aliases.

    @type aliases: L{list} of L{AliasBase} which implements L{IAlias}
    @ivar aliases: The destination aliases.
    c              	   G   s.  t j| f|žŽ  g | _|�r*| ¡  ¡ }| d¡rªzt|dd… ƒ}W n, tk
rr   t 	d|dd… ›�¡ Y n6X |� d 
dd„ |D ƒ¡}W 5 Q R X | | d¡¡ q| d	¡rÖ| j | j|dd… f|žŽ ¡ q| d
¡�rtj |¡rút 	d¡ n| j t|f|žŽ ¡ q| j t|f|žŽ ¡ qdS )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   NzInvalid filename in alias file r(   c                 S   s   g | ]}|  ¡ ‘qS r
   r   )r   Úlr
   r
   r   r   ¿  s     z'AliasGroup.__init__.<locals>.<listcomp>r   ú|ú/z Directory delivery not supported)r9   r=   ÚaliasesÚpopr   r/   r*   r[   r	   r   Újoinr   r   ÚappendÚprocessAliasFactoryÚosrw   Úisdirrb   rJ   )r<   r0   rK   Úaddrr^   r
   r
   r   r=   ¥  s&    

"zAliasGroup.__init__c                 C   s
   t | jƒS )z‰
        Return the number of aliases in the group.

        @rtype: L{int}
        @return: The number of aliases in the group.
        )r   r‚   r?   r
   r
   r   Ú__len__Ë  s    zAliasGroup.__len__rL   c                 C   s   dd  tt| jƒ¡ S )z¨
        Build a string representation of this L{AliasGroup} instance.

        @rtype: L{bytes}
        @return: A string containing the aliases in the group.
        z<AliasGroup [%s]>z, )r„   r   r   r‚   r?   r
   r
   r   rO   Ô  s    zAliasGroup.__str__c                 C   s   t dd„ | jD ƒƒS )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.
        c                 S   s   g | ]}|  ¡ ‘qS r
   )rA   )r   r7   r
   r
   r   r   æ  s     z4AliasGroup.createMessageReceiver.<locals>.<listcomp>)r|   r‚   r?   r
   r
   r   rA   Ý  s    	z AliasGroup.createMessageReceiverNc                 C   s<   |dkri }g }| j D ]}| | ||¡¡ qtt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)r‚   r…   rE   r|   Úfilter)r<   rC   rD   Úrr7   r
   r
   r   rE   è  s    
zAliasGroup.resolve)N)rF   rG   rH   rI   rv   r†   r=   rŠ   r   rO   rA   rE   r
   r
   r
   r   r1   –  s   &		r1   )NN)rI   r‡   rS   Zzope.interfacer   Ztwisted.internetr   r   r   Ztwisted.mailr   Ztwisted.mail.interfacesr   Ztwisted.pythonr   r	   r$   r8   r9   rJ   ZIMessagerR   rb   Ú	Exceptionrc   rd   ZProcessProtocolrs   rv   r|   r1   r
   r
   r
   r   Ú<module>   s6   
H6FE& T6