m %UIc@sdZdkZdddddgZddfZdfd YZd Zd Zd Zd fdYZdefdYZ dZ dddddddddddddddd dd!d"d#d$d%d&d'gZ d(d)d*d+d,d-d.gZ hd/d0<d1d0<d2d0<d3d0<d4d5<d6d7<d8d9<d:d5<d;d<<d=d9<d>d?<d@d<<dAdB<dCd?Os  cCs2y||}Wntj o dSnXt|S(sRetrieve a date field from a header. Retrieves a date field from the named header, returning a tuple compatible with time.mktime(). N(R R.tdataR6R R(R R.RG((Rtgetdatees  cCs2y||}Wntj o dSnXt|S(sRetrieve a date field from a header as a 10-tuple. The first 9 elements make up a tuple compatible with time.mktime(), and the 10th is the offset of the poster's time zone from GMT/UTC. N(R R.RGR6R R(R R.RG((Rt getdate_tzqs  cCs t|iS(s'Get the number of headers in a message.N(R'R R(R ((Rt__len__scCs|i|iS(s,Get a specific header, as from a dictionary.N(R RR.R+(R R.((Rt __getitem__scCs`||=||i|i<|d|}|id}x"|D]}|i i |dq>WdS(sSet the value of a header. Note: This is not a perfect inversion of __getitem__, because any changed headers get stuck at the end of the raw-headers list rather than where the altered header was. s: s N( R R.tvalueRR+ttexttsplittlinesRRR!(R R.RLRMROR((Rt __setitem__scCs|i}||ijodSn|i|=|d}t|}g}d}x~tt|i D]g}|i |}|| i|jo d}n|d i p d}n|o|i |qfqfWxt|D]}|i |=qWdS(s>Delete all occurrences of a specific header, if it is present.NR(ii(R.R+R RR'R/RR0trangeRR*RR1R!treversed(R R.R0R*RR/R((Rt __delitem__s*        RcCs|i}||ijo|i|SnT|d|}|id}x"|D]}|i i |dqOW||i|<|SdS(Ns: s ( R.R+t lowernameR RR7RMRNRORRR!(R R.R7RMRORRT((Rt setdefaults  cCs|i|ijS(s6Determine whether a message contains the named header.N(R.R+R R(R R.((Rthas_keyscCs|i|ijS(s6Determine whether a message contains the named header.N(R.R+R R(R R.((Rt __contains__scCs t|iS(N(titerR R(R ((Rt__iter__scCs |iiS(s*Get all of a message's header field names.N(R Rtkeys(R ((RRZscCs |iiS(s+Get all of a message's header field values.N(R Rtvalues(R ((RR[scCs |iiS(sWGet all of a message's headers. Returns a list of name, value tuples. N(R Rtitems(R ((RR\scCsdi|iS(NR(R4R R(R ((Rt__str__s( t__name__t __module__t__doc__RRRR&R%R$R2R3R5R R8tgetR=R@R>RHRIRJRKRPRSRURVRWRYRZR[R\R](((RRQs:    K                 cCst|djoz|ido7|ido'|dd!iddiddSn|ido|ido|dd!Sqn|S( sRemove quotes from a string.it"is\\s\s\"tN(R'tstrR tendswithtreplace(Re((Rtunquotes ' cCs|iddiddS(sAdd quotes around a string.s\s\\Rbs\"N(ReRg(Re((RtquotescCs0t|}|i}|pdSn |dSdS(s3Parse an address into a (realname, mailaddr) tuple.iN(NN(RtaddressRERFRR (RjRER((Rt parseaddrs   t AddrlistClasscBstZdZdZdZdZdZdZdZdZ dd Z d Z d Z d Z ed ZdZRS(s)Address parser class by Ben Escoto. To understand what this class does, it helps to have a copy of RFC 2822 in front of you. http://www.faqs.org/rfcs/rfc2822.html Note: this class interface is deprecated and may be removed in the future. Use rfc822.AddressList instead. cCsld|_d|_d|_d|_|i|i|i|_|iidd|_||_g|_ dS(sInitialize a new instance. `field' is an unparsed address header field, containing one or more addresses. s ()<>@,:;."[]is s t.RN( R tspecialstpostLWStCRtatomendsRgt phraseendstfieldt commentlist(R Rt((RRs     cCsx|it|ijoh|i|i|idjo|id|_q|i|idjo|ii|iqPqWdS(s*Parse up to the start of the next address.s it(N(R RoR'RtRpRuR!t getcomment(R ((RtgotonextscCs4g}x'|i}|o||7}q Pq W|S(sVParse all addresses. Returns a list containing all of the addresses. iN(R9R t getaddresstad(R R9Rz((RR>s cCsg|_|i|i}|i}|i}|ig}|it |i jo.|o#di |i|dfg}qhn|i |idjo=||_||_|i }di |i|fg}n|i |idjog}t |i }|id|_xM|it |i joZ|i|i|jo,|i |idjo|id|_Pn||i}qWn|i |idjof|i}|io4di |ddi |id |fg}qhdi ||fg}nY|o#di |i|dfg}n/|i |i|ijo|id|_n|i|it |i jo+|i |id jo|id|_n|S( sParse the next address.t is.@R(it;Rcs (t)t,N(R RuRxRotoldpostoldclt getphraselisttplistt returnlistR'RtR4t getaddrspectaddrspectfieldlenRyt getrouteaddrt routeaddrRn(R RRRRRRR((RRy*sP      '    '  4# 0cCs4|i|idjodSnd}|id|_|id}x|it|ijo|o|id}n|i|idjo|id|_Pnz|i|idjo|id|_d}nI|i|idjo|id|_n|i}|id|_P|iqHW|S( sParse a route address (Return-path value). This method just skips all the route stuff and returns the addrspec. RcNiiRRdt@R(( R RtRot expectrouteRxtadlistR't getdomainR(R RR((RRds2     cCsVg}|ix|it|ijo|i|idjo!|id|id|_ne|i|idjo|id|in3|i|i|ijoPn|i|i |iqW|it|ijp|i|idjodi |Sn|id|id|_|idi ||i S(sParse an RFC 2822 addr-spec.RmiRbs"%s"RRN( taslistR RxRoR'RtR!tgetquoteRrtgetatomR4R(R R((RRs(  0  cCs+g}x|it|ijo|i|i|ijo|id|_q |i|idjo|ii|iq |i|idjo|i|i q |i|idjo!|id|_|idq |i|i|i joPq |i|i q Wdi |S(s-Get the complete domain name from an address.iRvt[RmRN( tsdlistR RoR'RtRpRuR!RwtgetdomainliteralRrRR4(R R((RRs"icCsF|i|i|jodSndg}d}|id|_x|it|ijo|djo!|i|i|id}n|i|i|jo|id|_Pnq|o1|i|idjo|i|i qAn9|i|idjo d}n|i|i|i|id|_qAWdi |S(sParse a header fragment delimited by special characters. `beginchar' is the start character for the fragment. If self is not looking at an instance of `beginchar' then getdelimited returns the empty string. `endchars' is a sequence of allowable end-delimiting characters. Parsing stops when one of these is encountered. If `allowcomments' is non-zero, embedded RFC 2822 comments are allowed within the parsed fragment. RiiRvs\N( R RtRot beginchartslistRiR'R!tendcharst allowcommentsRwR4(R RRRRRi((Rt getdelimiteds,     cCs|idddS(s1Get a quote-delimited fragment from self's field.Rbs" iN(R R(R ((RRscCs|idddS(s7Get a parenthesis-delimited fragment from self's field.Rvs) iN(R R(R ((RRwscCsd|idddS(s!Parse an RFC 2822 domain-literal.s[%s]Rs] iN(R R(R ((RRscCsdg}|djo |i}nxa|it|ijoG|i|i|joPn|i|i|i|id|_q&Wdi|S(sParse an RFC 2822 atom. Optional atomends specifies a different set of end token delimiters (the default is to use self.atomends). This is used e.g. in getphraselist() since phrase endings must not include the `.' (which is legal in phrases).RiN( tatomlistRrR R RoR'RtR!R4(R RrR((RRs   cCsg}x|it|ijo|i|i|ijo|id|_q |i|idjo|i|iq |i|idjo|ii|i q |i|i|i joPq |i|i |i q W|S(sParse a sequence of RFC 2822 phrases. A phrase is a sequence of words, which are in turn either RFC 2822 atoms or quoted-strings. Phrases are canonicalized by squeezing all runs of continuous whitespace into one space. iRbRvN( RR RoR'RtRpR!RRuRwRsR(R R((RRs(R^R_R`RRxR>RyRRRRRRwRR RR(((RRls    :   %    cBsVtZdZdZdZdZdZdZdZdZ dZ RS( s@An AddressList encapsulates a list of parsed RFC 2822 addresses.cCs7ti|||o|i|_n g|_dS(N(RlRR RtR>RF(R Rt((RR scCs t|iS(N(R'R RF(R ((RRJscCsditt|iS(Ns, (R4tmaptdump_address_pairR RF(R ((RR]scCsUtd}|i|_x5|iD]*}||ijo|ii|q#q#W|S(N(RR tnewaddrR RFtotherR#R!(R RRR#((Rt__add__s   cCs<x5|iD]*}||ijo|ii|q q W|S(N(RRFR#R R!(R RR#((Rt__iadd__!s  cCsHtd}x5|iD]*}||ijo|ii|qqW|S(N(RR RR RFR#RR!(R RRR#((Rt__sub__(s   cCs<x5|iD]*}||ijo|ii|q q W|S(N(RRFR#R tremove(R RR#((Rt__isub__0s  cCs |i|S(N(R RFtindex(R R((RRK7s( R^R_R`RRJR]RRRRRK(((RR s       cCs7|do d|dd|ddSn |dSdS(s4Dump a (name, address) pair in a canonicalized form.iRbs" R8RIRRt localtimetasctimethhmmsstdivmodthhmmtssthhRRR/RR'RZR[R\(RhRRRRRR R,RRRiRRR RRRkRlRRRRR/RRRRR RR((Rt?Gst    2 N Q