Ϫfk dZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl mZddlmZddlmZddlmZdd lmZmZmZmZdd lmZdd lmZmZdd lm Z m!Z!m"Z#dd l$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z6m7Z7ddl8m9Z9m:Z:m;Z;mm?Z?m@Z@ddlAmBZBmCZCddlDmEZEmFZFmGZGddlHmIZIgdZJeIjr!ejjdZNn ejjdZNePjeRddZSdDdZTdZUeUZVddfdZWdZXd\ZYZZZ[dZ\GddZ]Gd d!Z^Gd"d#e?je@jZaGd$d%ejZcGd&d'e?je@jZeGd(d)eeZfGd*d+eaZgGd,d-ZhGd.d/eheeZiGd0d1ejZkGd2d3e#Z"ee9Gd4d5ZlGd6d7ehefZmGd8d9ekZndd:eddd;d;fd<ZoddlpZpdEd=ZqdEd>ZrGd?d@epjZtGdAdBepjZvdCZwepjewy)Fz/ Simple Mail Transfer Protocol implementation. N) parseaddr)BytesIO)Type) implementer)cred) longversion)defererrorprotocolreactor) _idnaText) ISSLTransport ITLSTransport)CramMD5ClientAuthenticatorLOGINAuthenticatorLOGINCredentials) AddressErrorAUTHDeclinedErrorAuthenticationErrorAUTHRequiredErrorEHLORequiredErrorESMTPClientErrorSMTPAddressError SMTPBadRcpt SMTPBadSenderSMTPClientErrorSMTPConnectErrorSMTPDeliveryError SMTPErrorSMTPProtocolErrorSMTPServerErrorSMTPTimeoutError SMTPTLSErrorTLSRequiredError)IClientAuthenticationIMessageDeliveryIMessageDeliveryFactory IMessageSMTP)basicpolicies)logutil) iterbytes nativeString networkString)platform)0rrrrrrrrrrrrrr!r"TLSErrorr$r r%IMessager&r'rrrPLAINAuthenticatorAddressUsersendmail SenderMixinESMTP ESMTPClient ESMTPSenderESMTPSenderFactorySMTP SMTPClient SMTPFactory SMTPSenderSMTPSenderFactory idGenerator messageid quoteaddr rfc822datextextStreamReaderxtextStreamWriter xtext_codec xtext_decode xtext_encodeasciii,c |s+|rtj}ntj}|rl|drtj }ntj }t t |d\}}|r|tt ||zz}t |d\}}nd\}}tdgd|d|dgd |d d z |d |d |d |d||f zS)a Format an RFC-2822 compliant date string. @param timeinfo: (optional) A sequence as returned by C{time.localtime()} or C{time.gmtime()}. Default is now. @param local: (optional) Indicates if the supplied time is local or universal time, or if no time is given, whether now should be local or universal time. Default is local, as suggested (SHOULD) by rfc-2822. @returns: A L{bytes} representing the time and date in RFC-2822 format. i<)rrz)%s, %02d %s %04d %02d:%02d:%02d %+03d%02d)MonTueWedThuFriSatSun) JanFebMarAprMayJunJulAugSepOctNovDecr) time localtimegmtimealtzonetimezonedivmodabsintr/)timeinfolocaltztzhrtzmintzsecs 3/usr/lib/python3/dist-packages/twisted/mail/smtp.pyrDrDs  ~~'H{{}H A;,,B--Bs2w- u CB2 & &Dr* u 3 =hqk J QK qkAo  QK QK QK QK  -   c#$Kd} ||dz } w)Nrrd)is rvrArAs! A  Q sc ttSN)next_genryrwrvrs 4:rwc .tjdtj}tj}t j d}|d}nd|z}dj|||||tjjS)z Return a globally unique random string in RFC 2822 Message-ID format Optional uniq string will be added to strengthen uniqueness if given. z %Y%m%d%H%M%Si.z<{}.{}.{}{}.{}@{}>) rhstrftimerjosgetpidrandom randrangeformatDNSNAMEdecodeencode)uniqNdatetimepidrands rvrBrBsx}}^T[[];H ))+C   I &D |Tz  & &#tT13(8  fhrwct|trdt|zdzSt|tr|jd}t |}|dk(rdt|zdzSd|dj dzdzS)zq Turn an email address, possibly with realname part etc, into a form suitable for and SMTP envelope. <>rJNNrd) isinstancer4bytesrrr)addrress rvrCrCs| $ eDk!D((${{7# D/C leDk!D((c!fmmG,,t33rw)COMMANDDATAAUTHs[-A-Za-z0-9!\#$%&'*+/=?^_`{|}~]ceZdZdZej dezdzejZej eZ d dZ ej dZ dZ de fd Zdefd Zde fd Zy) r4aFParse and hold an RFC 2821 address. Source routes are stipped and ignored, UUCP-style bang-paths and %-style routing are not parsed. @type domain: C{bytes} @ivar domain: The domain within which this address resides. @type local: C{bytes} @ivar local: The local ("user") portion of this address. s( # A string of (?:"[^"]*" # quoted string |\\. # backslash-escaped characted |sL # atom character )+|.) # or any single characterNct|tr |j}t|tr |jj |_yt|t st|jd}||_ ttd|jj|}g}g}|r|ddk(r|ddk7r td|dd}n|ddk(rE|dd}|s-|r|dd k7r|dd}|r |dd k7r|s td |dd}n|r td d g}n}t|ddk(r<|j j#|ds|dd k7rtd|dd||f|s|j%|dn|j%|d|dd}|rd j'||_d j'||_|j(d k7r |j*d k(r|t,}||_yyy)NrJrrrz Unbalanced <>rd@:zMalformed source routez Too many @rw.zParse error at z of )rr5destr4__dict__copyrstrraddrstrlistfiltertstringsplitrlenatomrematchappendjoinrqdomainr)selfr defaultDomainatlrqrs rv__init__zAddress.__init__s dD !99D dG $ MM..0DM D%(t9##G,D 6$ 2 24 89:1v~r7d?&77!BiQ4!"g#a&D.!!"g#a&D.*+CDDab'C&|44"UFSV!$++*;*;CF*CARV"_SVJdD#;/#RSSLLQ(MM#a&)!"g7:XXe_ hhv& :: !3$ ' 'DK"4 rws\\(.)cg}t|tst|jd}t d|j j |}|D]h}|ddk(r|ddk(r|j|dd(d|vr,|j|jjd|X|j|jd j|S) z6 Remove RFC-2821 quotes from address. rJNr"rrd\s\1rw) rrrrrrrr dequotebssubr)rrrrts rvdequotezAddress.dequoteJs$&t9##G,DT4<<--d34 Att|"  1Qr7# 4>>--fa89 1  xx}rwreturnc@|jjdSNrJ __bytes__rrs rv__str__zAddress.__str___~~&&w//rwc|js |jr'dj|j|jfSy)Nrrw)rqrrrs rvrzAddress.__bytes__bs. ::99djj$++67 7rwc dj|j|jjt t |S)Nz {}.{}({}))r __module__ __class____name__reprrrs rv__repr__zAddress.__repr__hs2!! OOT^^44d3t9o  rwr|)rr __qualname____doc__recompileatomXrrrrrrrrrrryrwrvr4r4s bjj      >  >  GRZZ F2(h 9%I*005  # rwr4c4eZdZdZdZdZdefdZdefdZ y)r5zu Hold information about and SMTP message recipient, including information on where the message came from c |j}t|||_||_||_t |tr||_yt|||_y#t$rd}YVwxYwr|)hostAttributeErrorr4rhelor rorig)r destinationrr rrs rvrz User.__init__tsc ==DK.    dG $DId+DI D s A A%$A%cL|j|jd|jdS)z Helper for pickle. protocol isn't picklabe, but we want User to be, so skip it in the pickle. N)rrr r)rrrrs rv __getstate__zUser.__getstate__s&IIIIII   rwrc@|jjdSrrrs rvrz User.__str__rrwc,t|jSr|)rrrs rvrzUser.__bytes__sTYYrwN) rrrrrrrrrrryrwrvr5r5ns) ,  00 5 rwr5ceZdZdZdZdZdZdZdZdZ d*dZ e dZ e jdZ dZd Zd Zd+d Zd Zd ZdZdZdZdZdZdZdezdzZej:dezdzezdzej<ej>zZ ej:dezdzezdzej<ej>zZ!dZ"d,dZ#dZ$dZ%d-dZ&dZ'd Z(d!Z)d"Z*d#Z+d$Z,e,Z-d%Z.d&Z/d'Z0d(Z1d)Z2y).r<zp SMTP server-side protocol. @ivar host: The hostname of this mail server. @type host: L{bytes} XNTcvt|_d|_d|_g|_||_||_t|_yr|) rmode_from_helo_todeliverydeliveryFactoryrr)rrrs rvrz SMTP.__init__s4     . rwc|jSr|)_hostrs rvrz SMTP.hosts zzrwcft|tst|jd}||_yr)rrrrr)rtoSets rvrz SMTP.hosts'%'J%%g.E rwcz|jdz}|jd||jjy)Ns' Timeout. Try talking faster next time!i)rsendCode transportloseConnection)rmsgs rvtimeoutConnectionzSMTP.timeoutConnections/iiDD c3 %%'rwc |jdzS)Ns NO UCE NO UBE NO RELAY PROBES)rrs rvgreetingz SMTP.greetingsyy<<\s*FROM:\s*(?P<> # Empty <> | # |sq # addr )\s*(\s(?P.*))? # Optional WS + ESMTP options $s\s*TO:\s*(?P MM#U Vrwc  |js|jddy|jj|}|s|jddy t |j d|j ||j}tj|j|}|j|j|j|fy#t$r.}|jdtt|Yd}~yd}~wwxYw)Nr&s!Must have sender before recipientr'r(r)r*) callbackArgs)rrrcpt_rerr5r,rrr/rr r- validateTor/ _cbToValidate _ebToValidate)rrr2userr3ds rvdo_RCPTz SMTP.do_RCPTmszz MM#C D  LL  t $ MM# /  T4::FD    6 t))4+=+=TGT   MM#}SV4 5  s1C D$C>>Dcj||}|jj||f|j||yr|)rrr)rtorHrrs rvrFzSMTP._cbToValidates. <D r # dC rwc|jttrD|j|jj t |jjytj||jddy)Nr:r;) r<rr!rr=rr/r>r+r?r@s rvrGzSMTP._ebToValidatesR ==o 6 MM'--,,mGMMrrQrOr+r?r_SMTP__inheader _SMTP__inbodynoisyrr)rrrorigin recipientsrPrHmsgFuncrrcvdhdrr3fmtufs rvdo_DATAz SMTP.do_DATAs :: dhh MM#I J  zz4::fXX  ' MD' i--dFTFC$$W- C  $*++$- c;' ::AC GGC6#Dv1CF#DEE F !#  affaff-#   &    c#;<#   &  $Es&;?D)G) G 2AE::AG  G c>|jtur% |jD]} |j|`|jr|jd|_|jdy#t$rt j YlwxYw#t$rYcwxYwr|) rrrrrOr+r?r _onLogoutr)rreasonrs rvrzSMTP.connectionLosts 99  #"G"..0" O >> NN !DN )" ""  s3BA-B-B  B B  B BBcDd|_g|_|jddy)NrsI remember nothing.)rrrrs rvdo_RSETz SMTP.do_RSETs  c12rwcP|dddk(r|dk(rt|_|jr;|j|jj|jj y|j s|jdytj|j Dcgc]}|jc}dj|j|`y|dd}|jry |jsC|js7d|vrd|_ n+|r)|j D]}|jdd|_ |sd|_ |j D]}|j|ycc}w#t$r2}||_|j D]}|j!Yd}~yd}~wwxYw)Nrdrz thrown awayT) consumeErrorsrrw)rrrUrrr>r_messageHandledr DeferredList eomReceived addCallbackrWrXrr!r)rrr2rr3s rvdataLineReceivedzSMTP.dataLineReceivedsl 8t t|# ??MM$//"6"68L8LM((7"".2oo>Q]]_>d+d223O8D ??  )??4==4<&'DO#'??2,,S12$%DM ! ?? +$$T* +1?4 )DO?? )&&( ) )sE%*A:E** F%3(F  F%cd}|D]"\}}|r |dz }tj|$|r:d}t|}|dkDr |d|d|dz }|jdt |y|jdd y) NrrdzCould not send e-mailz (z failures out of z recipients)rSrsDelivery in progress)r+r?rrr/)r resultListfailuressuccessresultr resultLens rvrizSMTP._messageHandleds) OGVA   )CJI1}H:%6ykNN MM#}S1 2 MM#6 7rwc|\}}}t|tr||_d|_n7t|trd|_||_nt |j d||_d|_y)zR Save the state resulting from a successful anonymous cred login. Nz is not a supported interface) issubclassr'rrr& RuntimeErrorrrc challenger)rrrifaceavatarlogouts rv_cbAnonymousAuthenticationzSMTP._cbAnonymousAuthenticationsj#) e4 5#)D  DM / 0#'D "DM%..!11NOP Prwcjjj_j+tjjj Sj r}j jtjjdtt}fd}|jj|fd}|j||St!)a Validate the address from which the message originates. @type helo: C{(bytes, bytes)} @param helo: The argument to the HELO command and the client's IP address. @type origin: C{Address} @param origin: The address the message is from @rtype: C{Deferred} or C{Address} @return: C{origin} or a C{Deferred} whose callback will be passed C{origin}. @raise SMTPBadSender: Raised of messages from this address are not to be accepted. Nc |jtjjr t }n9|jtjj rt d}n|St j|S)z Translate cred exceptions into SMTP exceptions so that the protocol code which invokes C{validateFrom} can properly report the failure. z#Unauthenticated senders not allowed)r>)r<rr UnauthorizedLoginrUnhandledCredentialsr fail)r?excrZs rvebAuthenticationz+SMTP.validateFrom..ebAuthenticationDs` 99TZZ99:'/CYYtzz>>?'%JCJzz#&rwc(jS)zE Re-attempt from address validation. )r.)ignoredrrZrs rvcontinueValidationz-SMTP.validateFrom..continueValidationVs((v66rw)rgetMessageDeliveryrr r-r.portalloginr credentials Anonymousr'r&r/r{rlr)rrrZrrrrs``` rvr.zSMTP.validateFrom!s$    + 00CCEDM == $&&t}}'A'A4P P ;;[[&&  **,' F '    ? ?AQ R 7   1 2MF##rwcf|j|jj|St|)a Validate the address for which the message is destined. @type user: L{User} @param user: The address to validate. @rtype: no-argument callable @return: A C{Deferred} which becomes, or a callable which takes no arguments and returns an object implementing C{IMessage}. This will be called and the returned object used to deliver the message when it arrives. @raise SMTPBadRcpt: Raised if messages to the address are not to be accepted. )rrErrrHs rvrEzSMTP.validateToas. == $==++D1 1$rwc|j|jj|||Sd}|drd|dz}t|jj j }d|dzdz|dzdz|zdz}d ||j jtfz}d d jtt|tfz}d |zd z|zd z|zS)Nrwrs helo=sfrom s ([rd])sby %s with %s (%s)s for %s; %s s Received: s ) rrVr/rgetHostrrrrrmaprrD) rrrZr[heloStrrfrom_byfor_s rvrVzSMTP.receivedHeaderus == $==//fjI I 7$q')Gt~~557<<=47"V+d1g5 MMu$w.3g=DDrwr)rw)rsSender address accepted)NrsRecipient address accepted)3rrrrrrrYrrrcrpropertyrsetterrrrrrrr r rr r!r$rqstringrrIrr+rDr5r0r1rJrFrGrQrarrfrm state_DATArir{r.rErVryrwrvr<r<sG F EOHI [[ ( = &  9# 1 <-7 R(  $&6Gbjj            rtt  Gbjj            rtt  GK(!W"U$! W&GP(3 ()T"J 8">$@ ( Erwr<c.eZdZdZeZdZeZdZ ddZ dZ y)r>z Factory for SMTP. rNc||_yr|)r)rrs rvrzSMTPFactory.__init__s  rwctjj||}|j|_|j|_|Sr|)r ServerFactory buildProtocolrrrrrps rvrzSMTPFactory.buildProtocols5  " " 0 0t <;;rwr|) rrrrrrrr<r rrrryrwrvr>r>s' FGH Frwr>ceZdZdZdZdZddZdZdZe jfdZ dZ d Z d Zd Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZy)r=a SMTP client for sending emails. After the client has connected to the SMTP server, it repeatedly calls L{SMTPClient.getMailFrom}, L{SMTPClient.getMailTo} and L{SMTPClient.getMailData} and uses this information to send an email. It then calls L{SMTPClient.getMailFrom} again; if it returns L{None}, the client will disconnect, otherwise it will continue as normal i.e. call L{SMTPClient.getMailTo} and L{SMTPClient.getMailData} and send a new email. TNct|tr|jd}|xsd|_g|_g|_d|_g|_d|_tj||_ y)NrJrwr) rrridentitytoAddressesResultsuccessAddressesrr>rr,LineLogr+)rrlogsizes rvrzSMTPClient.__init__sZ h $w/H C !# "   <<(rwc|jr|jjd|ztjj ||y)Ns>>> )debugr+rr) LineReceiverrrs rvrzSMTPClient.sendLines3 :: HHOOGdN + ##D$/rwc|j|jdg|_|j|_|j |_yr)rr _expectedsmtpState_helo _okresponsesmtpConnectionFailed _failresponsers rvrzSMTPClient.connectionMades7  %..!66rwc4|jdd|_y)z, We are no longer connected N)rmailFilerrds rvrzSMTPClient.connectionLosts  rwcl|jtdd|jjy)Nrs(Timeout waiting for SMTP server response) sendErrorr"r+rrs rvrzSMTPClient.timeoutConnections(  ?  rwc |j|jr|jjd|zd} t |dd|_|dddk(ry|jj|dd|ddd k(ry|j |jvr6|j|j d j|j}n5|j|j d j|j}d|_g|_ |S#t $r:|jtdd||jjYywxYw) Ns<<< rerz#Invalid response from SMTP server: rrd0rf- )rrr+rror ValueErrorrr rr>rrrr)rrwhys rvrzSMTPClient.lineReceiveds1  :: HHOOGdN + D!H DI !9   ab" !9   99 &""499ejj.CDC$$TYY 4990EFC   ;  NN!9$@HHLLN   sDAEEcl|jt|||jjyr|)rrr+rrrr>s rvrzSMTPClient.smtpConnectionFaileds" 'dDHHLLNCDrwc|dkr5|jt|||jjy|j ||y)Nr)rr r+rsmtpState_msgSentrs rvsmtpTransferFailedzSMTPClient.smtpTransferFaileds9 !8 NN,T4H I  " "4 .rwcx|jd|jzt|_|j|_y)NsHELO )rrSUCCESSrsmtpState_fromrrs rvrzSMTPClient.smtpState_helos, h./ ..rwc |j|_|j|_|jA|j dt |jzdg|_|j|_y|jy)Ns MAIL FROM:r) getMailFromrrrrrCr smtpState_tor_disconnectFromServerrs rvrzSMTPClient.smtpState_from si%%' !44 :: ! MM-)DJJ*?? @!UDN#00D   & & (rwc8|jjyr|)rrrs rvsmtpState_disconnectzSMTPClient.smtpState_disconnects %%'rwct|j|_g|_g|_|j |_tdd|_d|_ |j ddS)Nrrw) iter getMailTo toAddressesrrsmtpState_toOrDatarranger lastAddressrs rvrzSMTPClient.smtpState_tos\ 01!# "22q$&&q#..rwc|jU|jj|j||f|tvr%|jj|j t |j |_|jdt|jzy#t$rM|jr,|jddg|_ |j|_ Yy|j|dcYSwxYw)NsRCPT TO:sDATArTzNo recipients accepted)rrrrrr}rrrC StopIterationrsmtpState_datarrrs rvrzSMTPClient.smtpState_toOrData$s    '  " " ) )4+;+;T4*H Iw%%,,T-=-=> E#D$4$45D  MM+ $2B2B(CC D N$$ g&"%#'#6#6 --d4LMM  Ns#B%%?C;&C;:C;ctj}|jjjj }fd}|j j|t_ j_ y)Nc<j|jyr|)rr=)r?rs rv ebTransferz-SMTPClient.smtpState_data..ebTransfer9s NN399 %rw) r) FileSenderbeginFileTransfer getMailDatartransformChunkr/finishedFileTransferrrrr)rrr>srIrs` rvrzSMTPClient.smtpState_data5sh       0 0 2DNNDDWDW X & t00*= 11rwc |j<|j||t|j|j|j g|_d|_|j dt|_|j|_ y)NsRSET) rsentMailrrrr+rrrrrrs rvrzSMTPClient.smtpState_msgSent@sm :: ! MMdC 5 568N8NPTPXPX "$  g ..rwcf|j|jddjddS)a  Perform the necessary local to network newline conversion and escape leading periods. This method also resets the idle timeout so that as long as process is being made sending the message body, the client will not time out. rs  .s ..)rreplace)rchunks rvrzSMTPClient.transformChunkOs. }}UG,44XyIIrwc:|dk7rd}nd}|j|y)Nrrr)r)rlastsentrs rvrzSMTPClient.finishedFileTransferZs u DD drwct)z< Return the email address the mail is from. NotImplementedErrorrs rvrzSMTPClient.getMailFromc "!rwct)z5 Return a list of emails to send to. rrs rvrzSMTPClient.getMailToirrwct)z Return file-like object containing data of message to be sent. Lines in the file should be delimited by '\n'. rrs rvrzSMTPClient.getMailDataos "!rwct|tr|js|jy|j ddy)a2 If an error occurs before a mail message is sent sendError will be called. This base class method sends a QUIT if the error is non-fatal and disconnects the connection. @param exc: The SMTPClientError (or child class) raised @type exc: C{SMTPClientError} rN)rrisFatalrrrrs rvrzSMTPClient.sendErrorws2 c? +CKK  & & (  % %b$ /rwct)a Called when an attempt to send an email is completed. If some addresses were accepted, code and resp are the response to the DATA command. If no addresses were accepted, code is -1 and resp is an informative message. @param code: the code returned by the SMTP Server @param resp: The string response returned from the SMTP Server @param numOk: the number of addresses accepted by the remote host. @param addresses: is a list of tuples (address, code, resp) listing the response to each RCPT command. @param log: is the SMTP session log r)rrr>numOk addressesr+s rvrzSMTPClient.sentMails "!rwcjtdd|_|j|_|j dy)NrrsQUIT)rrrrrrs rvrz SMTPClient._disconnectFromServers)q$44 grw) )rrrrrrrrrr connectionDonerrrrrrrrrrrrrrrrrrrrryrwrvr=r=s  EG )07%-$;$; (TE/ / )(/E" 2 / J" " "0 ""rwr=ceZdZdZdZdZdZdZdZddZ dZ dZ ddZ dd Z dd Zdd Zdd Zdd ZddZdZdZdZdZdZdZdZdZdZdZdZy)r9a  A client for sending emails over ESMTP. @ivar heloFallback: Whether or not to fall back to plain SMTP if the C{EHLO} command is not recognised by the server. If L{requireAuthentication} is C{True}, or L{requireTransportSecurity} is C{True} and the connection is not over TLS, this fallback flag will not be honored. @type heloFallback: L{bool} @ivar requireAuthentication: If C{True}, refuse to proceed if authentication cannot be performed. Overrides L{heloFallback}. @type requireAuthentication: L{bool} @ivar requireTransportSecurity: If C{True}, refuse to proceed if the transport cannot be secured. If the transport layer is not already secured via TLS, this will override L{heloFallback}. @type requireAuthentication: L{bool} @ivar context: The context factory to use for STARTTLS, if desired. @type context: L{IOpenSSLClientConnectionCreator} @ivar _tlsMode: Whether or not the connection is over TLS. @type _tlsMode: L{bool} TFNc`tj|g|i|g|_||_||_yr|)r=rauthenticatorssecretcontext)rrcontextFactoryargskws rvrzESMTPClient.__init__s0D.4.2.  % rwc|dk(r(tjdtd|jSt |j j d|)NtlsModeStlsMode attribute of twisted.mail.smtp.ESMTPClient is deprecated since Twisted 13.0rWcategory stacklevelz instance has no attribute )warningswarnDeprecationWarning_tlsModerrr)rnames rv __getattr__zESMTPClient.__getattr__sQ 9  MM3+   ==  NN++ rwct|dk(r$tjdtd||_y||j|<y)NrrrWr)rrrrr)rr r=s rv __setattr__zESMTPClient.__setattr__s8 9  MM3+   "DM"'DMM$ rwcl|jtdd|jjy)a Fail because authentication is required, but the server does not support ESMTP, which is required for authentication. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} s,Server does not support ESMTP AuthenticationN)rrr+rrs rvesmtpEHLORequiredzESMTPClient.esmtpEHLORequireds*  H$((,,.  rwcg}|jD]/}|j|jj1ddj |z}|j t dd|z|jjy)a Fail because authentication is required, but the server does not support any schemes we support. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} s[%s]s, rs8Server does not support Client Authentication schemes %sN) rrgetNamerrrrr+r)rrr>tmpaauths rvesmtpAUTHRequiredzESMTPClient.esmtpAUTHRequiredsz$$ ,A JJqyy{((* + ,C(  ORVV   rwcl|jtdd|jjy)a` Fail because TLS is required and the server does not support it. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} rs:Server does not support secure communication via TLS / SSLN)rr$r+rrs rvesmtpTLSRequiredzESMTPClient.esmtpTLSRequireds+  Q   rwcl|jt|d|jjy)a[ Fail because the TLS handshake wasn't able to be completed. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} s(Could not complete the SSL/TLS handshakeN)rr1r+rrs rvesmtpTLSFailedzESMTPClient.esmtpTLSFailed%s*  Etxx||~  rwcl|jt|||jjy)aM Fail because the authentication was rejected. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} N)rrr+rrs rvesmtpAUTHDeclinedzESMTPClient.esmtpAUTHDeclined7s$ (tTXX\\^DErwcl|jtdd|jjy)ab Fail because the server sent a malformed authentication challenge. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} r'sRLogin failed because the SMTP Server returned a malformed Authentication ChallengeNrrr+rrs rvesmtpAUTHMalformedChallengez'ESMTPClient.esmtpAUTHMalformedChallengeEs.  M    rwcl|jt|||jjy)aP Fail because of some other authentication error. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} Nrrs rvesmtpAUTHServerErrorz ESMTPClient.esmtpAUTHServerErrorZs$ *4txx||~FGrwc:|jj|y)a Registers an Authenticator with the ESMTPClient. The ESMTPClient will attempt to login to the SMTP Server in the order the Authenticators are registered. The most secure Authentication mechanism should be registered first. @param auth: The Authentication mechanism to register @type auth: L{IClientAuthentication} implementor @return: L{None} N)rr)rrs rvregisterAuthenticatorz!ESMTPClient.registerAuthenticatorhs ""4(rwctj|j|_tj ||j |_y)zp Called when a connection has been made, and triggers sending an C{EHLO} to the server. N)r providedByrrr=resmtpState_ehlorrs rvrzESMTPClient.connectionMadevs6 &00@ !!$'//rwc&t|_|j|_|j|_|j rd}n |j}|jr|js|s|j|_|jd|jzy)a Send an C{EHLO} to the server. If L{heloFallback} is C{True}, and there is no requirement for TLS or authentication, the client will fall back to basic SMTP. @param code: The server status code from the most recently received server message. @type code: L{int} @param resp: The server status response from the most recently received server message. @type resp: L{bytes} @return: L{None} FsEHLO N) rresmtpState_serverConfigrrrrrequireTransportSecurity heloFallbackrequireAuthenticationrrr)rrr>needTLSs rvr%zESMTPClient.esmtpState_ehlost"!77!33 ==G33G   T%?%?!%!4!4D  h./rwci}|jD]6}|jdd}t|dkDr |d||d</d||d<8|j|||y)z Handle a positive response to the I{EHLO} command by parsing the capabilities in the server's response and then taking the most appropriate next step towards entering a mail transaction. Nrdr)rrrtryTLS)rrr>itemsrr3s rvr'z#ESMTPClient.esmtpState_serverConfigsj OO% #D 4#A1vzdad "ad  # D$&rwc(|j}|jxrd|v}|j}|s|s|s|j|||y|rr.hasTLScanTLSmustTLSs rvr-zESMTPClient.tryTLSsJ6+"6// &G   dD% 0 !UDN#77D !%!4!4D  MM+ &  ! ! #rwc |jj|jd|_|j||y#t$r(t j |jdYCwxYw)z Handle a positive response to the I{STARTTLS} command by starting a new TLS session on C{self.transport}. Upon success, re-handshake with the server to discover what capabilities it has when TLS is in use. Tr:N) rstartTLSrrrOr+r?rr%rs rvr2zESMTPClient.esmtpState_starttlss^ % NN # #DLL 1 DM T4(  % GGI    $ %s,A.A21A2c|jr;|jdr)|dj}i}|D]}d||j<|jD]}|j j}||vs&||_|dk(r{|j|_|j|_ dg|_ tj|j j|jd} |jd|| fzydg|_ |j |_|j"|_ |jd|zy|j$r|j'y|j||y)NAUTHrdPLAINs AUTH %s %sNsAUTH )rgetrrrr _authinforr_esmtpState_plainAuthrrbase64 b64encodechallengeResponseresmtpState_challenger r*r) rrr>r.schemes tmpSchemesrrr challenges rvr1zESMTPClient.authenticates] ;;599W-Gn**,GJ *() 1779% *(( yy{((*:%%&DNx'+/+>+>(-1-G-G**-$*$4$4 NN<rBrr)rrr>rFs rvr?z!ESMTPClient._esmtpState_plainAuths^..!33$$T^^%E%EdkkST%UV  ny01rwc<|j|j|yr|) _authResponser>rs rvrCz ESMTPClient.esmtpState_challenge#s 4>>40rwc|j|_ tj|}|j |j |}ddg|_|j|_|jtj|y#tj$r6|jd|j|_|j|_YywxYw)Nr;r<*)rrr@ b64decoderBrrsmtpState_maybeAuthenticatedrrrAbinasciiErrorr)rrrFr>s rvrIzESMTPClient._authResponse&s!33 2((3I))$++yAD!3ZDN#@@D  MM&**40 1~~ B MM$ #??D !%!A!AD   BsBAC  C cp|dk(r|`|j||y|j|j|y)z Called to handle the next message from the server after sending a response to a SASL challenge. The server response might be another challenge or it might indicate authentication has succeeded. r;N)r>rrIrs rvrMz(ESMTPClient.smtpState_maybeAuthenticated5s6 3;   d +   t~~t 4rwr|)rN)rrrrr)r*r(rrrr r rrrrrrr r"rr%r'r-r2r1r?rCrIrMryrwrvr9r9s2L!$GH& $ ( & 8 ( $ F * H )00@' 1$f)&%,N21 2 5rwr9cfeZdZdZdZdZdZddZdZdZ dZ dZ dZ d Z d Zd Zd Zd ZdZy)r8NFc`tj||i}||_d|_||_y)NF)r<r challengers authenticatedctx)rchalrs rvrzESMTP.__init__Ks/ d <D"!rwctj|tj|j|_|j xr|j du|_yr|)r<rrr$r canStartTLSrUrs rvrzESMTP.connectionMadeSsC D!(33DNNC++F1Erwc2tj|dzS)Ns ESMTP)r<rrs rvrzESMTP.greetingXs}}T"Y..rwcdt|jji}|jr|jsd|d<|S)z SMTP service extensions @return: the SMTP service extensions that are supported. @rtype: L{dict} with L{bytes} keys and a value of either L{None} or a L{list} of L{bytes}. r9Nr0)rrSkeysrX startedTLS)rexts rv extensionszESMTP.extensions[s@T--22456   DOO#C  rwct|}tj||}|t|d|j zd}|S)Next_)r.r<r rr)rrr2s rvr zESMTP.lookupMethodhsAw'   dG , 9fw}}6=Arwcg}|jjD]B\}}|*|s |j|dzdj|z2|j|Ddj|S)N r)r^r.rr)rrcvs rvlistExtensionszESMTP.listExtensionspsj OO%++- DAq}HHQX ! 45  zz!}rwc(|jjj}t|ts|j d}||f|_d|_g|_|jd|jdz|zdz|jzy)Nrrr s, nice to meet you ) rrrrrrrrrrrf)rrrs rvdo_EHLOz ESMTP.do_EHLO|s~~%%',,$&;;v&DD\    **%%' ( rwc|jr|jddy|jrK|jr?|jdd|jj |jd|_y|jddy)Nr&sTLS already negotiatedrsBegin TLS negotiation nowTsTLS not available)r\rrUrXrr7rs rv ext_STARTTLSzESMTP.ext_STARTTLSsb ?? MM#8 9 XX$** MM#; < NN # #DHH -"DO MM#3 4rwc|jr|jddy|jdd}|jj |dj d}|s|jddyt |_||_t|dkDr|j|d}nd}|j|y)Nr&sAlready authenticatedrdrcyr|ryryrwrvrz ESMTP.ext_AUTH..srwis Unrecognized authentication type) rTrrrSr=rrrrwr getChallenge state_AUTH)rrr rVs rvext_AUTHzESMTP.ext_AUTHs    MM#7 8  4#Ct##E!HNN$4lCE MM#B C   u:>    8DD rwc@tj||}d|_|S)zz Save the state resulting from a successful cred login and mark this connection as authenticated. T)r<r{rT)r loginInforrs rv_cbAuthenticatedzESMTP._cbAuthenticateds# 00yA! rwcd|_|jtjjr|j ddyt j|d|j ddy)a Handle cred login errors by translating them to the SMTP authenticate failed. Translate all other errors into a generic SMTP error code and log the failure for inspection. Stop all errors from propagating. @param reason: Reason for failure. NisAuthentication failedzSMTP authentication failurer:r;)rFr<rr r~rr+r?rs rv_ebAuthenticatedzESMTP._ebAuthenticatedsN << 44 5 MM#7 8 GGF9 : MM#U Vrwcjjddt_y|Bjj }t j|}jd|y|dk(r%jddd_t_y t j|}jj|jjrBjj }t j|}jd|yt_jjjdtt }|j#j$|j#fd |j'j(y#ttjf$r'jddd_t_YywxYw) a+ Handle one step of challenge/response authentication. @param response: The text of a response. If None, this function has been called as a result of an AUTH command with no initial response. A response of '*' aborts authentication, as per RFC 2554. Nrjs Temporary authentication failurer<rKr'sAuthentication aborteds'Syntax error in parameters or argumentsc(jddS)Nr;sAuthentication successful.r)ignrs rvrz"ESMTP.state_AUTH..s c+HIrw)rrrrrwrnr@rArL TypeErrorrNrO setResponsemoreChallengesrr'r&rlrs addErrbackru)rresponserFencodeduncodedcodedrrs` rvrozESMTP.state_AUTHs ;;  MM#B CDI   446I&&y1G MM#w '  t  MM#8 9"DODI  &&x0G ##G, ?? ) ) +446I$$Y/E MM#u %  "" OOT#:>*  MM#I J"DODI   sF--=G-,G-r)rrrrUrXr\rTrrrr^r rfrhrkrprsruroryrwrvr8r8DsT CKJM"G /   (5* W11rwr8c2eZdZdZdZdZdZdZdZdZ y) r7zi Utility class for sending emails easily. Use with SMTPSenderFactory or ESMTPSenderFactory. rch|js&d|_t|jjSyNrd)donerfactoryr7rs rvrzSenderMixin.getMailFroms(yyDIt||--. .rwc.|jjSr|)rtoEmailrs rvrzSenderMixin.getMailTo s||###rwc.|jjSr|)rfilers rvrzSenderMixin.getMailDatas||   rwc&tj|||jjdk\s*|jsV|j dk\r|j dks7d|j_|jjj|yyy)NrirT) r=rrretriesretryr sendFinishedrrerrbackrs rvrzSenderMixin.sendErrorsmT3' <<  1 $ 388s?sxx#~(,DLL % LL   ' ' ,8F rwcd|j_|tvrg}|D]9\}}} |tvs|j|dzt d|fzzdz| z;|j|j t ||dj||} |jjj| y|jjj||fy)NTr9z%03drbr) rrrrr/rrrrrrcallback) rrr>rrr+errlogracodearesprs rvrzSenderMixin.sentMail s$( ! w F&/ "eU'MMu }Vuh5F'GG$NQVV  MM'#'') $#D$ 60BINC LL   ' ' , LL   ( (%); }. c@tj|ddg|_y)Ns Password:s Username:) _lcredentialsr challengesrs rvrzLOGINCredentials.__init__st$'6rwN)rrrrrryrwrvrrs 7rwrc eZdZdZdZddZy)r3c||_yr|rHrs rvrzPLAINAuthenticator.__init__s  rwcy)Nr:ryrs rvrzPLAINAuthenticator.getNamesrwcz|dk(r"|jdz|jzdz|zSd|jzdz|zS)Nrdr)rrrVs rvrBz$PLAINAuthenticator.challengeResponsesD 1999u$tyy0586A A499$u,v5 5rwN)rd)rrrrrrBryrwrvr3r3s6rwr3c(eZdZdZdZddZdZdZy)r:TNcd|_||_|jdd|_||j }t j |||g|i||jy)Nrhostname)r)usernamepop _hostname_getContextFactoryr9r_registerAuthenticators)rrrrrrs rvrzESMTPSender.__init__s_   D1  !!446NT6>GDGBG $$&rwc|jt|j|jt|j|jt |jyr|)r"rrrr3rs rvrz#ESMTPSender._registerAuthenticatorssJ ""#=dmm#LM ""#5dmm#DE ""#5dmm#DErwc|j |jS|jy ddlm}||j}|S#t$rYywxYw)Nr)optionsForClientTLS)rrtwisted.internet.sslr ImportError)rrrs rvrzESMTPSender._getContextFactorysT << #<<  >> !  @*$..9GN   sA A  A r|)rrrr*r(rrrryrwrvr:r:s # 'F rwr:c0eZdZdZeZ ddZdZy)r;z Utility factory for sending emails easily. @type currentProtocol: L{ESMTPSender} @ivar currentProtocol: The current running protocol as made by L{buildProtocol}. Nc tj|||||||||_||_| |_| |_| |_| |_| |_yr|) r@rrpassword_contextFactory _heloFallback_requireAuthentication_requireTransportSecurityr)rrrr7rrrrrrr)r*r(rs rvrzESMTPSenderFactory.__init__sX "" )WdHgw !   -)&;#)A&!rwc|j|j|j|j|j|j dzdz|j }|j|_|j|_ |j|_ ||_ |j|_||_|j j#|j$|S)a) Build an L{ESMTPSender} protocol configured with C{heloFallback}, C{requireAuthentication}, and C{requireTransportSecurity} as specified in L{__init__}. This sets L{currentProtocol} on the factory, as well as returning it. @rtype: L{ESMTPSender} rW)r)r rrrrrrrr)rr*rr(rrrrrrrrs rvrz ESMTPSenderFactory.buildProtocols MM MM MM  KK LL1 q ^^  ++"&"="=%)%C%C" LL   D001rw)rgNNFTTN)rrrrr:r rrryrwrvr;r;s/H"!%"6rwr;Fc t|dstt|}fd} tj| } t |t r|jd}t |t r|jd}|} t | t s t| } t|||||| d| | |  |t|_ |j||| S)aR Send an email. This interface is intended to be a replacement for L{smtplib.SMTP.sendmail} and related methods. To maintain backwards compatibility, it will fall back to plain SMTP, if ESMTP support is not available. If ESMTP support is available, it will attempt to provide encryption via STARTTLS and authentication if a secret is provided. @param smtphost: The host the message should be sent to. @type smtphost: L{bytes} @param from_addr: The (envelope) address sending this mail. @type from_addr: L{bytes} @param to_addrs: A list of addresses to send this mail to. A string will be treated as a list of one address. @type to_addrs: L{list} of L{bytes} or L{bytes} @param msg: The message, including headers, either as a file or a string. File-like objects need to support read() and close(). Lines must be delimited by '\n'. If you pass something that doesn't look like a file, we try to convert it to a string (so you should be able to pass an L{email.message} directly, but doing the conversion with L{email.generator} manually will give you more control over the process). @param senderDomainName: Name by which to identify. If None, try to pick something sane (but this depends on external configuration and may not succeed). @type senderDomainName: L{bytes} @param port: Remote port to which to connect. @type port: L{int} @param username: The username to use, if wanting to authenticate. @type username: L{bytes} or L{unicode} @param password: The secret to use, if wanting to authenticate. If you do not specify this, SMTP authentication will not occur. @type password: L{bytes} or L{unicode} @param requireTransportSecurity: Whether or not STARTTLS is required. @type requireTransportSecurity: L{bool} @param requireAuthentication: Whether or not authentication is required. @type requireAuthentication: L{bool} @param reactor: The L{reactor} used to make the TCP connection. @rtype: L{Deferred} @returns: A cancellable L{Deferred}, its callback will be called if a message is sent to ANY address, the errback if no message is sent. When the C{cancel} method is called, it will stop retrying and disconnect the connection immediately. The callback will be called with a tuple (numOk, addresses) where numOk is the number of successful recipient addresses and addresses is a list of tuples (address, code, resp) giving the response to the RCPT command for each address. readcd_jr%jjjyj y)z Cancel the L{twisted.mail.smtp.sendmail} call, tell the factory not to retry and disconnect the connection. @param d: The L{defer.Deferred} to be cancelled. TN)rrrabortConnection disconnect)rIrrs rvcancelzsendmail..cancel|s< $  " "  # # - - = = ?  "rwzutf-8T)r)r*r(r) hasattrrrr Deferredrrrr r;r/r connectTCP)smtphost from_addrto_addrsrsenderDomainNameportr rrr*r(rrI tlsHostnamerrs @@rvr6r6/sR 3 eCj! # vA(C ??7+(C ??7+K k3 ' ,    3!9 G#&'78"""8T7;I Hrwcg}t|D][}t|}|dk(s|dk(s |dks|dkDr|jtd|dA|jt |f]dj |t |fS)N+=!~02Xrw)r-ordrr/rrr)rerrorsrcchos rvrIrIs Al" G 9c QVq3w HH]Qqg;/ 0 HHUA4[ ! " HHQKQ  rwc g}d}|t|kr|||dzdk(r= |jttt ||dz|dzd|dz }n4|jt |||dzjd|dz }|t|krdj|t|fS#t $r#|jt |||dzYwxYw)z Decode the xtext-encoded string C{s}. @param s: String to decode. @param errors: codec error handling scheme. @return: The decoded string. rrd+rerJr) rrchrrorrrrr)rrrcrzs rvrHrHs A A c!f* QQ<4  ,SqQQ'7!8"=>? FA HHU1QQ<(//8 9 FA c!f* GGAJA   ,Qq1q5\*+ ,s6B::)C&%C&ceZdZddZy)rEct|Sr|)rHrrrs rvrzxtextStreamReader.decode ArwNstrictrrrrryrwrvrErErwrEceZdZddZy)rFct|Sr|)rIrs rvrzxtextStreamWriter.decoderrwNrrryrwrvrFrFrrwrFc:|dk(rttttfSy)Nxtext)rIrHrErF)r s rvrGrGs wl,=?PQQrwrr|)yrr@rNrrrsocketrhr email.utilsriortypingrzope.interfacertwistedrtwisted.copyrightrtwisted.internetr r r r twisted.internet._idnar twisted.internet.interfacesrrtwisted.mail._credrrrrtwisted.mail._exceptrrrrrrrrrrrrrr r!r"r#r1r$twisted.mail.interfacesr%r&r'r(r2twisted.protocolsr)r*twisted.pythonr+r,twisted.python.compatr-r.r/twisted.python.runtimer0__all__isMacOSX gethostnamerrgetfqdndictfromkeysrrrDrAr~rBrCrrrrr4r5LineOnlyReceiver TimeoutMixinr<rr>rr=r9r8r7r? ClientFactoryr@r3r:r;r6codecsrIrH StreamReaderrE StreamWriterrFrGregisterryrwrvrs  !&)<<,D ( .$HH+1 l8!f  "))'2Gfnn%%g.G --c3 (9x}-*4*0t+p p f% % PkE5 ! !8#8#8kE\(((,A##X%:%:AHc5*c5L t1Dt1n5=5=pjn..nb 7} 7 "# 6 6$ 6"+{"J?*?N   "x v! .++ ++ R  rw