Ϫf8c dZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlmZddlmZddlmZmZddlmZddlZddlZddlZddlZddlZddlZddlZddl Zddl!Zddlm"Z"m#Z#ddl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*dd l+m,Z,dd l-m.Z.m/Z/m0Z0m1Z1dd l2m3Z3m4Z4m5Z5dd l6m7Z7m8Z8dd l!m9Z9ddl:m;Z;ddlZ>m?Z?ddl@mAZAddlBmCZCmDZDddlEmFZFddlGmHZHddlImJZJeeHdk7dGddeJZKeeHdk7dGddeJZLeeHdk7dGddeJZMeeHdk7dGddeJZNeeHdk7dGdd eJZOeeHdk7dGd!d"eJZPeeHdk7dGd#d$eJZQeeHdk7dGd%d&e#jjZTGd'd(ZUeeHdk7dGd)d*eJeUZVeeHdk7dGd+d,eJeUZWeeHdk7dGd-d.eJZXeeHdk7dGd/d0eJZYeeHdk7dGd1d2eJZZee#jFjGd3d4Z\eeHdk7dGd5d6eJZ]eeHdk7dGd7d8eJZ^Gd9d:e8jZ`eeHdk7dGd;deJZbGd?d@ZceeHdk7dGdAdBeJZdeeHdk7dGdCdDeJZeddEl:mfZfmgZgmhZhGdFdGegjZjdHZkdIZleeHdk7dGdJdKeJZmeeHdk7dGdLdMeJZnGdNdOZoeeHdk7dGdPdQeJZpGdRdSZqeeHdk7dGdTdUeJZrGdVdWZsGdXdYe#jjZvGdZd[e#jjZxGd\d]ZyeeHdk7dGd^d_eJZzGd`daZ{GdbdcZ|GdddeZ}eeHdk7dGdfdgeJZ~y)hz. Tests for large portions of L{twisted.mail}. N)md5)skipIf) Interface implementer) verifyClass)credmail)addressdefer interfacesprotocolreactortask)Deferred)CannotListenErrorDNSLookupError ProcessDoneProcessTerminated)LineSendingProtocolMemoryReactorClockStringTransport)pop3smtp)_AttemptManager)dns) Record_CNAME Record_MXRRHeader) DNSNameError)failurelog)FilePath) platformType)TestCaseposixz twisted.mail only works on posixc\eZdZeej dk\ddZdZdZdZ dZ y) DomainWithDefaultsTestsnot ported to Python 3c vtdDcic]}||dz }}tjj|d}|jt |d|jt t |t td|jt |jt t |t |j}|j|j|tdDcgc] }||dzf c}t |j}|j|j|t tdd|j}|j|j|tdDcgc] }||dzf c}|j}|j|j|t tddtdD]Q}|j|||dz|j|j||dz|j||vS|d=|d=|d=|jt |d|j|dd|j|dd|j|dd|jddd d |jt |d|j|d d|j|d d|j|d d |j!|jt |d|j|j#ddd|j|dd|j|j%d|jt |d|j'}|j|j(|j(|j|j*|j*ycc}wcc}wcc}w)N Default*)abcr5r6r7rkeyvalue)r8r9)ranger DomainWithDefaultDict assertEquallenlistiteriterkeys iteritemssort itervaluesitemsvaluesget assertTrueupdateclear setdefaultpopitemcopydomainsdefault)selfxdrDrEdcopys =/usr/lib/python3/dist-packages/twisted/mail/test/test_mail.py testMethodsz#DomainWithDefaultsTests.testMethods?sO %b *1QBY * * II + +Ay 9 Q$ d1gU2Y8 ajjl+T$q'];Q[[]#  eBi @!QV @Aalln%  eBm!45   eBi @!QV @A  eBm!45r $A   QqT1r6 *   QUU1Xq2v . OOAF # $ aD!A$! Q# 1y) 1y) 1y) t"3/0 Q$ 3& 3$ 3%   Q# eW5w? 57+ &67 Q# EMM2 EMM2i +!A!As P, P1 'P6 ctjjid}|j|jj||d|d<|jt ddi||y)a Assert that the class name of a L{mail.mail.DomainWithDefaultDict} instance and the string-formatted underlying domain dictionary both appear in the string produced by the given string-returning function. @type stringifier: one-argument callable @param stringifier: either C{str} or C{repr}, to be used to get a string to make assertions against. r-r9r8N)r r;assertIn __class____name__str)rO stringifierdomains rS_stringificationTestz,DomainWithDefaultsTests._stringificationTestws_00Y? f&&//V1DEu  c5'*+[-@Ac.|jty)z L{DomainWithDefaultDict.__str__} should return a string including the class name and the domain mapping held by the instance. N)r\rYrOs rStest_strz DomainWithDefaultsTests.test_strs !!#&r]c.|jty)z L{DomainWithDefaultDict.__repr__} should return a string including the class name and the domain mapping held by the instance. N)r\reprr_s rS test_reprz!DomainWithDefaultsTests.test_reprs !!$'r]c@tjjid}|jdd}|j|jg}|j dt ||j t|dd|j ||ddy) z, has_key is now deprecated. r-anythingzotwisted.mail.mail.DomainWithDefaultDict.has_key was deprecated in Twisted 16.3.0. Use the `in` keyword instead.rcategorymessageN)r r;has_key flushWarningstest_has_keyDeprecationr<r=DeprecationWarning)rOsutrhwarningss rSrkz/DomainWithDefaultsTests.test_has_keyDeprecationsii--b)< J ? %%t'C'C&DE CM* +Xa[-DE (1+i"89r]N) rX __module__ __qualname__rsys version_inforTr\r`rcrkr3r]rSr'r'=s> C   $&>?53@53n B'(:r]r'c$eZdZdZdZdZdZy) BounceTestscJtjj|_yN)r BounceDomainr[r_s rSsetUpzBounceTests.setUpsii,,. r]cn|jtj|jjdy)Nzany user) assertRaisesr AddressErrorr[existsr_s rS testExistszBounceTests.testExistss$ $++T[[-?-?Lr]c\|j|jjdddy)Nzrandom q emailerr F)r<r[ willRelayr_s rS testRelayzBounceTests.testRelays% ../A:NPUVr]c|jjdd|jtj|jj dy)Nbobpassword)r[addUserrzr SMTPBadRcptr|r_s rS testAddUserzBounceTests.testAddUsers8 E:. $**DKK,>,>Fr]N)rXrorprxr}rrr3r]rSrtrts/MWGr]rtceZdZdZdZy)BounceWithSMTPServerTestsz_ Tests for L{twisted.mail.mail.BounceDomain} with L{twisted.mail.smtp.SMTPServer}. ctjj}tjj}|jd|tjj |}|j d}tjj|dd}||_t}|j||jd|jd|jd|jd|j|j|jd|j|j!j#j%ddd y) zo Incoming emails to a SMTP server with L{twisted.mail.mail.BounceDomain} are rejected. sfoo.comNs HELO baz.netsMAIL FROM:sRCPT TO:sQUITs s(550 Cannot receive for specified address)r MailServicerw addDomain protocols SMTPFactory buildProtocolSMTPDomainDeliverydeliveryrmakeConnection lineReceivedrG disconnectingconnectionLostr<r9stripsplit)rOservicer[factoryr deliverer transports rS test_rejectedz'BounceWithSMTPServerTests.test_rejecteds, ))'')'')*f-..,,W5((.NN55gtTJ %#%  *o.6767g&  //0%  OO  # # % + +G 4R 8 7 r]N)rXrorp__doc__rr3r]rSrrs   r]rc*eZdZdZdZdZdZdZy)FileMessageTestsc`|j|_|j|_t|jd|_|j |jj tjj|j|j|j|_ y)Nwb) mktempnamefinalopenf addCleanupcloser FileMessagefpr_s rSrxzFileMessageTests.setUpshKKM [[] dii&  %))'' 4::Fr]ch|jjj|jSrv)r eomReceived addCallback _cbFinalNamer_s rS testFinalNamezFileMessageTests.testFinalNames&ww""$001B1BCCr]c|j||j|j|jj|j t jj|jyrv) r<rrGrclosed assertFalseospathr|rrOresults rSrzFileMessageTests._cbFinalNamesI ,  &  23r]c2d}|jD]}|jj||jjt |j d5}|j |j|dddy#1swYyxYw)N"first line second line third line rb) splitlinesrrrrrr<read)rOcontentsliners rS testContentszFileMessageTests.testContentss|;'') 'D GG  & '  $**d # 1q   QVVXx 0 1 1 1s #!B  Bc|d}|jD]}|jj||jj|j t j j|j|j t j j|jy)Nfirst line second line ) rrrrrrrr|rrrOrrs rStestInterruptedz FileMessageTests.testInterrupteds/'') 'D GG  & '    23  34r]N)rXrorprxrrrrr3r]rSrrsGD4 15r]rc.eZdZdZdZdZdZdZdZy)MaildirMessageTestszL Tests for the file creating by the L{mail.maildir.MaildirMessage}. c|j|_|j|_d|_t |jd|_|j |j jtjj|j|j |j|j|_ y)z3 Create and open a temporary file. suser@example.comrN) rrrr rrrrr maildirMaildirMessagerr_s rSrxzMaildirMessageTests.setUpszKKM [[] * dii&  %,,-- LL$&&$))TZZ r]cLtj|jddS)zk Search for the final file path. @rtype: L{str} @return: Final file path. z ,S=[0-9]*r)globrr_s rS _finalNamezMaildirMessageTests._finalNames#yyDJJ (<=tyyI LL ' ' )  1h&<&<=> (<=tyyI LL ( ( *  1h&<&<=> (<=tzzJr]c>t}t}||jjd<||jjd<|j|jj d|u|j|jj |uy)Nr[)objectrportalsrG lookupPortal defaultPortal)rOo1o2s rS testPortalszMailServiceTests.testPortalsRsv X X)+ X&#% R   11(;rAB  224:;r]N)rXrorprxrrr3r]rSrr@s/ K ,,00%@ GOOA.0BCr]ctjjdg}|jd|j |j dd|j |j dgy)z L{StringListMailbox.deleteMessage} marks a message for deletion causing further requests for its length to return 0. rrN)r rr deleteMessager<rrs rStest_deleteMessagez)StringListMailboxTests.test_deleteMessages^ ,,00%9a  --a0!4 --/!5r]c tjjdg}|jd|j |j |j dd|j |j dgy)z L{StringListMailbox.undeleteMessages} causes any messages marked for deletion to be returned to their original state. rrr)N)r rrrundeleteMessagesr<rrs rStest_undeleteMessagesz,StringListMailboxTests.test_undeleteMessagessj ,,00%9a   " --a0!4 --/!5r]c*tjjdg}|jd|j |j |j |jdd|j |jdgy)zy L{StringListMailbox.sync} causes any messages as marked for deletion to be permanently deleted. rrN)r rrrsyncrr<rrs rS test_syncz StringListMailboxTests.test_syncss ,,00%9a    " --a0!4 --/!5r]N)rXrorprrrrrqrrrrrrr r3r]rSrr\st 5< C   $&>?H@H C   $&>?D@D6 6 6r]rc*eZdZdZdZdZdZdZdZy)&FailingMaildirMailboxAppendMessageTaskTc||jrtj|||Sttj dNzFaked Permission Problem) _openstaterrOSErrorerrnoEPERM)rOfnattrmodes rSosopenz-FailingMaildirMailboxAppendMessageTask.osopens. ??772tT* *%++'AB Br]cz|jrtj||Sttj d)NzFaked Space problem) _writestaterwriterrENOSPC)rOfhdatas rSoswritez.FailingMaildirMailboxAppendMessageTask.oswrites.   88B% %%,,(=> >r]cz|jrtj||Sttj dr) _renamestaterrenamerrr)rOoldnamenewnames rSosrenamez/FailingMaildirMailboxAppendMessageTask.osrenames.   99Wg. .%++'AB Br]N) rXrorprrrrrr#r3r]rSr r s$JKLC ? Cr]r ceZdZdZdZy)_AppendTestMixinz Mixin for L{MaildirMailbox.appendMessage} test cases which defines a helper for serially appending multiple messages to a mailbox. cgfd}tj|j}|jfd|S)z Deliver the given messages one at a time. Delivery is serialized to guarantee a predictable order in the mailbox (overlapped message deliver makes no guarantees about which message which appear first). c3|KD]2}j|}|jj|4ywrv) appendMessagerappend)mrQmboxmessagesresultss rSr)z0_AppendTestMixin._appendMessages..appends; &&q) gnn- s9<cSrvr3)ignoredr-s rSz2_AppendTestMixin._appendMessages..sgr])r cooperatewhenDoner)rOr+r,r)rQr-s `` @rS_appendMessagesz _AppendTestMixin._appendMessagess<   NN68 $ - - / -.r]N)rXrorprr3r3r]rSr%r%s  r]r%cbeZdZdZdZdZd dZeejdk\ddZ d Z y) MaildirAppendStringTestsO Tests for L{MaildirMailbox.appendMessage} when invoked with a C{str}. c|j|_tjj |jyrvrrQr rinitializeMaildirr_s rSrxzMaildirAppendStringTests.setUp% &&tvv.r]cP|jd}|j|tS)NTEST)r( assertFailure Exception)rOr/r+rQs rS_appendz MaildirAppendStringTests._appends%   v &!!!Y//r]Nc|G|jt|jd|jj||j_|G|jt|jd|jj||j_|H|jt|jd|jj ||j_yy)a Change the behavior of future C{rename}, C{write}, or C{open} calls made by the mailbox C{mbox}. @param rename: If not L{None}, a new value for the C{_renamestate} attribute of the mailbox's append factory. The original value will be restored at the end of the test. @param write: Like C{rename}, but for the C{_writestate} attribute. @param open: Like C{rename}, but for the C{_openstate} attribute. Nrrr)rsetattr AppendFactoryrrr)rOr/r+r rrs rS _setStatez"MaildirAppendStringTests._setStates   OO""""//   /5D   +   OO""""..   .3D   *   OO++\4;M;M;X;X -1D   ) r]r(r*cJtjj|j}t|_|j |tddDcgc]}d|z c}}|j|jdgdz|j|j||Scc}w) L{MaildirMailbox.appendMessage} returns a L{Deferred} which fires when the message has been added to the end of the mailbox. rf XNr,) r rMaildirMailboxrQr rBr3r:rr< _cbTestAppend)rOr+irQs rS test_appendz$MaildirAppendStringTests.test_appends ||**4662C  q"'FAa'F G d&& 4 d(($/(Gs B c |jt|jd|jtdDcgc]*}t|j |j ,c}t tdd|jd|d|jd|}|j|j|dd|j|j||j|j|dd |j|j||j|j|d |Scc}w) Check that the mailbox has the expected number (ten) of messages in it, and that each has the expected contents, and that they are in the same order as that in which they were appended. r,rfrFNF)r T)r r)rr)r) r<r=rr:rrr>rCr?r)rOr/r+rJrQs rSrIz&MaildirAppendStringTests._cbTestAppends T..0126 5:2Y ?S#((* + ?eArlAS  tT%0 LLt $ dnnd4u E dllD) dnnd$U C dllD) dnnd 6 @s/E)NNN) rXrorprrxr?rCrrqrrrKrIr3r]rSr5r5sD/0!1F C   $&>? @ r]r5cTeZdZdZdZeejdk\ddZdZ y)MaildirAppendFileTestsr6c|j|_tjj |jyrvr8r_s rSrxzMaildirAppendFileTests.setUp8r:r]r(r*ctjj|j}g}t ddD]h}t j }|jd|z|jdd|j||j|jj|j||}|j|j||S)rErfrFrGr)r rrHrQr:tempfile TemporaryFilerseekr)rrr3rrI)rOr+r,rJtemprQs rSrKz"MaildirAppendFileTests.test_append<s ||**4662q" (A))+D JJsQw  IIaO OOD ! OODJJ '  (  x 0 d(($/r]c $|jt|jd|jtdDcgc]*}t|j |j ,c}t tddycc}w)rMr,rfrFN)r<r=rr:rrr>)rOrr+rJs rSrIz$MaildirAppendFileTests._cbTestAppendOsi T..0126 5:2Y ?S#((* + ?eArlAS ?s/B N) rXrorprrxrrqrrrKrIr3r]rSrOrO2s9/ C   $&>?@$  r]rOc\eZdZdZdZdZdZeejdk\ddZ y) MaildirTestsc|j|_tjj |jyrvr8r_s rSrxzMaildirTests.setUp]r:r]cBtj|jyrv)shutilrmtreerQr_s rStearDownzMaildirTests.tearDownas dffr]c|j}tjj|d}|j tjj |xrtjj ||j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|d|j tjj tjj|dy)N.Trashnewcurtmp)rQrrjoinrGr|isdir)rOrQtrashs rStestInitializerzMaildirTests.testInitializerds* FF Q) q)>bggmmA.>? rww||Au'=>? rww||Au'=>? rww||Au'=>?  bggll1e&<=>  bggll1e&<=>  bggll1e&<=> rww||E5'ABC rww||E5'ABC rww||E5'ABC  bggll5%&@AB  bggll5%&@AB  bggll5%&@ABr]ctj}|jdtjj |}|j }|jd|j }|j||ky)a Each call to L{_MaildirNameGenerator.generate} returns a unique string suitable for use as the basename of a new message file. The names are ordered such that those generated earlier sort less than those generated later. g?N)rClockadvancer r_MaildirNameGeneratorgeneraterG)rOclock generator firstName secondNames rStest_nameGeneratorzMaildirTests.test_nameGeneratorwsh  dLL66u= &&(  d'')   J./r]r(r*c tjj}tjj }dDcgc] }t dD]}|||"}}}d}|D]A}t||j|d5}|jd|zddd|dz}Ctjj|j} |j| jtt dd|j| jdd|j| jdd |j| jd jd |j| jdjd i} t d D]+}| j!|} |j#| | vd| | <-tjj%|d\} }| j'd|j| jdd |j)tjj+||jdd||j#tjj+||j|d| j-|j| jdd |j#tjj+||jdd||j)tjj+||j|dycc}}w#1swYxYw)zb Exercise the methods of L{IMailbox} as implemented by L{MaildirMailbox}. )rar`rfwrPNrFr/r1xxxxxxxxxr,rr_ra)rrrcr r_generateMaildirNamer:rrQrrHr<rr>rrrrrrrGr|r) rOjnr6rPmsgsrJrfObjmbrQups rS test_mailboxzMaildirTests.test_mailboxs GGLL LL - -#1Da58Da!QS D DD  AalC( $D 37# $AA  \\ ( ( 0 *Dq",>? +Q/ +Q/ q)..0': q)..0': r A 1 A   Q!V $AaD  ww}}T!W%1  +Q/ q5!'DEF $&&$q'(:;<  +Q/ $&&(E1(EFG qa'9:;CE  $ $s%M0M66N N) rXrorprxr]rfrprrqrrr~r3r]rSrXrX[s?/C&0" C   $&>?(<@(.ISomethingN)rXrorpr3r]rS ISomethingrs r]ruserrNr)rrfr/) rrrrzNotImplementedError requestAvatarrIMailboxr<r=rGr)rOrts rStest_requestAvatarz+MaildirDirdbmDomainTests.test_requestAvatars   vz*  !5!5vtZ  FF t}} = Q# ! -.  00167 !r]c|jjdd|jjd}tjj dd}|j tjj|j|tjj dd}|j|j|dy)a L{DirdbmDatabase.requestAvatarId} raises L{UnauthorizedLogin} if supplied with invalid user credentials. When called with valid credentials, L{requestAvatarId} returns the username associated with the supplied credentials. rrrwrong passwordN) rrrrrUsernamePasswordrzerrorUnauthorizedLoginrequestAvatarIdr<)rOdatabasers rStest_requestAvatarIdz-MaildirDirdbmDomainTests.test_requestAvatarId s vz*6600215  11&:JK $**668P8PRWX  11&*E 11%8&Ar]cJ|jjdd|j|jjdtj j |jjdd|j_|j|jjddd|j_|j|jjdtj j |jjdy)a] L{MaildirDirdbmDomain.userDirectory} is supplied with a user name and returns the path to that user's maildir subdirectory. Calling L{MaildirDirdbmDomain.userDirectory} with a non-existent user returns the 'postmaster' directory if there is a postmaster or returns L{None} if there is no postmaster. rrFnouserNT postmaster) rrr< userDirectoryrrrcrootrassertIdenticalr_s rStest_userDirectoryz+MaildirDirdbmDomainTests.test_userDirectorys vz*  FF  ("'',,tvv{{F*K " TVV11(;TB   FF  *BGGLLl,S r]N)rXrorprrxr]rrqrrrrrrrr3r]rSrrsB C   $&>? E@ E   C   $&>?@0 C   $&>?B@B  C   $&>? @ r]rc*eZdZdZddZdZdZdZy)StubAliasableDomainz> Minimal testable implementation of IAliasableDomain. Nctz{ No test coverage for invocations of this method on domain objects, so we just won't implement it. rrOrmemos rSr|zStubAliasableDomain.exists; "##r]ctrr)rOrrs rSrzStubAliasableDomain.addUserBrr]cgS)a! This needs to succeed in order for other tests to complete successfully, but we don't actually assert anything about its behavior. Return an empty list. Sometime later we should return something else and assert that a portal got set up properly. r3r_s rSrz*StubAliasableDomain.getCredentialsCheckersIs  r]c||_y)zG Just record the value so the test can check it later. N) aliasGroup)rOaliasess rS setAliasGroupz!StubAliasableDomain.setAliasGroupRs "r]rv)rXrorprr|rrrr3r]rSrr5s$$"r]rceZdZdZdZdZeejdk\ddZ eejdk\ddZ dZ d Z d Z d Zy ) ServiceDomainTestsctjj|_tjj |jd|_|j|j _d|j _d|j _|j|_ tjj|j|j}|jdd|jjd|y)Nr<hostnameuserpassword test.domain)r rrrDomainDeliveryBaserr protocolNamehostrtmpdirrrrrrOr[s rSrxzServiceDomainTests.setUp[s&&(224664@$  kkm 11$&&$++Fw , /r]cBtj|jyrvr[r\rr_s rSr]zServiceDomainTests.tearDowng dkk"r]ct}t}||j_|jj d||j |j |y)z Test that adding an IAliasableDomain to a mail service properly sets up alias group references and such. example.comN)rrrrrrr)rOrr[s rStestAddAliasableDomainz)ServiceDomainTests.testAddAliasableDomainjsH ($&  / V..8r]r(r*cd|jjdtjddg}t j |}t jj}|j|}|jt|jd|jd|y)N) remotehostz123.232.101.234zzuser@host.namerfReceived)rreceivedHeaderrAddressioBytesIOemailparserParserparser<r=rDrV)rOhdrr emailParserr*s rStestReceivedHeaderz%ServiceDomainTests.testReceivedHeaderusff## - LL. /    ZZ_ll))+   b ! QWWY+ j!$r]ctjdddd}tj|jj |j |jS)Nzuser@test.domainhelowherever@whatever)rUserr maybeDeferredr validateTor _cbValidateTorOrs rStestValidateToz!ServiceDomainTests.testValidateTosKyy+VT;NO""466#4#4d;GG     r]c8|jt|yrv)rGcallablers rSrz ServiceDomainTests._cbValidateTos ()r]ctjdddd}|jtj|j j |tjS)Nzresu@test.domainrrrrr=r rrrrrs rStestValidateToBadUsernamez,ServiceDomainTests.testValidateToBadUsernameMyy+VT;NO!!    1 14 8$:J:J  r]ctjdddd}|jtj|j j |tjS)Nzuser@domain.testrrrrs rStestValidateToBadDomainz*ServiceDomainTests.testValidateToBadDomainrr]cd}tjd}|j|jj |||ud}tjd}|j|jj |||ud}tjd}|j|jj |||u|j tj |jjd|y)N)rrz)r1.2.3.4z<>)rrrGr validateFromrz SMTPBadSender)rOrorigins rStestValidateFromz#ServiceDomainTests.testValidateFroms(/0 ++D&9VCD&/0 ++D&9VCD&d# ++D&9VCD $,,dff.A.A4Pr]N)rXrorprxr]rrrqrrrrrrrrr3r]rSrrYsv 0# 9 C   $&>? %@ % C   $&>? @ *  Qr]rcteZdZdZdZeejdk\ddZdZ eejdk\ddZ eejdk\ddZ eejdk\dd Z d Z eejdk\dd Zeejdk\dd Zy )VirtualPOP3Testsc|j|_tjj|_tj j |j|j|_|jjdd|jjd|jtjj|j}t|j|jj|x|jj d<|jj d<tj"j%|_|j|j&_d|j&_y)Nrrrrz)rrr rrrrrrrrportalPortalmapregisterCheckerrrr VirtualPOP3rrmagic)rOrs rSrxzVirtualPOP3Tests.setUpskkm &&(11$&&$++F w , /##DFF+ F " "DFF$A$A$CD=CCrTVV^^M:++-* r]cBtj|jyrvrr_s rSr]zVirtualPOP3Tests.tearDownrr]r(r*ct|jjdzj}|jj d|j |j S)Nrr)rrr hexdigestauthenticateUserAPOPr_cbAuthenticateAPOPrOresps rStestAuthenticateAPOPz%VirtualPOP3Tests.testAuthenticateAPOPsO466<<*,-779vv**648DD  $ $  r]c|jt|d|j|dtj|j tjj |d|dyNr)rrfr/r<r=rrrGrrs rSr z$VirtualPOP3Tests._cbAuthenticateAPOPX Va( DMM2  00;<q r]ct|jjdzj}|j |jj d|t jjS)Nrresu) rrrr r=r rrrr s rS!testAuthenticateIncorrectUserAPOPz2VirtualPOP3Tests.testAuthenticateIncorrectUserAPOPsU466<<*,-779!! FF ' ' 5tzz7S7S  r]ctdj}|j|jj d|t j jS)Nz wrong digestr)rr r=rr rrrr s rS%testAuthenticateIncorrectResponseAPOPz6VirtualPOP3Tests.testAuthenticateIncorrectResponseAPOPsH>",,.!! FF ' ' 5tzz7S7S  r]cl|jjddj|jS)Nrr)rauthenticateUserPASSr_cbAuthenticatePASSr_s rStestAuthenticatePASSz%VirtualPOP3Tests.testAuthenticatePASSs/vv**6:>JJ  $ $  r]c|jt|d|j|dtj|j tjj |d|dyrrrs rSrz$VirtualPOP3Tests._cbAuthenticatePASSrr]c|j|jjddtjj S)Nrrr=rrrrrr_s rStestAuthenticateBadUserPASSz,VirtualPOP3Tests.testAuthenticateBadUserPASSs6!! FF ' ' ; JJ ( (  r]c|j|jjddtjj S)Nrrrr_s rStestAuthenticateBadPasswordPASSz0VirtualPOP3Tests.testAuthenticateBadPasswordPASSs7!! FF ' '0@ A JJ ( (  r]N)rXrorprxr]rrqrrrr rrrrr r"r3r]rSrrs +# C   $&>? @   C   $&>? @  C   $&>? @  C   $&>? @   C   $&>? @  C   $&>? @ r]rceZdZdZy)emptycyrvr3r_s rS__init__zempty.__init__s r]N)rXrorpr&r3r]rSr$r$s r]r$cDeZdZeej dk\ddZy) RelayTestsr(r*cptjj}tjj|}t j dt j dddg}t j dddt j dddg}|D]t}d |_d |_ t|_ t|j_ fd |jj_ |jt|j||D]t}d |_t|_ t|j_ fd |jj_ d|_ |j!t"j$|j|y)Nz/var/run/mail-relayTCPrrz 192.168.2.1>riz user@hostz tsoh@resucSrvr3peersrSr0z'RelayTests.testExists..dr]z some@placecSrvr3r-srSr0z'RelayTests.testExists..r/r]z who@cares)r rrelay DomainQueuerr UNIXAddress IPv4Addressr$origdestr rgetPeerrGrr|rzrr)rOrr[doRelay dontRelayrr.s @rSr}zRelayTests.testExistssV))'')((1    5 6   {E :    }b 9   y$ 7  ;D7D#DI#DI!GDM&+gDMM #.:DMM # # + OOHV]]4%89 : ; ED7D$DI!GDM&+gDMM #.:DMM # # +#DI   d.. t D Er]N)rXrorprrqrrr}r3r]rSr(r(s* C   $&>? E@ Er]r(c*eZdZdZdZdZdZdZy) RelayerTestsc|j|_tj|jg|_t dD]}tj j|jd|fz}t|dzd5}tjd|fzd|fzg|dddt|dzd}|j||jd d |jj|tjj!|_|j"j%|jy#1swYxYw) Nr,body-%d-Hrfrom-%dto-%d-Drsr)rrrmkdir messageFilesr:rrcrpickledumprrTr)r r1 RelayerMixinR loadMessages)rOrJrrs rSrxzRelayerTests.setUpskkm  r +A77<< Y!-=>DdTk4( CA Y!-w!~>B CTD[#&A GGDM FF1aL    $ $T * +((* D--. C Cs !EE cBtj|jyrvrr_s rSr]zRelayerTests.tearDown0rr]ctdD]O}|j|jjd|fz|jj dddddQ|j|jjdy)Nr,r?)r:r<rG getMailFromsentMailrOrJs rS testMailFromzRelayerTests.testMailFrom3spr 9A   TVV//19t3C D FFOOCtT4 8 9 ++-t4r]ctdD]P}|j|jjd|fzg|jj dddddR|j|jjdy)Nr,r@rK)r:r<rG getMailTorMrNs rS testMailTozRelayerTests.testMailTo9srr 9A   TVV--/'QD.1A B FFOOCtT4 8 9 ))+T2r]ctdD]}tjj|jd|fz}|j |j jj||j jddddd|j |j jdy)Nr,r=rK) r:rrrcrr<rG getMailDatarrM)rOrJrs rS testMailDatazRelayerTests.testMailData?sr 9A77<< Y!-=>D   TVV//1668$ ? FFOOCtT4 8 9 ++-t4r]N)rXrorprxr]rOrRrUr3r]rSr;r;s/"#5 3 5r]r;c$eZdZdZdZdZdZy)Managerc.g|_g|_g|_yrv)successr doner_s rSr&zManager.__init__Hs   r]c>|jj||fyrv)rYr)rOrrhs rS notifySuccesszManager.notifySuccessM Wg./r]c>|jj||fyrv)r r)r\s rS notifyFailurezManager.notifyFailurePr^r]c:|jj|yrv)rZr))rOrs rS notifyDonezManager.notifyDoneSs !r]N)rXrorpr&r]r`rbr3r]rSrWrWGs 00"r]rWc$eZdZdZdZdZdZy)ManagedRelayerTestsct|_ttddd|_t |_tjj|j|_ |jdd|j_|jdd|j_ |j |j_y)Nrr.r/) rWmanagerr>r:r,rrr relaymanagerManagedRelayerMixinr1namesr_s rSrxzManagedRelayerTests.setUpYs~y U1b!_- x &&::4<<H "mmA. ==+ !\\ r]c|jD]!}|jjddddd#|j|jj |jDcgc]}|j |fc}ycc}w)NrK)r,r1rMr<rfrYrrOrJr*s rStestSuccessfulSentMailz*ManagedRelayerTests.testSuccessfulSentMailbi =A JJ  T4t < =  LL dmm"LDLL!#4"L "LA< c|jD]!}|jjddddd#|j|jj |jDcgc]}|j |fc}ycc}w)Ni&)r,r1rMr<rfr rrks rStestFailedSentMailz&ManagedRelayerTests.testFailedSentMailjrmrnc|jjtjt |j |j j|jgyrv) r1rr Failurer>r<rfrZrr_s rStestConnectionLostz&ManagedRelayerTests.testConnectionLostrs? !!'//)+">? **T\\N;r]N)rXrorprxrlrprsr3r]rSrdrdWs*  A   Y]]1-!} = >r]N) rXrorprxr]rrqrrrrrrr3r]rSruruws ## C   $&>? ;@ ; C   $&>? ;@ ; C   $&>? 9@ 9>r]ru)clientcommonserverceZdZdZddZy) TestAuthoritycPtjj|i|_yrv)r ResolverBaser& addressesr_s rSr&zTestAuthority.__init__s$$T*r]Nc ||jvr|tjk(rg}|j|D]\}tj|tjtjdtj d|}|j |^tj|ggfStjtjtj|S)N<r) rrMXrINrr)r succeedfailr rr DomainError)rOrclstypetimeoutr-r5rs rS_lookupzTestAuthority._lookups 4>> !dcffnG^^D) $ll4S]]1a=PQs# $=='2r!23 3zz'//#//$*?@AAr]rv)rXrorpr&rr3r]rSrrs Br]rct|_tj|jg}t j |} t jd|d|_|jjj} t j||d|_ tjd|fg|_y#t$r|jjYnwxYw)Nrr interface)servers)rauthrDNSServerFactoryrDNSDatagramProtocolr listenTCPportgetHost listenUDPudpPortr stopListeningrResolverresolver)rOrr portNumbers rSsetUpDNSrsDI%%tyyk2G&&w/H %%aKH YY&&(--  ",,H DL OOk:-F,GHDM ! & II # # % & sC#C+*C+cxg}|jtj|jj|jtj|j j |j jjtj|S#t$rY wxYwrv) r)r rrrrr _parseCallcancel BaseException DeferredList)rOdls rS tearDownDNSrs BIIe!!$))"9"9:;IIe!!$,,"<"<=>    '')   b !!    s4$B-- B98B9ceZdZdZdZdZdZeejdk\ddZ dZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZeejdk\ddZdZdZdZdZy)MXTestsz6 Tests for L{mail.relaymanager.MXCalculator}. ct|tj|_tj j |j|j|_yrv) rrrhrlr rg MXCalculatorrmxr_s rSrxz MXTests.setUps8ZZ\ ##00 Kr]ct|Srv)rr_s rSr]zMXTests.tearDowns 4  r]c|jtjj|jj t y)zQ L{MXCalculator}'s default clock is C{twisted.internet.reactor}. N)rr rgrrrlrr_s rStest_defaultClockzMXTests.test_defaultClocks2     * *4== 9 ? ? r]r(r*cdg|jjd<|jjdj |j S)Nthe.email.test.domainr)rrrgetMXr_cbSimpleSuccessr_s rStestSimpleSuccesszMXTests.testSimpleSuccesss=.E-F M*ww}}]+778M8MNNr]c|j|jd|jt|jdy)Nrr)r< preferencerYrrOrs rSrzMXTests._cbSimpleSuccesss/ * RWW'>?r]cd|j_|j|jjdtS)NFr)rfallbackToDomainr=rIOErrorr_s rStestSimpleFailurezMXTests.testSimpleFailure s.#( !!$''-- ">HHr]c`|j|jjdtSNr)r=rrrr_s rStestSimpleFailureWithFallbackz%MXTests.testSimpleFailureWithFallbacks"!!$''-- ">OOr]cGfdd}|j_jj}fd}|j||S)aZ Issue an MX request for the given domain and arrange for it to be responded to with the given records. Verify that the resulting mail exchange is the indicated host. @type domain: C{str} @type records: C{list} of L{RRHeader} @type correctMailExchange: C{str} @rtype: L{Deferred} ceZdZfdZy),MXTests._exchangeTest..DummyResolvercz|k(rtjggfStjtSrv)r rrr)rOrr[recordss rSlookupMailExchangez?MXTests._exchangeTest..DummyResolver.lookupMailExchanges46> =='2r):;;zz,v"677r]NrXrorpr)r[rsrS DummyResolverrs 8r]rcPjt|jyrvr<rYr)recordcorrectMailExchangerOs rSgotMailExchangez.MXTests._exchangeTest..gotMailExchange's   S-/B Cr])rrrr)rOr[rrrrQrs```` rS _exchangeTestzMXTests._exchangeTestsH 8 8 )? GGMM& ! D o&r]c d}d}d}t|tjtd|t|tjtd|t|tjtd|g}|j|||S)zh The MX record with the lowest preference is returned by L{MXCalculator.getMX}. rgood.example.combad.example.comrfrrpayloadrr/)rrTYPErrOr[goodbadrs rStest_mailExchangePreferencez#MXTests.test_mailExchangePreference-sx ! &y~~yC?P Q &y~~yD?Q R &y~~yC?P Q  !!&'488r]c d}d}d}t|tjtd|t|tjtd|g}|jj ||j |||S)z L{MXCalculator.getMX} returns the MX record with the lowest preference which is not also marked as bad. rrrrrrfrrrrmarkBadrrs rStest_badExchangeExcludedz MXTests.test_badExchangeExcluded=sq ! &y~~yC?P Q &y~~yD?Q R  !!&'488r]c 8d}d}d}t|tjtd|t|tjtd|g}|jj ||jj ||j |||S)z L{MXCalculator.getMX} returns the MX record with the lowest preference if all the MX records in the response have been marked bad. rrzworse.example.comrrrfr)rOr[rworsers rStest_fallbackForAllBadExchangesz'MXTests.test_fallbackForAllBadExchangesMs # &y~~yC?P Q &y~~yE?R S   !!&'377r]c `d}d}d}t|tjtd|t|tjtd|g}|jj ||j j |jj|j|||S)z L{MXCalculator.getMX} returns the MX record with the lowest preference if it was last marked bad longer than L{MXCalculator.timeOutBadMX} seconds ago. rrrrrrf) rrrrrrlri timeOutBadMXrrOr[r previouslyBadrs rStest_badExchangeExpireszMXTests.test_badExchangeExpires^s !)  )..)A}:U  &y~~yD?Q R    & 477//0!!&'=AAr]c d}d}d}t|tjtd|t|tjtd|g}|jj ||jj ||j j|jj|j|||S)z L{MXCalculator.getMX} returns the MX record with the lowest preference if it was marked good after it was marked bad. rrrrrrf) rrrrrmarkGoodrlrirrrs rStest_goodExchangeUsedzMXTests.test_goodExchangeUsedrs !)  )..)A}:U  &y~~yD?Q R    & ' 477//0!!&'=AAr]cddGfdd}||j_|jj}|j|jt |S)z If an MX lookup succeeds but the result set is empty, L{MXCalculator.getMX} should try to look up an I{A} record for the requested name and call back its returned Deferred with that address. rz example.orgc:eZdZdZWgggfiZWWiZdZdZy)9MXTests.test_successWithoutResults..DummyResolverah Fake resolver which will respond to an MX lookup with an empty result set. @ivar mx: A dictionary mapping hostnames to three-tuples of results to be returned from I{MX} lookups. @ivar a: A dictionary mapping hostnames to addresses to be returned from I{A} lookups. cFtj|j|Srv)r rrrs rSrzLMXTests.test_successWithoutResults..DummyResolver.lookupMailExchanges}}TWWV_55r]cFtj|j|Srv)r rr5rs rS getHostByNamezGMXTests.test_successWithoutResults..DummyResolver.getHostByNames}}TVVF^44r]N)rXrorprrr5rr)r[ipsrSrrs- 2r2,'B A 6 5r]rrrrrrr<r)rOrrQr[rs @@rStest_successWithoutResultsz"MXTests.test_successWithoutResultssY 5 5*)? GGMM& ! d&& r(:;r]cGdd}||j_|jjd}|j|jt d|S)a' Test that if the MX record lookup fails, fallback is enabled, and an A record is available for the name, then the Deferred returned by L{MXCalculator.getMX} ultimately fires with a Record_MX instance which gives the address in the A record for the name. ceZdZdZdZdZy)AMXTests.test_failureWithSuccessfulFallback..DummyResolverzw Fake resolver which will fail an MX lookup but then succeed a getHostByName call. c<tjtSrv)r rrrs rSrzTMXTests.test_failureWithSuccessfulFallback..DummyResolver.lookupMailExchangeszz,.11r]c,tjdS)Nr)r rrs rSrzOMXTests.test_failureWithSuccessfulFallback..DummyResolver.getHostByNames}}Y//r]N)rXrorprrrr3r]rSrr s   2 0r]rr[rrr)rOrrQs rS"test_failureWithSuccessfulFallbackz*MXTests.test_failureWithSuccessfulFallbacksL 0 0)? GGMM( # d&& y(ABr]cdddGfdd}||j_|jj}|j|jt |S)z If an MX lookup returns a single CNAME record as a result, MXCalculator will perform an MX lookup for the canonical name indicated and return the MX record which results. alias.example.comcanonical.example.commail.example.comc eZdZdZfdZy);MXTests.test_cnameWithoutGlueRecords..DummyResolverz Fake resolver which will return a CNAME for an MX lookup of a name which is an alias and an MX for an MX lookup of the canonical name. c F|k(r.DummyResolver.lookupMailExchangesU? ==!))/)5):):,8,C!"   y( ==!))/)2,5a,B!"   !::l6&:;;r]N)rXrorprr)rrrsrSrrs    .DummyResolverz Fake resolver which generates a CNAME chain of infinite length in response to MX lookups. rc |xjdz c_d|jfz}tjt|tj t |gggfS)Nrfx-%d.example.comr) chainCounterr rrrr)rOr[rs rSrzAMXTests.test_cnameChain..DummyResolver.lookupMailExchangesg!!Q&!)T->->,@@}}%%+%1%6%6(4T(:   r]N)rXrorprrrr3r]rSrrs  L r]rr)rcj|jdtddzfzjjjj dzy)Nrrrf)r<argsrrrr)r cnameLimitrOs rScbChainTooLongz/MXTests.test_cnameChain..cbChainTooLongsV    1 |,>*q.AR,RS    TWW--::JN Kr]) rrrr=twistedr rgCanonicalNameChainTooLongr)rOrrQr"r!s` @rStest_cnameChainzMXTests.test_cnameChainsp  2 (? GGMM,j 9 1gll77QQR L n%r]cgdddGfdd}||j_|jj}|j|jt |S)z If an MX lookup returns a CNAME and the MX record for the CNAME, the L{Deferred} returned by L{MXCalculator.getMX} should be called back with the name from the MX record without further lookups being attempted. rrrceZdZfdZy)8MXTests.test_cnameWithGlueRecords..DummyResolverc |k7srgggfStjttjttt jt gggfS)Nrr)r rrrrr)rOr[rrrlookedUps rSrzKMXTests.test_cnameWithGlueRecords..DummyResolver.lookupMailExchange3swU?hB<'}}%%*%1%6%6(4Y(? %%.%.^^(1x(@ r]Nr)rrrr*srSrr(2s   r]rrr)rOrrQrrrr*s @@@@rStest_cnameWithGlueRecordsz!MXTests.test_cnameWithGlueRecords&sc#+ %  2)? GGMM%  d&& x(@Ar]cddGfdd}||j_|jj}|j|tj j j|S)z If an MX lookup returns two CNAME records which point to each other, the loop should be detected and the L{Deferred} returned by L{MXCalculator.getMX} should be errbacked with L{CanonicalNameLoop}. zcname1.example.comzcname2.example.comceZdZfdZy).DummyResolverc tjttjtttjtgggfS)Nr)r rrrr)rOr[ firstAlias secondAliass rSrzOMXTests.test_cnameLoopWithGlueRecords..DummyResolver.lookupMailExchangeZsb}}%%/%1%6%6(4[(A %%0%1%6%6(4Z(@ r]Nr)r0r1srSrr.Ys r]r)rrrr=r#r rgCanonicalNameLoop)rOrrQr0r1s @@rStest_cnameLoopWithGlueRecordsz%MXTests.test_cnameLoopWithGlueRecordsPs` * *   *)? GGMM* % 1gll77IIJr]cgd|jjd<|jjdj |j S)N)zmx1.test.domainzmx2.test.domainzmx3.test.domainr)rrrrr_cbManyRecordsSuccessfulLookupr_s rStestManyRecordszMXTests.testManyRecordsssC.  M* ww}}]+77  / /  r]c:|jt|jjddddv|jj t|j|jj dj|j|S)N.rfr)mx1mx2mx3r) rGrYrrrrrr_cbManyRecordsDifferentResultrs rSr5z&MXTests._cbManyRecordsSuccessfulLookup~sq BGG **32159NNO BGG %ww}}]+77  . .  r]c:|jt|jt|j|jj t|j|jj dj |j||Sr)rrYrrrrr_cbManyRecordsLastResult)rOnextMXrs rSr<z%MXTests._cbManyRecordsDifferentResultsi CL#fkk*:; FKK()ww}}]+77  ) )2v  r]c|jt|jt|j|jt|jt|j|jj t|j|jj t|j|jj dj|j|Sr) rrYrrrrrr"_cbManyRecordsRepeatSpecificResult)rOlastMXrr?s rSr>z MXTests._cbManyRecordsLastResults CL#fkk*:; C ,c&++.>? FKK() V[[)*ww}}]+77  3 3V  r]ct|jt|jt|jyrvr)rOagainMXr?s rSrAz*MXTests._cbManyRecordsRepeatSpecificResults$ W\\*C ,<=r]N)rXrorprrxr]rrrqrrrrrrrrrrrrrr rr%r+r3r6r5r<r>rAr3r]rSrrsL !  C   $&>?O@O@IP69 9 8"B(B("H23j,\(T!F C   $&>? @     >r]rceZdZejeddZdZdZe e jdk\ddZ e e jdk\ddZ y) LiveFireExerciseTestsNz1UDP support is required to determining MX recordsc,t|gd|_y)N) domainDirinsertionDomaininsertionQueuedestinationDomaindestinationQueue)rtmpdirsr_s rSrxzLiveFireExerciseTests.setUps  r]c|jD]7}tjj|s#t j |9t |Srv)rMrrr|r[r\r)rOrQs rSr]zLiveFireExerciseTests.tearDowns> !Aww~~a  a  !4  r]r(r*ctjj}|jjtj j tjj|djdd|jd|jd|jd<t|jdjj|jtjj!||j#}t%j&d|d_t+gd t-t/j0}fd |_fd |_t%j4dj(j7j8|fd }j;|S) NrHrrrrrrr) HELO mesonzMAIL FROM: zRCPT TO: DATAThis is the messager8QUITcSrvr3rsrSr0z9LiveFireExerciseTests.testLocalDelivery..Vr]c&jdSrvcallbackr rZs rSr0z9LiveFireExerciseTests.testLocalDelivery..t}}T/Br]cjddtjd}|jdj }j |j ddjjSNrrfrrR) rrrrrrfind smtpServerr)ignr+rr[rOs rSfinishedz9LiveFireExerciseTests.testLocalDelivery..finishedsd''dmmDQGD//!$))+C   )> ? D??002 2r])r r smtpPortalrrrAllowAnonymousAccessrrrrrrrsetQueuer1r2rrrr`rrr ClientFactoryclientConnectionLost connectTCPrrr)rOrrrbrr[rZs` @@@rStestLocalDeliveryz'LiveFireExerciseTests.testLocalDeliverysX))'')**4==+M+M+OP11';Gvz*-0%oom< GOOB  / /1N1N1PQ009:  " " $!++AqKH$   z  " " $# !B;(?(?(A(F(FJ 3 " r]c tjj}|jjtj j tjj|d|jdtjd|jtjjd|jj!tj"j%|tjj'|j( xj*dz c_tjj- dtjj/j0 _dgj4j6d<|j9}t;j<d|d _tjj}|jjtj j tjj|d jAd d |jdtjd |jtjjd tjj- djC|j9}t;j<d|d _"jDjGjH _%tMgdtOtQjR}fd|_(fd|_*t;jVdj>jGjH| fd}jY|S)NrIzinsertion.domainrJ)ztest.identity.hostnamerfrzdestination.domainrrrKrrrL)rPzMAIL FROM: z"RCPT TO: rQrRr8rScSrvr3rUsrSr0z9LiveFireExerciseTests.testRelayDelivery..rVr]c&jdSrvrXrZs rSr0z9LiveFireExerciseTests.testRelayDelivery..r[r]cXj}fd}|j||S)NcVjddtjd}|jdj }j |j ddjjjjjyr]) rrrrrrr_ insServerr destServer stopService)rar+rr[helperrOs rS deliveredzLLiveFireExerciseTests.testRelayDelivery..finished..delivereds}++FD$--HKooa(--/##CHH-B$CRH,,.--/""$r]) checkStater)rarrsr[rrrfrOs rSrbz9LiveFireExerciseTests.testRelayDelivery..finisheds-))+H %   +Or])-r rrcrrrrdrrrrrBrergryrMsetDefaultDomainr1r2SmartHostSMTPRelayingManagerrzfArgsRelayStateHelperrrmxcalcrrrrrror startServicerprrPORTrrr rfrgrhr) rOinsServrdestServrbrr[rZrrrfs ` @@@@@rStestRelayDeliveryz'LiveFireExerciseTests.testRelayDeliverys))'')**4==+M+M+OP11';LM,f5 !"**001ABC(()@)@)IJ##@@O 44 ""33GQ?**77 F5@M 01  " " $ **1a;G99((*++DMM,N,N,PQ11((>(@(E(EqI " " r])rXrorpr IReactorUDPrskiprxr]rrqrrrir~r3r]rSrFrFsyzgt,4B !  C   $&>?)@)V C   $&>?K@Kr]rFc$eZdZdZdZdZdZy)LineBufferMessagec.g|_d|_d|_y)NF)lineseomlostr_s rSr&zLineBufferMessage.__init__-s  r]c:|jj|yrv)rr))rOrs rSrzLineBufferMessage.lineReceived2s $r]c:d|_tjdS)NTz )rr rr_s rSrzLineBufferMessage.eomReceived5s}}\**r]cd|_y)NT)rr_s rSrz LineBufferMessage.connectionLost9s  r]N)rXrorpr&rrrr3r]rSrr,s  +r]rceZdZgdZdZeejdk\ddZdZ dZ eejdk\ddZ d Z y ) AliasTestsz First linez Next linerzAfter a blank linez Last lineci}gd}|D]$}tjj||dd&|j|dddg|j|ddg|j|dd g|j|d gd y) N)zuser: another@host znextuser: |/bin/program zuser: me@again z"moreusers: :/etc/include/filename z3multiuser: first@host, second@host,last@anotherhostr$rz another@hostzme@againnextuserz |/bin/program moreusersz:/etc/include/filename multiuser)z first@hostz second@hostzlast@anotherhost)r rhandler<)rOrrls rS testHandlezAliasTests.testHandleAs  ;A JJ  faT : ; .*)EF  +o->?  ,/G.HI  ; !R r]r(r*c8dti}tjj|t j t jdj}|jt|d|d}t|}dD]#}|j|j|d%|jt|d|d }t|}d D]#}|j|j|d%|jt|d|d }t|}|j|jd dd D]'}|j|j|dd|z)|jt|dy)Nra # Here's a comment # woop another one testuser: address1,address2, address3, continuation@address, |/bin/process/this usertwo:thisaddress,thataddress, lastaddress lastuser: :/includable, /filename, |/program, address )rr)testuser)address1address2address3zcontinuation@addressz/bin/process/thisr^rrusertwo) thisaddress thataddress lastaddresslastuserz /includable)z /filenameprogramr z %s not found)rr r loadAliasFilerrtextwrapdedentencoder<r=rYrr_)rOrMrgroupsr5s rStestFileLoaderzAliasTests.testFileLoaderUswvx.)) zz &( * " Va(z" J  /A   q 2 . / UQ'y! J> /A   q 2 . / UQ'z" J  .34 CA   q 2~/A B C UQ'r]ctttf}tjj|}|jD]}|j ||j j|j|Srv) rr r MultiWrapperrrrr_cbMultiWrapper)rOryrLs rStestMultiWrapperzAliasTests.testMultiWrappersn "$5$79J9LLjj%%d+ A   Q   ,,T-A-A4HHr]c|D]^}|j|j|j|j|j |j |j `yrv)rGrrrr<r)rOr/ryr*s rSrzAliasTests._cbMultiWrappersK 2A OOAEE "   QVV $   TZZ 1 2r]c|j}tjj|dd}|j }|j D]}|j ||jj|j|Srv) rr r FileAliascreateMessageReceiverrrrr_cbTestFileAlias)rOtmpfiler5r*rs rS testFileAliaszAliasTests.testFileAliassq++- JJ $ 5 # # % A NN1  }}**4+@+@'JJr]ct|5}|j}ddd|jDcgc]}|dd c}|jy#1swY7xYwcc}w)Nr^r readlinesr<r)rOr/rrrrs rSrzAliasTests._cbTestFileAliassR '] "aKKME " %0Q!CR&0$**= " "0sA AAN) rXrorprrrrqrrrrrrrr3r]rSrr=so NE ( C   $&>?,(@,(\I2  C   $&>?K@K>r]rceZdZdZdZddZy) DummyDomainz/ Test domain for L{AddressAliasTests}. c||_yrv)r )rOr s rSr&zDummyDomain.__init__s  r]NcT|rtjjdfdS)a  @returns: When a C{memo} is passed in this will raise a L{smtp.SMTPBadRcpt} exception, otherwise a boolean indicating if the C{user} and string version of L{self.address} are equal or not. @rtype: C{bool} hamc4tjk(Srv)rYr rsrSr0z$DummyDomain.exists..sts4<<00r])r rrrs`` rSr|zDummyDomain.existss# ))''. .00r]rv)rXrorprr&r|r3r]rSrrs 1r]rc.eZdZdZdZdZdZdZdZy)AddressAliasTestsz7 Tests for L{twisted.mail.alias.AddressAlias}. ctjjd|_|jjt |ji}tj j|j||j|_y)z+ Setup an L{AddressAlias}. zfoo@barN)r rrr r[rr AddressAlias)rOrMs rSrxzAddressAliasTests.setUpsYyy((3 <<&& DLL(ABZZ,,T\\7DLLQ r]cV|j|jjy)z L{createMessageReceiever} calls C{exists()} on the domain object which key matches the C{alias} passed to L{AddressAlias}. N)rGrrr_s rStest_createMessageReceiverz,AddressAliasTests.test_createMessageReceivers  88:;r]cN|jt|jdy)zP The string presentation of L{AddressAlias} includes the alias. z
N)r<rYrr_s rSr`zAddressAliasTests.test_strs TZZ*=>r]cr|j|jj|jdidy)z L{resolve} will look for additional aliases when an C{aliasmap} dictionary is passed, and returns L{None} if none were found. rN)r<rresolver r_s rS test_resolvezAddressAliasTests.test_resolves, ++T\\5,ABDIr]cZ|j|jjidy)z L{resolve} returns L{None} when the alias could not be found in the C{aliasmap} and no L{mail.smtp.User} with this alias exists either. N)r<rrr_s rStest_resolveWithoutAliasmapz-AddressAliasTests.test_resolveWithoutAliasmaps# ++B/6r]N) rXrorprrxrr`rrr3r]rSrrs"R<? J7r]rceZdZdgZy) DummyProcessonEndN)rXrorp __slots__r3r]rSrrs  Ir]rceZdZdZdZy)MockProcessAliaszD An alias processor that doesn't actually launch processes. cy)z( Don't spawn a process. Nr3)rOprotorrs rS spawnProcesszMockProcessAlias.spawnProcessr]N)rXrorprrr3r]rSrrs  r]rceZdZdZeZy)MockAliasGroupz3 An alias group using C{MockProcessAlias}. N)rXrorprrprocessAliasFactoryr3r]rSrrs+r]rc"eZdZdZdZdZdZy) StubProcessz Fake implementation of L{IProcessTransport}. @ivar signals: A list of all the signals which have been sent to this fake process. cg|_yrv)signalsr_s rSr&zStubProcess.__init__s  r]cy)z8 No-op implementation of disconnection. Nr3r_s rSloseConnectionzStubProcess.loseConnectionrr]c:|jj|y)zL Record a signal sent to this process for later inspection. N)rr))rOsignals rS signalProcesszStubProcess.signalProcess s F#r]N)rXrorprr&rrr3r]rSrrs $r]rc eZdZdZej eddZgdZdZ dZ dZ dZ e ejd k\d d Zd Zd ZdZdZdZe ejd k\d dZe ejd k\d dZy)ProcessAliasTestsz% Tests for alias resolution. NzIReactorProcess not supportedrc|dzdz}|jtj||jtj|||j tj ||S)a Construct a status from the given exit code. @type code: L{int} between 0 and 255 inclusive. @param code: The exit status which the code will represent. @rtype: L{int} @return: A status integer for the given exit code. r)rGr WIFEXITEDr< WEXITSTATUSr WIFSIGNALED)rOcodestatuss rS exitStatuszProcessAliasTests.exitStatuss]!)q  V,- /6 /0 r]c|}|jtj||jtj|||j tj ||S)a Construct a status from the given signal. @type signal: L{int} between 0 and 255 inclusive. @param signal: The signal number which the status will represent. @rtype: L{int} @return: A status integer for the given signal. )rGrrr<WTERMSIGrr)rOrrs rS signalStatuszProcessAliasTests.signalStatus0sU v./ V,f5 f-. r]cDtj|_dt_y)zB Replace L{smtp.DNSNAME} with a well-known value. rN)rDNSNAMEr_s rSrxzProcessAliasTests.setUpHs||  r]c.|jt_y)z@ Restore the original value of L{smtp.DNSNAME}. N)rrr_s rSr]zProcessAliasTests.tearDownOs|| r]r(r*ctj}|jdtj|j dt jj|j dd}|j}jD]}|j|fd}|jj|S)z Standard call to C{mail.alias.ProcessAlias}: check that the specified script is called, and that the input is correctly transferred to it. zX#!/bin/sh rm -f process.alias.out while read i; do echo $i >> process.alias.out doneiNctd5}|j}dddjDcgc]}|dd c}jy#1swY7xYwcc}w)Nzprocess.alias.outr^r)r/rrrrOs rS_cbProcessAliasz._cbProcessAliasksU)* &a  &   e4af4djj A & &4sA A A)r"r setContentrchmodrr r ProcessAliasrrrrr)rOshr5r*rrs` rStest_processAliasz#ProcessAliasTests.test_processAliasUs dkkm $    % JJ # #BGGT4 8 # # % A NN1   B }}**?;;r]ctj}ttjj j tjjd|}|j}|j|jfd}j|tjj|j||S)a  If the alias child process does not exit within a particular period of time, the L{Deferred} returned by L{MessageWrapper.eomReceived} should fail with L{ProcessAliasTimeout} and send the I{KILL} signal to the child process.. Ncjjdgjtj t j y)NKILL)r<r processEndedrrrSIGKILL)r/rrOrs rStimedOutz.timedOuts@   Y.. 9   01B1B6>>1RS Tr])rrhrr rProcessAliasProtocolrMessageWrapperrricompletionTimeoutr=ProcessAliasTimeoutr)rOrreceiverrQrrrs` @@rStest_processAliasTimeoutz*ProcessAliasTests.test_processAliasTimeoutrs**,M  //1 Y'::,,UD'B  "223 U 1djj<<= hr]c\t}tjj}|j|tjj |dd}|j tjtd|j|jtS)z If the process associated with an L{mail.alias.MessageWrapper} exits before I{eomReceived} is called, the L{Deferred} returned by I{eomReceived} should fail. Nr) rr rrrrrr rrrr=r)rOrr rs rStest_earlyProcessTerminationz.ProcessAliasTests.test_earlyProcessTerminations~  M ::224 *::,,XtTBgook!n=>!!("6"6"8+FFr]c\t}tjj}|j|tjj |dd}|j tjt||j|jtS)z Verify that if the process associated with an L{mail.alias.MessageWrapper} exits with the given status, the L{Deferred} returned by I{eomReceived} fails with L{ProcessTerminated}. N) rr rrrrrr rrrr=r)rOrrr rs rS_terminationTestz"ProcessAliasTests._terminationTests  M ::224 *::,,XtTBgoo.?.GHI!!("6"6"8:KLLr]cB|j|jdS)z If the process associated with an L{mail.alias.MessageWrapper} exits with a non-zero exit code, the L{Deferred} returned by I{eomReceived} should fail. rf)rrr_s rStest_errorProcessTerminationz.ProcessAliasTests.test_errorProcessTerminations $$T__Q%788r]c^|j|jtjS)z If the process associated with an L{mail.alias.MessageWrapper} exits because it received a signal, the L{Deferred} returned by I{eomReceived} should fail. )rrrSIGHUPr_s rStest_signalProcessTerminationz/ProcessAliasTests.test_signalProcessTerminations$ $$T%6%6v}}%EFFr]c ri}dt|gdi}tgd|d}tddg|d}tjj d|d}|j |||d |j |}tt|j}|jtttjj d d d tjjtd tjjd g}|j|j|||j |} tt| j} | jtttjj dd d tjj dd d g}|j|j| ||j |} tt| j} | jtttjj d d d tjjtd tjjd g}|j|j| |y )a Check that the C{resolve} method of alias processors produce the correct set of objects: - direct alias with L{mail.alias.AddressAlias} if a simple input is passed - aliases in a file with L{mail.alias.FileWrapper} if an input in the format '/file' is given - aliases resulting of a process call wrapped by L{mail.alias.MessageWrapper} if the format is '|process' r)rrr)r|echo/filealias1rralias2alias3r rrrNechor ) TestDomainrr rrrHrrrYobjsrBrr FileWrapperr<) rOrr[A1A2A3res1r1expectedres2r2res3r3s rStest_aliasResolutionz&ProcessAliasTests.test_aliasResolutionsj*EFG 7 J Wg. A ZZ $ $Xvx @  zz'" dii     ''t< )),.&A &&w/     X&zz'" dii     ''t< ''t<     X&zz'" dii     ''t< )),.&A &&w/     X&r]c<i}dt|gi}tjjd|d}tjjd|d}tjjd|d}|j |||d|j |dj |d|j |dj |d|j |dj |dtddg|d}||d<|j |}tt|j}|jtttjjtd g} | j|j || y) zN Check that a cycle in alias resolution is correctly handled. rrr rrNr alias4r)rr rrrHr<rrrrYrrBrr) rOrr[rrrA4resrrs rStest_cyclicAliasz"ProcessAliasTests.test_cyclicAliassT j"-. ZZ $ $Xvx @ ZZ $ $Xvx @ ZZ $ $Xvx @"bAB *227;TB *227;TB *227;TB Wh/ Bjj! SXX  sTZZ66|~vNOP  H%r])rXrorprr IReactorProcessrrrrrrxr]rrqrrrrrrrr rr%r3r]rSrrs"z!!'408. NE*0$  C   $&>?<@<84 G M9G C   $&>?>'@>'@ C   $&>?&@&r]rceZdZdZddZy)rc ||_||_yrv)rusers)rOrr)s rSr&zTestDomain.__init__ s  r]Nc,jj|jvrfdS |j}|j |j|rfdSt j #t$rt j wxYw)NcFtjjddSrv)r rr)rsrSr0z#TestDomain.exists.. s4::224tDr]cSrvr3)rsrSr0z#TestDomain.exists.." swr])r6localr)rrrrr)rOrrr5rs ` @rSr|zTestDomain.exists syy 4:: D D ) T"Aii d3G&&""4( (  )""4( ( )s A44Brv)rXrorpr&r|r3r]rSrr s  )r]rc4eZdZdZdZdZdZdZdZdZ y) DummyQueuez A fake relay queue to use for testing. This queue doesn't keep track of which messages are waiting to be relayed or are in the process of being relayed. @ivar directory: See L{__init__}. c||_y)z @type directory: L{bytes} @param directory: The pathname of the directory holding messages in the queue. N) directory)rOr1s rSr&zDummyQueue.__init__0 s #r]ctjj|}tj|j |dztj|j |dzy)z Remove a message from the queue. @type message: L{bytes} @param message: The base filename of a message. rAr>N)rrbasenameremovegetPathrOrhs rSrZzDummyQueue.done8 sL''""7+ $,,w'$./ $,,w'$./r]cpttjj|j|dzdS)z Get the envelope file for a message in the queue. @type message: L{bytes} @param message: The base filename of a message. @rtype: L{file} @return: The envelope file for the message. r>r)rrrrcr1r6s rSgetEnvelopeFilezDummyQueue.getEnvelopeFileC s(BGGLL4@$GGr]cVtjj|j|S)z Return the full base pathname of a message in the queue. @type message: L{bytes} @param message: The base filename of a message. @rtype: L{bytes} @return: The full base pathname of the message. )rrrcr1r6s rSr5zDummyQueue.getPathO sww||DNNG44r]ctjdt|}ttjj |j |dzd}tjj |j |dz}tjj |j |dz}t|d}|tjj|||fS)z Create a new message in the queue. @rtype: 2-L{tuple} of (E{1}) L{file}, (E{2}) L{FileMessage} @return: The envelope file and a message receiver for a new message in the queue. _r>rz-CrA) timeidrrrrcr1r r)rOfname headerFile tempFilename finalFilename messageFiles rSr|zDummyQueue.createNewMessage[ s99;-qD +"'',,t~~ut|DdK ww||DNNEDLA  T^^UT\B <. 49900 }   r]cy)z Ignore the request to mark a message as waiting to be relayed. @type message: L{bytes} @param message: The base filename of a message. Nr3r6s rSrzDummyQueue.setWaitingm s r]N) rXrorprr&rZr8r5r|rr3r]rSr/r/& s&# 0 H 5 $ r]r/ceZdZdZdZy)!DummySmartHostSMTPRelayingManagera4 A fake smart host to use for testing. @type managed: L{dict} of L{bytes} -> L{list} of L{list} of L{bytes} @ivar managed: A mapping of a string identifying a managed relayer to filenames of messages the managed relayer is responsible for. @ivar queue: See L{__init__}. c i|_||_y)z Initialize the minimum necessary members of a smart host. @type queue: L{DummyQueue} @param queue: A queue that can be used for testing purposes. N)managedrz)rOrzs rSr&z*DummySmartHostSMTPRelayingManager.__init__ s  r]N)rXrorprr&r3r]rSrErEw s  r]rEceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z eej d k\d dZeej d k\d dZdZdZdZdZy)_AttemptManagerTestsa Test the behavior of L{_AttemptManager}. @type tmpdir: L{bytes} @ivar tmpdir: The path to a temporary directory holding the message files. @type reactor: L{MemoryReactorClock} @ivar reactor: The reactor used for test purposes. @type eventLog: L{None} or L{dict} of L{bytes} -> L{object} @ivar eventLog: Information about the last informational log message generated or none if no log message has been generated. @type noisyAttemptMgr: L{_AttemptManager} @ivar noisyAttemptMgr: An attempt manager which generates informational log messages. @type quietAttemptMgr: L{_AttemptManager} @ivar quietAttemptMgr: An attempt manager which does not generate informational log messages. @type noisyMessage: L{bytes} @ivar noisyMessage: The full base pathname of the message to be used with the noisy attempt manager. @type quietMessage: L{bytes} @ivar quietMessage: The full base pathname of the message to be used with the quiet. c|j|_tj|jt |_d|_tj|jttt|jd|j |_ ttt|jd|j |_d}d}tjj!|j||_tjj!|j||_t'|j"dzdj)t'|j$dzdj)|g|jj*j,d<|g|jj*j,d <t'|j"d zd 5}t/j0d d g|dddt'|j$d zd 5}t/j0ddg|dddy#1swYDxYw#1swYyxYw)a Set up a temporary directory for the queue, attempt managers with the noisy flag on and off, message files for use with each attempt manager, and a reactor. Also, register to be notified when log messages are generated. NTF noisyMessage quietMessagerArs noisyRelayer quietRelayerr>rzfrom-noisy@domainzto-noisy@domainzfrom-quiet@domainzto-quiet@domain)rrrrBrreventLogr! addObserver _logObserverrrEr/noisyAttemptMgrquietAttemptMgrrrcrKrLrrrfrGrDrE)rO noisyBaseName quietBaseNameenvelopes rSrxz_AttemptManagerTests.setUp skkm  )+   ))*. -j.E F  LL  / -j.E F  LL  ' & GGLLmDGGLLmD T   %s+113 T   %s+113@M$$,,^<@M$$,,^< $##d*D 1 LX KK,.?@( K L$##d*D 1 LX KK,.?@( K L L L L L Ls+I%IIIctj|jtj|j y)zO Unregister for log events and remove the temporary directory. N)r!removeObserverrQr[r\rr_s rSr]z_AttemptManagerTests.tearDown s( 4,,- dkk"r]c||_y)z A log observer. @type eventDict: L{dict} of L{bytes} -> L{object} @param eventDict: Information about the last informational log message generated. N)rO)rO eventDicts rSrQz!_AttemptManagerTests._logObserver s " r]cttt|j}|j |j y)z When an attempt manager is created without the noisy parameter, the noisy instance variable should default to true. N)rrEr/rrGr{rOams rStest_initNoisyDefaultz*_AttemptManagerTests.test_initNoisyDefault s- >z$++?VW X !r]cN|j|jjy)z When an attempt manager is created with the noisy parameter set to true, the noisy instance variable should be set to true. N)rGrRr{r_s rStest_initNoisyz#_AttemptManagerTests.test_initNoisy s ,,223r]cN|j|jjy)z When an attempt manager is created with the noisy parameter set to false, the noisy instance variable should be set to false. N)rrSr{r_s rStest_initQuietz#_AttemptManagerTests.test_initQuiet s --334r]cttt|j}|j |j t y)z When an attempt manager is created without the reactor parameter, the reactor instance variable should default to the global reactor. N)rrEr/rr<rr\s rStest_initReactorDefaultz,_AttemptManagerTests.test_initReactorDefault s1 >z$++?VW X W-r]cd|j|jj|jy)z When an attempt manager is created with a reactor provided, the reactor instance variable should default to that reactor. N)r<rRrr_s rStest_initReactorz%_AttemptManagerTests.test_initReactor s$ --55t||Dr]c|jjd|j|j|jy)zw For an attempt manager with the noisy flag set, notifySuccess should result in a log message. rMN)rRr]rKrGrOr_s rStest_notifySuccessNoisyz,_AttemptManagerTests.test_notifySuccessNoisy s0 **>4;L;LM  &r]c|jjd|j|j|jy)z| For an attempt manager with the noisy flag not set, notifySuccess should result in no log message. rNN)rSr]rLrrOr_s rStest_notifySuccessQuietz,_AttemptManagerTests.test_notifySuccessQuiet s2 **>4;L;LM 'r]r(r*c|jjd|j|j|jy)zw For an attempt manager with the noisy flag set, notifyFailure should result in a log message. rMN)rRr`rKrGrOr_s rStest_notifyFailureNoisyz,_AttemptManagerTests.test_notifyFailureNoisy! s0 **>4;L;LM  &r]c|jjd|j|j|jy)z| For an attempt manager with the noisy flag not set, notifyFailure should result in no log message. rNN)rSr`rLrrOr_s rStest_notifyFailureQuietz,_AttemptManagerTests.test_notifyFailureQuiet* s2 **>4;L;LM 'r]cp|jjd|j|jy)zt For an attempt manager with the noisy flag set, notifyDone should result in a log message. rMN)rRrbrGrOr_s rStest_notifyDoneNoisyz)_AttemptManagerTests.test_notifyDoneNoisy3 s( ''7  &r]cp|jjd|j|jy)zy For an attempt manager with the noisy flag not set, notifyDone should result in no log message. rNN)rSrbrrOr_s rStest_notifyDoneQuietz)_AttemptManagerTests.test_notifyDoneQuiet; s* ''7 'r]c|jjd|j|j|jj dy)z| For an attempt manager with the noisy flag set, notifyNoConnection should result in a log message. rMrN)rRnotifyNoConnectionrGrOrrir_s rStest_notifyNoConnectionNoisyz1_AttemptManagerTests.test_notifyNoConnectionNoisyC s: //?  & R r]c|jjd|j|j|jj dy)z For an attempt manager with the noisy flag not set, notifyNoConnection should result in no log message. rNrN)rSrtrrOrrir_s rStest_notifyNoConnectionQuietz1_AttemptManagerTests.test_notifyNoConnectionQuietL s< //? ' R r]N)rXrorprrxr]rQr^r`rbrdrfrhrjrrqrrrlrnrprrrurwr3r]rSrIrI s<+LZ#""45.E'( C   $&>?'@' C   $&>?(@('(!!r]rI)r email.messager email.parserrrrrrDr[rrqrRrr<hashlibrunittestrzope.interfacerrzope.interface.verifyrtwisted.cred.checkersr#twisted.cred.credentialstwisted.cred.portaltwisted.mail.aliastwisted.mail.mailtwisted.mail.maildirtwisted.mail.protocolstwisted.mail.relaytwisted.mail.relaymanagerrr twisted.internetr r r r rrtwisted.internet.deferrtwisted.internet.errorrrrrtwisted.internet.testingrrr twisted.mailrrr twisted.namesrtwisted.names.dnsrrrtwisted.names.errorrtwisted.pythonr r!twisted.python.filepathr"twisted.python.runtimer#twisted.trial.unittestr$r'rtrrrrrr _MaildirMailboxAppendMessageTaskr r%r5rOrXrrrrrrrr$r(r;rWrdrurrrrrrrrrFrrrrrrrr AliasGrouprrrrr/rErIr3r]rSrs  1- PP+  $5??,',/+ !CDe:he:Ee:P !CD G( GE G !CD# # E# L !CD5x5E5B !CD=7(=7E=7@ !CD !CDA>(A>EA>H10 BF'' BI&" !CDl>hl>El>^  !CDLHLEL^" !CDa>a>Ea>H11, !CD&7&7E&7R tzz.. +TZZ**+$$. !CD~&~&E~&B))(N N b. !CDD!8D!ED!r]