a
    ze                     @   sN  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
 d dlmZmZ g dZe jd  ZdZG dd dZe adZd	Zd
Zd%ddZG dd dejZG dd dejZG dd deZG dd deZG dd deZG dd dZdd Z e!dkrJe  Z"e"j#Z#de#v rfe#$dZ%e&e#de% e' e( dgZ)e#e%d d Z#nd dl*Z)e+e)e#Z,e,e"j-e"j.fe"j/e"j0fe"j1e"j2dZ3e"j4r(zd dl5Z5W n, e6y   e7d e j8d! e 9d Y n0 e5:d"d# Z;ze4e; W n, e<y&   e7d$e j8d! e 9d Y n0 ze=  W n e>yH   Y n0 dS )&    N)warn)get_addr_specget_angle_addr)SMTPChannel
SMTPServerDebuggingServer	PureProxyMailmanProxyzPython SMTP proxy version 0.3c                   @   s   e Zd Zdd Zdd ZdS )Devnullc                 C   s   d S N selfmsgr   r   /usr/lib/python3.9/smtpd.pywritef       zDevnull.writec                 C   s   d S r   r   r   r   r   r   flushg   r   zDevnull.flushN)__name__
__module____qualname__r   r   r   r   r   r   r
   e   s   r
   
z, i    c                 C   s4   t tt  tjd |r&t |tjd t|  d S )Nfile)print__doc__globalssysstderrexit)coder   r   r   r   usagep   s    r#   c                   @   s  e Zd ZdZdZdZeefddZe	dd Z
edd	d	fd
dZdd Zdd Ze	dd Zejdd Ze	dd Zejdd Ze	dd Zejdd Ze	dd Zejdd Ze	dd Zejdd Ze	dd  Zejd!d  Ze	d"d# Zejd$d# Ze	d%d& Zejd'd& Ze	d(d) Zejd*d) Ze	d+d, Zejd-d, Ze	d.d/ Zejd0d/ Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Z d=d> Z!d?d@ Z"dAdB Z#dCdD Z$dEdF Z%dGdH Z&dIdJ Z'dKdL Z(dMdN Z)dOdP Z*dQdR Z+dS )Sr   r      i   c                 C   s   | S r   r   )xr   r   r   <lambda>|   r   zSMTPChannel.<lambda>c                 C   s.   zt | j W S  ty(   | j Y S 0 d S r   )maxcommand_size_limitsvalues
ValueErrorcommand_size_limitr   r   r   r   max_command_size_limit~   s    z"SMTPChannel.max_command_size_limitNFc           	   
   C   s&  t jj| ||d || _|| _|| _|| _|| _|| _|rF|rFt	d|rdd| _
d| _d| _t| _nd| _
d| _td| _d	| _|   d| _d
| _| j  t | _z| | _W nB t y } z(|   |jd tjkr W Y d }~d S d }~0 0 tdt | jt!d | "d| jt#f  d S )NmapFdecode_data and enable_SMTPUTF8 cannot be set to True at the same timer   
.r      
   .   
Fr   zPeer:r   z	220 %s %s)$asynchat
async_chat__init__smtp_serverconnaddrdata_size_limitenable_SMTPUTF8_decode_datar*   _emptystring_linesep_dotsepNEWLINE_newlineord_set_rset_stateseen_greetingextended_smtpr(   clearsocketgetfqdnfqdngetpeernamepeerOSErrorcloseargserrnoZENOTCONNr   reprDEBUGSTREAMpush__version__)	r   Zserverr9   r:   r;   r.   r<   decode_dataerrr   r   r   r7      s@    


zSMTPChannel.__init__c                 C   s.   | j | _d | _g | _d| _d| _| d d S )NFr   r2   )COMMAND
smtp_statemailfromrcpttosrequire_SMTPUTF8	num_bytesset_terminatorr   r   r   r   _set_post_data_state   s    z SMTPChannel._set_post_data_statec                 C   s   |    d| _g | _d S Nr   )r^   received_datareceived_linesr   r   r   r   rD      s    zSMTPChannel._set_rset_statec                 C   s   t dtd | jS )NzTAccess to __server attribute on SMTPChannel is deprecated, use 'smtp_server' instead   r   DeprecationWarningr8   r   r   r   r   __server   s    zSMTPChannel.__serverc                 C   s   t dtd || _d S )NzRSetting __server attribute on SMTPChannel is deprecated, set 'smtp_server' insteadrb   rc   r   valuer   r   r   re      s    c                 C   s   t dtd | jS )NzUAccess to __line attribute on SMTPChannel is deprecated, use 'received_lines' insteadrb   r   rd   ra   r   r   r   r   __line   s    zSMTPChannel.__linec                 C   s   t dtd || _d S )NzSSetting __line attribute on SMTPChannel is deprecated, set 'received_lines' insteadrb   rh   rf   r   r   r   ri      s    c                 C   s   t dtd | jS )NzRAccess to __state attribute on SMTPChannel is deprecated, use 'smtp_state' insteadrb   r   rd   rX   r   r   r   r   __state   s    zSMTPChannel.__statec                 C   s   t dtd || _d S )NzPSetting __state attribute on SMTPChannel is deprecated, set 'smtp_state' insteadrb   rj   rf   r   r   r   rk      s    c                 C   s   t dtd | jS )NzXAccess to __greeting attribute on SMTPChannel is deprecated, use 'seen_greeting' insteadrb   r   rd   rE   r   r   r   r   
__greeting   s    zSMTPChannel.__greetingc                 C   s   t dtd || _d S )NzVSetting __greeting attribute on SMTPChannel is deprecated, set 'seen_greeting' insteadrb   rl   rf   r   r   r   rm      s    c                 C   s   t dtd | jS )NzSAccess to __mailfrom attribute on SMTPChannel is deprecated, use 'mailfrom' insteadrb   r   rd   rY   r   r   r   r   
__mailfrom   s    zSMTPChannel.__mailfromc                 C   s   t dtd || _d S )NzQSetting __mailfrom attribute on SMTPChannel is deprecated, set 'mailfrom' insteadrb   rn   rf   r   r   r   ro      s    c                 C   s   t dtd | jS )NzQAccess to __rcpttos attribute on SMTPChannel is deprecated, use 'rcpttos' insteadrb   r   rd   rZ   r   r   r   r   	__rcpttos   s    zSMTPChannel.__rcpttosc                 C   s   t dtd || _d S )NzOSetting __rcpttos attribute on SMTPChannel is deprecated, set 'rcpttos' insteadrb   rp   rf   r   r   r   rq      s    c                 C   s   t dtd | jS )NzTAccess to __data attribute on SMTPChannel is deprecated, use 'received_data' insteadrb   r   rd   r`   r   r   r   r   __data   s    zSMTPChannel.__datac                 C   s   t dtd || _d S )NzRSetting __data attribute on SMTPChannel is deprecated, set 'received_data' insteadrb   rr   rf   r   r   r   rs     s    c                 C   s   t dtd | jS )NzKAccess to __fqdn attribute on SMTPChannel is deprecated, use 'fqdn' insteadrb   r   rd   rJ   r   r   r   r   __fqdn
  s    zSMTPChannel.__fqdnc                 C   s   t dtd || _d S )NzISetting __fqdn attribute on SMTPChannel is deprecated, set 'fqdn' insteadrb   rt   rf   r   r   r   ru     s    c                 C   s   t dtd | jS )NzKAccess to __peer attribute on SMTPChannel is deprecated, use 'peer' insteadrb   r   rd   rL   r   r   r   r   __peer  s    zSMTPChannel.__peerc                 C   s   t dtd || _d S )NzISetting __peer attribute on SMTPChannel is deprecated, set 'peer' insteadrb   rv   rf   r   r   r   rw     s    c                 C   s   t dtd | jS )NzKAccess to __conn attribute on SMTPChannel is deprecated, use 'conn' insteadrb   r   rd   r9   r   r   r   r   __conn   s    zSMTPChannel.__connc                 C   s   t dtd || _d S )NzISetting __conn attribute on SMTPChannel is deprecated, set 'conn' insteadrb   rx   rf   r   r   r   ry   %  s    c                 C   s   t dtd | jS )NzKAccess to __addr attribute on SMTPChannel is deprecated, use 'addr' insteadrb   r   rd   r:   r   r   r   r   __addr+  s    zSMTPChannel.__addrc                 C   s   t dtd || _d S )NzISetting __addr attribute on SMTPChannel is deprecated, set 'addr' insteadrb   rz   rf   r   r   r   r{   0  s    c                 C   s&   t j| t|d | jrdnd d S )Nr0   utf-8ascii)r5   r6   rS   bytesr[   r   r   r   r   rS   7  s    
zSMTPChannel.pushc                 C   s|   d }| j | jkr| j}n| j | jkr*| j}|r<| j|kr<d S |rR|  jt|7  _| jrl| j	t
|d n| j	| d S )Nr|   )rX   rW   r,   DATAr;   r\   lenr=   ra   appendstr)r   datalimitr   r   r   collect_incoming_data<  s    z!SMTPChannel.collect_incoming_datac                 C   s  | j | j}tdt|td g | _| j| jkr| jd }| _|sT| 	d d S | j
sdt|d}|d}|dk r| }d }n$|d |  }||d d   }| jr| j| n| j}||kr| 	d d S t| d	| d }|s| 	d
|  d S || d S | j| jkr(| 	d d| _d S | jrR| j| jkrR| 	d d| _d S g }|| jD ]:}	|	r|	d | jkr||	dd   n
||	 qb| j|| _| j| j| j| jf}
i }| j
s| j| jd}| j j!|
i |}| "  |s| 	d n
| 	| d S )NzData:r   r   z500 Error: bad syntaxr|    r$   z500 Error: line too longZsmtp_z&500 Error: command "%s" not recognizedz451 Internal confusionz552 Error: Too much mail data)mail_optionsrcpt_options250 OK)#r>   joinra   r   rQ   rR   rX   rW   r\   rS   r=   r   findupperstriprF   r(   r+   getattrr   r;   splitr?   r@   r   rB   r`   rL   rY   rZ   r   r   r8   process_messager^   )r   lineZszicommandargZmax_szmethodr   textrO   kwargsstatusr   r   r   found_terminatorL  sl    





zSMTPChannel.found_terminatorc                 C   sH   |s|  d d S | jr&|  d d S |   || _|  d| j  d S )Nz501 Syntax: HELO hostname503 Duplicate HELO/EHLOz250 %s)rS   rE   rD   rJ   r   r   r   r   r   	smtp_HELO  s    

zSMTPChannel.smtp_HELOc                 C   s   |s|  d d S | jr&|  d d S |   || _d| _|  d| j  | jrr|  d| j  | jd  d7  < | js|  d | jr|  d	 | jd  d
7  < |  d d S )Nz501 Syntax: EHLO hostnamer   Tz250-%sz250-SIZE %sMAIL   z250-8BITMIMEz250-SMTPUTF8
   z250 HELP)	rS   rE   rD   rF   rJ   r;   r(   r=   r<   r   r   r   r   	smtp_EHLO  s&    



zSMTPChannel.smtp_EHLOc                 C   s   |r|  d n
|  d d S )Nz501 Syntax: NOOPr   rS   r   r   r   r   	smtp_NOOP  s    zSMTPChannel.smtp_NOOPc                 C   s   |  d |   d S )Nz221 Bye)rS   Zclose_when_doner   r   r   r   	smtp_QUIT  s    
zSMTPChannel.smtp_QUITc                 C   s0   t |}|d |  |kr,||d   S dS r_   )r   r   r   )r   keywordr   Zkeylenr   r   r   _strip_command_keyword  s    z"SMTPChannel._strip_command_keywordc                 C   sF   |sdS |  dr$t|\}}nt|\}}|s<||fS |j|fS )N)r   r   <)lstrip
startswithr   r   Z	addr_spec)r   r   addressrestr   r   r   _getaddr  s    zSMTPChannel._getaddrc                 C   sH   i }|D ]:}| d\}}}| r,|r2|s2 d S |r:|nd||< q|S )N=T)	partitionisalnum)r   paramsresultZparameqrg   r   r   r   
_getparams  s    zSMTPChannel._getparamsc                 C   s  |rd}|  }|dkr$| d q|dkr8| d q|dkr^d}| jrR||7 }| | q|dkrd	}| jrx||7 }| | q|d
kr| d q|dkr| d q|dkr| d q|dkr| d q|dkr| d q| d n
| d d S )N [SP <mail-parameters>]ZEHLOz250 Syntax: EHLO hostnameZHELOz250 Syntax: HELO hostnamer   z 250 Syntax: MAIL FROM: <address>ZRCPTz250 Syntax: RCPT TO: <address>r   z250 Syntax: DATAZRSETz250 Syntax: RSETZNOOPz250 Syntax: NOOPZQUITz250 Syntax: QUITZVRFYz250 Syntax: VRFY <address>zD501 Supported commands: EHLO HELO MAIL RCPT DATA RSET NOOP QUIT VRFYzD250 Supported commands: EHLO HELO MAIL RCPT DATA RSET NOOP QUIT VRFY)r   rS   rF   )r   r   ZextendedZlc_argr   r   r   r   	smtp_HELP  s:    zSMTPChannel.smtp_HELPc                 C   s@   |r2|  |\}}|r"| d q<| d|  n
| d d S )NzB252 Cannot VRFY user, but will accept message and attempt deliveryz502 Could not VRFY %sz501 Syntax: VRFY <address>)r   rS   )r   r   r   r   r   r   r   	smtp_VRFY  s    zSMTPChannel.smtp_VRFYc                 C   s  | j s| d d S td|td d}| jr4|d7 }|d u rJ| | d S | d|}| |\}}|sv| | d S | js|r| | d S | jr| d d S | 	 | _
| | j
}|d u r| | d S | js|dd	}|d
vr| d d S | jr8|dd}|du r d| _n|dur8| d d S |dd }|r| sb| | d S | jrt|| jkr| d d S t| dkr| d d S || _td| jtd | d d S )N503 Error: send HELO firstz	===> MAILr   z 501 Syntax: MAIL FROM: <address>r   zFROM:z503 Error: nested MAIL commandZBODY7BIT)r   Z8BITMIMEz1501 Error: BODY can only be one of 7BIT, 8BITMIMEZSMTPUTF8FTz&501 Error: SMTPUTF8 takes no argumentsZSIZEz:552 Error: message size exceeds fixed maximum message sizer   z:555 MAIL FROM parameters not recognized or not implementedzsender:r   )rE   rS   r   rR   rF   r   r   rY   r   r   r   r   r=   popr<   r[   isdigitr;   intr   keys)r   r   	syntaxerrr   r   bodysmtputf8sizer   r   r   	smtp_MAIL  sh    














zSMTPChannel.smtp_MAILc                 C   s  | j s| d d S td|td | js6| d d S d}| jrH|d7 }|d u r^| | d S | d|}| |\}}|s| | d S | js|r| | d S | 	 | _
| | j
}|d u r| | d S t| dkr| d	 d S | j| td
| jtd | d d S )Nr   z	===> RCPTr   z503 Error: need MAIL commandz501 Syntax: RCPT TO: <address>r   zTO:r   z8555 RCPT TO parameters not recognized or not implementedzrecips:r   )rE   rS   r   rR   rY   rF   r   r   r   r   r   r   r   r   rZ   r   )r   r   r   r   r   r   r   r   	smtp_RCPT7  s@    







zSMTPChannel.smtp_RCPTc                 C   s(   |r|  d d S |   |  d d S )Nz501 Syntax: RSETr   )rS   rD   r   r   r   r   	smtp_RSETZ  s
    
zSMTPChannel.smtp_RSETc                 C   sZ   | j s| d d S | js(| d d S |r:| d d S | j| _| d | d d S )Nr   z503 Error: need RCPT commandz501 Syntax: DATAs   
.
z#354 End data with <CR><LF>.<CR><LF>)rE   rS   rZ   r   rX   r]   r   r   r   r   	smtp_DATAa  s    



zSMTPChannel.smtp_DATAc                 C   s   |  d d S )Nz502 EXPN not implementedr   r   r   r   r   	smtp_EXPNp  s    zSMTPChannel.smtp_EXPN),r   r   r   rW   r   r+   collectionsdefaultdictr(   propertyr,   DATA_SIZE_DEFAULTr7   r^   rD   Z_SMTPChannel__serversetterZ_SMTPChannel__lineZ_SMTPChannel__stateZ_SMTPChannel__greetingZ_SMTPChannel__mailfromZ_SMTPChannel__rcpttosZ_SMTPChannel__dataZ_SMTPChannel__fqdnZ_SMTPChannel__peerZ_SMTPChannel__connZ_SMTPChannel__addrrS   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   w   s   

'	





















>#6#r   c                   @   s2   e Zd ZeZedddfddZdd Zdd ZdS )	r   NFc                 C   s   || _ || _|| _|| _|| _|r.|r.tdtjj| |d zNt	j
|dt	ji}| |d d |d d  |   | | | d W n   |    Y n(0 td| jjtt ||f td d S )	Nr/   r-   typer   r$      z0%s started at %s
	Local addr: %s
	Remote addr:%sr   )Z
_localaddr_remoteaddrr;   r<   r=   r*   asyncore
dispatcherr7   rH   getaddrinfoSOCK_STREAMZcreate_socketZset_reuse_addrbindlistenrN   r   	__class__r   timectimerR   )r   Z	localaddrZ
remoteaddrr;   r.   r<   rU   Zgai_resultsr   r   r   r7   x  s2    
zSMTPServer.__init__c              	   C   s6   t dt| td | | ||| j| j| j| j}d S )NzIncoming connection from %sr   )r   rQ   rR   channel_classr;   _mapr<   r=   )r   r9   r:   Zchannelr   r   r   handle_accepted  s    zSMTPServer.handle_acceptedc                 K   s   t d S r   )NotImplementedErrorr   rL   rY   rZ   r   r   r   r   r   r     s    zSMTPServer.process_message)	r   r   r   r   r   r   r7   r   r   r   r   r   r   r   t  s   
r   c                   @   s   e Zd Zdd Zdd ZdS )r   c                 C   sl   d}|  }|D ]V}|rL|sLd|d  }t|ts@t|d}t| d}t|ts^t|}t| qd S )Nr$   zX-Peer: r   r|   )
splitlines
isinstancer   rQ   encoder   )r   rL   r   Z	inheaderslinesr   Z
peerheaderr   r   r   _print_message_content  s    

z&DebuggingServer._print_message_contentc                 K   sX   t d |r@|dr&t d|d   |dr@t d|d   | || t d d S )Nz%---------- MESSAGE FOLLOWS ----------r   zmail options: %sr   zrcpt options: %s
z%------------ END MESSAGE ------------)r   getr   r   r   r   r   r     s    

zDebuggingServer.process_messageN)r   r   r   r   r   r   r   r   r   r     s   r   c                       s,   e Zd Z fddZdd Zdd Z  ZS )r   c                    s2   d|v r|d rt dtt| j|i | d S )Nr<   z$PureProxy does not support SMTPUTF8.)r*   superr   r7   r   rO   r   r   r   r   r7     s    zPureProxy.__init__c           	      C   sf   | d}d}|D ]}|s q(|d7 }q||d|d   t|}| |||}td|td d S )Nr   r   r$   z
X-Peer: %szwe got some refusals:r   )r   insertrA   r   _deliverr   rR   )	r   rL   rY   rZ   r   r   r   r   refusedr   r   r   r     s    


zPureProxy.process_messagec              
   C   s   dd l }i }zJ| }|| jd | jd  z||||}W |  n
|  0 W n |jy } ztdtd |j	}W Y d }~npd }~0  t
|jfy } zJtd|jtd t|dd}t|dd	}	|D ]}
||	f||
< qW Y d }~n
d }~0 0 |S )
Nr   r$   zgot SMTPRecipientsRefusedr   ZgotZ	smtp_codeZ
smtp_errorignore)smtplibZSMTPconnectr   ZsendmailquitZSMTPRecipientsRefusedr   rR   Z
recipientsrM   ZSMTPExceptionr   r   )r   rY   rZ   r   r   r   seZerrcodeerrmsgrr   r   r   r     s$    $zPureProxy._deliver)r   r   r   r7   r   r   __classcell__r   r   r   r   r     s   r   c                       s$   e Zd Z fddZdd Z  ZS )r	   c                    s>   t dtd d|v r$|d r$tdtt| j|i | d S )Nz8MailmanProxy is deprecated and will be removed in futurerb   r<   z'MailmanProxy does not support SMTPUTF8.)r   rd   r*   r   r   r7   r   r   r   r   r7     s    zMailmanProxy.__init__c                 C   s*  ddl m} ddlm} ddlm} ddlm} g }	|D ]t}
|
 dd }|d}t|dkrfq8|d }t|dkr|d	 }nd
}|	|r8|dvrq8|	
|
||f q8|	D ]\}
}}||
 qtdd|td |r| |||}td|td i }||}||}|ds&||d< |dsDtt |d< |	D ]\}
}}td|
td ||}|s|j|dd}|||< |d
kr|j|d	d n|dkr|j|d	d nh|dkr|j|d	d nN|dkr|j|d	d n4|dv rH|dkrd|d < nd!|d < |j|d	d qHd S )"Nr   )StringIO)Utils)Message)MailList@-rb   r$   r   )r   adminownerrequestr   leavezforwarding recips:r   r   zwe got refusals:fromZFromdateZDatezsending message to)lock)tolistr   )Ztoadminr   )Ztoownerr   )Z	torequest)r   r   r   Z	subscribeZSubjectZunsubscribe)ior   ZMailmanr   r   r   lowerr   r   Zlist_existsr   remover   r   rR   r   r   r   r   ZEnqueue)r   rL   rY   rZ   r   r   r   r   r   Z	listnamesZrcptlocalpartsZlistnamer   r   Zmlistsr   r   Zmlistr   r   r   r     sb    










zMailmanProxy.process_message)r   r   r   r7   r   r   r   r   r   r   r	     s   r	   c                   @   s   e Zd ZdZdZdZdZdS )OptionsTr   NF)r   r   r   setuid	classname
size_limitr<   r   r   r   r   r  a  s   r  c            
   
   C   sd  z$t  tjdd  dg d\} }W n0 t jyT } ztd| W Y d }~n
d }~0 0 t }| D ]\}}|dv rztd q`|dv rtt td q`|dv rd|_	q`|d	v r||_
q`|d
v rtjaq`|dv rd|_q`|dv r`zt|}||_W q`   td| tjd td Y q`0 q`t|dk r4d}d}nPt|dk rP|d }d}n4t|dk rp|d }|d }ntddt|  |d}	|	dk rtdd|  |d |	 |_zt||	d d  |_W n" ty   tdd|  Y n0 |d}	|	dk rtdd|  |d |	 |_zt||	d d  |_W n" ty^   tdd|  Y n0 |S )Nr$   z	nVhc:s:du)zclass=Znosetuidversionhelpzsize=debugr   )z-hz--helpr   )z-Vz	--version)z-nz
--nosetuidF)z-cz--class)z-dz--debug)z-uz
--smtputf8T)z-sz--sizezInvalid size: r   zlocalhost:8025zlocalhost:25rb      zInvalid arguments: %s:zBad local spec: %szBad local port: %szBad remote spec: %szBad remote port: %s)getoptr   argverrorr#   r  r   rT   r!   r  r  r    rR   r<   r   r  r   
COMMASPACEr   r   	localhost	localportr*   
remotehost
remoteport)
ZoptsrO   r   optionsoptr   Zint_sizeZ	localspecZ
remotespecr   r   r   r   	parseargsh  sp     






r  __main__r1   r$   )r<   z7Cannot import module "pwd"; try running with -n option.r   nobodyrb   z3Cannot setuid "nobody"; try running with -n option.)r   )?r   osrP   r  r   rH   r   r5   r   warningsr   Zemail._header_value_parserr   r   __all__r  ZprogramrT   r
   rR   rA   r  r   r#   r6   r   r   r   r   r   r	   r  r  r   r  r  rfindZlastdot
__import__r   localsmodr  r   class_r  r  r  r  r  r<   proxyr  pwdImportErrorr   r    r!   getpwnamr  PermissionErrorZloopKeyboardInterruptr   r   r   r   <module>P   sv   

    M-UB




