o
     JAf]                     @   s^  	 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dedd d dlZd dl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r-e! Z#e#j$Z$d e$v re$%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#j0e#j1fe#j2e#j3d"Z4e#j5rzd dl6Z6W n e7y   e8d#e j9d$ e :d! Y nw e6;d%d Z<ze5e< W n e=y   e8d&e j9d$ e :d! Y nw ze>  W dS  e?y,   Y dS w dS )(    N)warn)get_addr_specget_angle_addr)SMTPChannel
SMTPServerDebuggingServer	PureProxyMailmanProxyzThe smtpd module is deprecated and unmaintained and will be removed in Python 3.12.  Please see aiosmtpd (https://aiosmtpd.readthedocs.io/) for the recommended replacement.   )
stacklevelzPython SMTP proxy version 0.3c                   @      e Zd Zdd Zdd ZdS )Devnullc                 C      d S N selfmsgr   r   /usr/lib/python3.10/smtpd.pywriter       zDevnull.writec                 C   r   r   r   r   r   r   r   flushs   r   zDevnull.flushN)__name__
__module____qualname__r   r   r   r   r   r   r   q   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   usage|   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 w 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 || _|| _|| _|| _|| _|| _|r#|r#t	d|r2d| _
d| _d| _t| _nd| _
d| _td| _d	| _|   d| _d
| _| j  t | _z| | _W n tyy } z|   |jtjkrn W Y d }~d S d }~ww 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   
.       
   .   
Fz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errnoZENOTCONNr    reprDEBUGSTREAMpush__version__)	r   Zserverr>   r?   r@   r2   rA   decode_dataerrr   r   r   r<      sD   


zSMTPChannel.__init__c                 C   s0   	 | j | _d | _g | _d| _d| _| d d S )NFr   r7   )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   )rb   received_datareceived_linesr   r   r   r   rI      s   
zSMTPChannel._set_rset_statec                 C      t dtd | jS )NzTAccess to __server attribute on SMTPChannel is deprecated, use 'smtp_server' insteadr
   r   DeprecationWarningr=   r   r   r   r   __server      zSMTPChannel.__serverc                 C      t dtd || _d S )NzRSetting __server attribute on SMTPChannel is deprecated, set 'smtp_server' insteadr
   rg   r   valuer   r   r   ri         
c                 C   rf   )NzUAccess to __line attribute on SMTPChannel is deprecated, use 'received_lines' insteadr
   r   rh   re   r   r   r   r   __line   rj   zSMTPChannel.__linec                 C   rk   )NzSSetting __line attribute on SMTPChannel is deprecated, set 'received_lines' insteadr
   ro   rl   r   r   r   rp      rn   c                 C   rf   )NzRAccess to __state attribute on SMTPChannel is deprecated, use 'smtp_state' insteadr
   r   rh   r\   r   r   r   r   __state   rj   zSMTPChannel.__statec                 C   rk   )NzPSetting __state attribute on SMTPChannel is deprecated, set 'smtp_state' insteadr
   rq   rl   r   r   r   rr      rn   c                 C   rf   )NzXAccess to __greeting attribute on SMTPChannel is deprecated, use 'seen_greeting' insteadr
   r   rh   rJ   r   r   r   r   
__greeting   rj   zSMTPChannel.__greetingc                 C   rk   )NzVSetting __greeting attribute on SMTPChannel is deprecated, set 'seen_greeting' insteadr
   rs   rl   r   r   r   rt      rn   c                 C   rf   )NzSAccess to __mailfrom attribute on SMTPChannel is deprecated, use 'mailfrom' insteadr
   r   rh   r]   r   r   r   r   
__mailfrom   rj   zSMTPChannel.__mailfromc                 C   rk   )NzQSetting __mailfrom attribute on SMTPChannel is deprecated, set 'mailfrom' insteadr
   ru   rl   r   r   r   rv      rn   c                 C   rf   )NzQAccess to __rcpttos attribute on SMTPChannel is deprecated, use 'rcpttos' insteadr
   r   rh   r^   r   r   r   r   	__rcpttos   rj   zSMTPChannel.__rcpttosc                 C   rk   )NzOSetting __rcpttos attribute on SMTPChannel is deprecated, set 'rcpttos' insteadr
   rw   rl   r   r   r   rx     rn   c                 C   rf   )NzTAccess to __data attribute on SMTPChannel is deprecated, use 'received_data' insteadr
   r   rh   rd   r   r   r   r   __data  rj   zSMTPChannel.__datac                 C   rk   )NzRSetting __data attribute on SMTPChannel is deprecated, set 'received_data' insteadr
   ry   rl   r   r   r   rz     rn   c                 C   rf   )NzKAccess to __fqdn attribute on SMTPChannel is deprecated, use 'fqdn' insteadr
   r   rh   rO   r   r   r   r   __fqdn  rj   zSMTPChannel.__fqdnc                 C   rk   )NzISetting __fqdn attribute on SMTPChannel is deprecated, set 'fqdn' insteadr
   r{   rl   r   r   r   r|     rn   c                 C   rf   )NzKAccess to __peer attribute on SMTPChannel is deprecated, use 'peer' insteadr
   r   rh   rQ   r   r   r   r   __peer!  rj   zSMTPChannel.__peerc                 C   rk   )NzISetting __peer attribute on SMTPChannel is deprecated, set 'peer' insteadr
   r}   rl   r   r   r   r~   &  rn   c                 C   rf   )NzKAccess to __conn attribute on SMTPChannel is deprecated, use 'conn' insteadr
   r   rh   r>   r   r   r   r   __conn,  rj   zSMTPChannel.__connc                 C   rk   )NzISetting __conn attribute on SMTPChannel is deprecated, set 'conn' insteadr
   r   rl   r   r   r   r   1  rn   c                 C   rf   )NzKAccess to __addr attribute on SMTPChannel is deprecated, use 'addr' insteadr
   r   rh   r?   r   r   r   r   __addr7  rj   zSMTPChannel.__addrc                 C   rk   )NzISetting __addr attribute on SMTPChannel is deprecated, set 'addr' insteadr
   r   rl   r   r   r   r   <  rn   c                 C   s&   t j| t|d | jrdnd d S )Nr4   utf-8ascii)r:   r;   rW   bytesr_   r   r   r   r   rW   C  s   

zSMTPChannel.pushc                 C   s~   d }| j | jkr| j}n	| j | jkr| j}|r| j|krd S |r)|  jt|7  _| jr7| j	t
|d d S | j	| d S )Nr   )r\   r[   r0   DATAr@   r`   lenrB   re   appendstr)r   datalimitr   r   r   collect_incoming_dataH  s   z!SMTPChannel.collect_incoming_datac                 C   s  | j | j}tdt|td g | _| j| jkr| jd}| _|s)| 	d d S | j
s1t|d}|d}|dk rA| }d }n|d |  }||d d   }| jr[| j| n| j}||kri| 	d d S t| d	| d }|s|| 	d
|  d S || d S | j| jkr| 	d d| _d S | jr| j| jkr| 	d d| _d S g }|| jD ]}	|	r|	d | jkr||	dd   q||	 q| j|| _| j| j| j| jf}
i }| j
s| j| jd}| j j!|
i |}| "  |s| 	d d S | 	| 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)#rC   joinre   r    rU   rV   r\   r[   r`   rW   rB   r   findupperstriprK   r,   r/   getattrr   r@   splitrD   rE   r   rG   rd   rQ   r]   r^   r   r   r=   process_messagerb   )r   lineZszicommandargZmax_szmethodr   textargskwargsstatusr   r   r   found_terminatorX  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)rW   rJ   rI   rO   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r9|  d| j  | jd  d7  < | jsA|  d | jrR|  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)	rW   rJ   rI   rK   rO   r@   r,   rB   rA   r   r   r   r   	smtp_EHLO  s&   



zSMTPChannel.smtp_EHLOc                 C   s    |r	|  d d S |  d d S )Nz501 Syntax: NOOPr   rW   r   r   r   r   	smtp_NOOP  s   zSMTPChannel.smtp_NOOPc                 C   s   |  d |   d S )Nz221 Bye)rW   Zclose_when_doner   r   r   r   	smtp_QUIT  s   
zSMTPChannel.smtp_QUITc                 C   s0   t |}|d |  |kr||d   S dS rc   )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|r|s d S |r|nd||< q|S )N=T)	partitionisalnum)r   paramsresultZparameqrm   r   r   r   
_getparams  s   zSMTPChannel._getparamsc                 C   s  |rd}|  }|dkr| d d S |dkr| d d S |dkr2d}| jr+||7 }| | d S |dkrFd	}| jr?||7 }| | d S |d
krQ| d d S |dkr\| d d S |dkrg| d d S |dkrr| d d S |dkr}| d d S | d d S | 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   rW   rK   )r   r   ZextendedZlc_argr   r   r   r   	smtp_HELP  s:   zSMTPChannel.smtp_HELPc                 C   sD   |r|  |\}}|r| d d S | d|  d S | d d S )NzB252 Cannot VRFY user, but will accept message and attempt deliveryz502 Could not VRFY %sz501 Syntax: VRFY <address>)r   rW   )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r|d7 }|d u r%| | d S | d|}| |\}}|s;| | d S | jsG|rG| | d S | jrQ| d d S | 	 | _
| | j
}|d u ri| | d S | js}|dd	}|d
vr}| d d S | jr|dd}|du rd| _n|dur| d d S |dd }|r| s| | 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   )rJ   rW   r    rV   rK   r   r   r]   r   r   r   r   rB   poprA   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s| d d S d}| jr$|d7 }|d u r/| | d S | d|}| |\}}|sE| | d S | jsQ|rQ| | d S | 	 | _
| | j
}|d u ri| | d S t| dkrx| 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   )rJ   rW   r    rV   r]   rK   r   r   r   r   r   r   r   r   r^   r   )r   r   r   r   r   r   r   r   	smtp_RCPTC  s@   







zSMTPChannel.smtp_RCPTc                 C   s(   |r	|  d d S |   |  d d S )Nz501 Syntax: RSETr   )rW   rI   r   r   r   r   	smtp_RSETf  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>)rJ   rW   r^   r   r\   ra   r   r   r   r   	smtp_DATAm  s   



zSMTPChannel.smtp_DATAc                 C   s   |  d d S )Nz502 EXPN not implementedr   r   r   r   r   	smtp_EXPN|  s   zSMTPChannel.smtp_EXPN),r   r   r   r[   r   r/   collectionsdefaultdictr,   propertyr0   DATA_SIZE_DEFAULTr<   rb   rI   Z_SMTPChannel__serversetterZ_SMTPChannel__lineZ_SMTPChannel__stateZ_SMTPChannel__greetingZ_SMTPChannel__mailfromZ_SMTPChannel__rcpttosZ_SMTPChannel__dataZ_SMTPChannel__fqdnZ_SMTPChannel__peerZ_SMTPChannel__connZ_SMTPChannel__addrrW   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      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 z't	j
|dt	ji}| |d d |d d  |   | | | d W n   |    td| jjtt ||f td d S )	Nr3   r1   typer   r(      z0%s started at %s
	Local addr: %s
	Remote addr:%sr   )Z
_localaddr_remoteaddrr@   rA   rB   r.   asyncore
dispatcherr<   rM   getaddrinfoSOCK_STREAMZcreate_socketZset_reuse_addrbindlistenrS   r    	__class__r   timectimerV   )r   Z	localaddrZ
remoteaddrr@   r2   rA   rY   Zgai_resultsr   r   r   r<     s2   

zSMTPServer.__init__c              	   C   s6   t dt| td | | ||| j| j| j| j}d S )NzIncoming connection from %sr   )r    rU   rV   channel_classr@   _maprA   rB   )r   r>   r?   Zchannelr   r   r   handle_accepted  s   zSMTPServer.handle_acceptedc                 K   s   	 t r   )NotImplementedErrorr   rQ   r]   r^   r   r   r   r   r   r     s   zSMTPServer.process_message)	r   r   r   r   r   r   r<   r   r   r   r   r   r   r     s    
r   c                   @   r   )r   c                 C   sl   d}|  }|D ]+}|r&|s&d|d  }t|ts t|d}t| d}t|ts/t|}t| qd S )Nr(   zX-Peer: r   r   )
splitlines
isinstancer   rU   encoder    )r   rQ   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 )NrA   z$PureProxy does not support SMTPUTF8.)r.   superr   r<   r   r   r   r   r   r   r<     s   zPureProxy.__init__c           	      C   sf   | d}d}|D ]
}|s n|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   insertrF   r   _deliverr    rV   )	r   rQ   r]   r^   r   r   r   r   refusedr   r   r   r     s   


zPureProxy.process_messagec              
   C   s   dd l }i }z%| }|| jd | jd  z||||}W |  W |S |  w  |jyH } ztdtd |j	}W Y d }~|S d }~w t
|jfy| } z&td|jtd t|dd}t|dd	}	|D ]}
||	f||
< qhW Y d }~|S d }~ww )
Nr   r(   zgot SMTPRecipientsRefusedr   ZgotZ	smtp_codeZ
smtp_errorignore)smtplibZSMTPconnectr   ZsendmailquitZSMTPRecipientsRefusedr    rV   Z
recipientsrR   ZSMTPExceptionr   r   )r   r]   r^   r   r   r   seZerrcodeerrmsgrr   r   r   r     s2   



zPureProxy._deliver)r   r   r   r<   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 futurer
   rA   z'MailmanProxy does not support SMTPUTF8.)r   rh   r.   r   r   r<   r   r   r   r   r<     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 ]:}
|
 dd }|d}t|dkr3q|d }t|dkrB|d	 }nd
}|	|rM|dvrNq|	
|
||f q|	D ]
\}
}}||
 qYtdd|td |r~| |||}td|td i }||}||}|ds||d< |dstt |d< |	D ]g\}
}}td|
td ||}|s|j|dd}|||< |d
kr|j|d	d q|dkr|j|d	d q|dkr|j|d	d q|dkr|j|d	d q|dv r	|dkrd|d < nd!|d < |j|d	d qd S )"Nr   )StringIO)Utils)Message)MailList@-r
   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   rV   r   r   r   r   ZEnqueue)r   rQ   r]   r^   r   r   r   r   r   Z	listnamesZrcptlocalpartsZlistnamer   r   Zmlistsr   r   Zmlistr   r   r   r      sf   







zMailmanProxy.process_message)r   r   r   r<   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_limitrA   r   r   r   r   r  m  s
    r  c            
   
   C   sX  zt  tjdd  dg d\} }W n t jy* } ztd| W Y d }~nd }~ww t }| D ]\\}}|dv r=td q0|dv rKtt td q0|dv rSd|_	q0|d	v r[||_
q0|d
v rctjaq0|dv rkd|_q0|dv rz	t|}||_W q0   td| tjd td Y q0q0t|dk rd}d}n&t|dk r|d }d}nt|dk r|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w |d}	|	dk rtdd|  |d |	 |_zt||	d d  |_W |S  ty+   tdd|  Y |S w )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:25r
      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    rX   r%   r  r  r$   rV   rA   r   r  r   
COMMASPACEr   r   	localhost	localportr.   
remotehost
remoteport)
Zoptsr   r   optionsoptr   Zint_sizeZ	localspecZ
remotespecr   r   r   r   	parseargst  s|   

	



r  __main__r5   r(   )rA   z7Cannot import module "pwd"; try running with -n option.r   nobodyz3Cannot setuid "nobody"; try running with -n option.)r   )@r#   osrT   r  r   rM   r   warningsr   Zemail._header_value_parserr   r   __all__rh   r   r:   r  ZprogramrX   r   rV   rF   r  r   r'   r;   r   r   r   r   r   r	   r  r  r   r  r  rfindZlastdot
__import__r"   localsmodr   r   class_r  r  r  r  r  rA   proxyr  pwdImportErrorr    r$   r%   getpwnamr!  PermissionErrorZloopKeyboardInterruptr   r   r   r   <module>   s   N


    M-U
B


