B
    \ Çc>3 ã               @   sR  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZyddlZW n ek
rˆ   dZY nX ddddddd	d
dddddddddgZej d¡ZG dd„ dƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd	„ d	ejjƒZG d d
„ d
eƒZG d!d"„ d"eƒZG d#d„ deƒZG d$d„ deƒZG d%d„ deƒZ G d&d„ deƒZ!G d'd(„ d(ƒZ"G d)d*„ d*e"ƒZ#d=d,d-„Z$d.d/„ Z%d0d1„ Z&d2d3„ Z'd4d5„ Z(d6d7„ Z)G d8d„ de*ƒZ+G d9d„ de+ƒZ,G d:d„ de+ƒZ-G d;d„ de+ƒZ.G d<d„ de+ƒZ/dS )>zDRead/write support for Maildir, mbox, MH, Babyl, and MMDF mailboxes.é    NÚMailboxÚMaildirÚmboxÚMHÚBabylÚMMDFÚMessageÚMaildirMessageÚmboxMessageÚ	MHMessageÚBabylMessageÚMMDFMessageÚErrorÚNoSuchMailboxErrorÚNotEmptyErrorÚExternalClashErrorÚFormatErrorÚasciic               @   s  e Zd ZdZdCdd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dDdd„Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ ZdEd0d1„Zd2d3„ ZdFd4d5„Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Z d>d?„ Z!d@Z"dGdAdB„Z#dS )Hr   z*A group of messages in a particular place.NTc             C   s    t j t j |¡¡| _|| _dS )zInitialize a Mailbox instance.N)ÚosÚpathÚabspathÚ
expanduserÚ_pathÚ_factory)Úselfr   ÚfactoryÚcreate© r   úlib/python3.7/mailbox.pyÚ__init__$   s    zMailbox.__init__c             C   s   t dƒ‚dS )z$Add message and return assigned key.z&Method must be implemented by subclassN)ÚNotImplementedError)r   Úmessager   r   r   Úadd)   s    zMailbox.addc             C   s   t dƒ‚dS )z=Remove the keyed message; raise KeyError if it doesn't exist.z&Method must be implemented by subclassN)r    )r   Úkeyr   r   r   Úremove-   s    zMailbox.removec             C   s   |   |¡ d S )N)r$   )r   r#   r   r   r   Ú__delitem__1   s    zMailbox.__delitem__c             C   s(   y|   |¡ W n tk
r"   Y nX dS )z'If the keyed message exists, remove it.N)r$   ÚKeyError)r   r#   r   r   r   Údiscard4   s    zMailbox.discardc             C   s   t dƒ‚dS )z>Replace the keyed message; raise KeyError if it doesn't exist.z&Method must be implemented by subclassN)r    )r   r#   r!   r   r   r   Ú__setitem__;   s    zMailbox.__setitem__c             C   s$   y
|   |¡S  tk
r   |S X dS )z9Return the keyed message, or default if it doesn't exist.N)Ú__getitem__r&   )r   r#   Údefaultr   r   r   Úget?   s    
zMailbox.getc          	   C   s6   | j s|  |¡S t |  |¡¡}|   |¡S Q R X dS )z=Return the keyed message; raise KeyError if it doesn't exist.N)r   Úget_messageÚ
contextlibÚclosingÚget_file)r   r#   Úfiler   r   r   r)   F   s    
zMailbox.__getitem__c             C   s   t dƒ‚dS )z4Return a Message representation or raise a KeyError.z&Method must be implemented by subclassN)r    )r   r#   r   r   r   r,   N   s    zMailbox.get_messagec             C   s   t  |  |¡¡ ¡ S )zœReturn a string representation or raise a KeyError.

        Uses email.message.Message to create a 7bit clean string
        representation of the message.)ÚemailÚmessage_from_bytesÚ	get_bytesÚ	as_string)r   r#   r   r   r   Ú
get_stringR   s    zMailbox.get_stringc             C   s   t dƒ‚dS )z8Return a byte string representation or raise a KeyError.z&Method must be implemented by subclassN)r    )r   r#   r   r   r   r3   Y   s    zMailbox.get_bytesc             C   s   t dƒ‚dS )z6Return a file-like representation or raise a KeyError.z&Method must be implemented by subclassN)r    )r   r#   r   r   r   r/   ]   s    zMailbox.get_filec             C   s   t dƒ‚dS )zReturn an iterator over keys.z&Method must be implemented by subclassN)r    )r   r   r   r   Úiterkeysa   s    zMailbox.iterkeysc             C   s   t |  ¡ ƒS )zReturn a list of keys.)Úlistr6   )r   r   r   r   Úkeyse   s    zMailbox.keysc          	   c   s@   x:|   ¡ D ].}y| | }W n tk
r0   w
Y nX |V  q
W dS )z%Return an iterator over all messages.N)r6   r&   )r   r#   Úvaluer   r   r   Ú
itervaluesi   s    zMailbox.itervaluesc             C   s   |   ¡ S )N)r:   )r   r   r   r   Ú__iter__r   s    zMailbox.__iter__c             C   s   t |  ¡ ƒS )z,Return a list of messages. Memory intensive.)r7   r:   )r   r   r   r   Úvaluesu   s    zMailbox.valuesc          	   c   sD   x>|   ¡ D ]2}y| | }W n tk
r0   w
Y nX ||fV  q
W dS )z.Return an iterator over (key, message) tuples.N)r6   r&   )r   r#   r9   r   r   r   Ú	iteritemsy   s    zMailbox.iteritemsc             C   s   t |  ¡ ƒS )z9Return a list of (key, message) tuples. Memory intensive.)r7   r=   )r   r   r   r   Úitems‚   s    zMailbox.itemsc             C   s   t dƒ‚dS )z9Return True if the keyed message exists, False otherwise.z&Method must be implemented by subclassN)r    )r   r#   r   r   r   Ú__contains__†   s    zMailbox.__contains__c             C   s   t dƒ‚dS )z*Return a count of messages in the mailbox.z&Method must be implemented by subclassN)r    )r   r   r   r   Ú__len__Š   s    zMailbox.__len__c             C   s    x|   ¡ D ]}|  |¡ q
W dS )zDelete all messages.N)r8   r'   )r   r#   r   r   r   ÚclearŽ   s    zMailbox.clearc             C   s0   y| | }W n t k
r    |S X |  |¡ |S )z3Delete the keyed message and return it, or default.)r&   r'   )r   r#   r*   Úresultr   r   r   Úpop“   s    
zMailbox.popc             C   s*   x$|   ¡ D ]}||  |¡fS W tdƒ‚dS )z6Delete an arbitrary (key, message) pair and return it.zNo messages in mailboxN)r6   rC   r&   )r   r#   r   r   r   Úpopitemœ   s    zMailbox.popitemc          	   C   sx   t |dƒr| ¡ }nt |dƒr(| ¡ }n|}d}x6|D ].\}}y|| |< W q6 tk
rb   d}Y q6X q6W |rttdƒ‚dS )z4Change the messages that correspond to certain keys.r=   r>   FTzNo message with key(s)N)Úhasattrr=   r>   r&   )r   ÚargÚsourceZbad_keyr#   r!   r   r   r   Úupdate£   s    



zMailbox.updatec             C   s   t dƒ‚dS )z&Write any pending changes to the disk.z&Method must be implemented by subclassN)r    )r   r   r   r   Úflush´   s    zMailbox.flushc             C   s   t dƒ‚dS )zLock the mailbox.z&Method must be implemented by subclassN)r    )r   r   r   r   Úlock¸   s    zMailbox.lockc             C   s   t dƒ‚dS )z#Unlock the mailbox if it is locked.z&Method must be implemented by subclassN)r    )r   r   r   r   Úunlock¼   s    zMailbox.unlockc             C   s   t dƒ‚dS )zFlush and close the mailbox.z&Method must be implemented by subclassN)r    )r   r   r   r   ÚcloseÀ   s    zMailbox.closec             C   s,   y
|  d¡S  tk
r&   tdƒ‚Y nX d S )Nr   z?String input must be ASCII-only; use bytes or a Message instead)ÚencodeÚUnicodeErrorÚ
ValueError)r   r!   r   r   r   Ú_string_to_bytesÄ   s    
zMailbox._string_to_bytesFc       	      C   sþ  t |tjjƒrvt ¡ }tj ||d¡}| |¡ | 	d¡ | 
¡ }| dt¡}| |¡ | jrr| t¡sr| t¡ n„t |tttjfƒrt |tjƒr¬t dtd¡ | ¡ }t |tƒrÀ|  |¡}|rÐ| dd¡}| dt¡}| |¡ | jrú| t¡sú| t¡ nôt|dƒrêt|dƒr2t d	td¡ |j}d
}xŒ| ¡ }| d¡r^|d
d… d }n| d¡rz|d
d… d }|s‚P |r¤| d¡r¤d|dd
…  }| dt¡}| |¡ |}q8W | jrú|rú| t¡sú| t¡ ntdt|ƒ ƒ‚d
S )z%Dump message contents to target file.r   ó   
z8Use of StringIO input is deprecated, use BytesIO insteadé   s   
From s   
>From ÚreadÚbufferzDUse of text mode files is deprecated, use a binary mode file insteadNs   
éþÿÿÿó   éÿÿÿÿs   From s   >From é   zInvalid message type: %s)Ú
isinstancer1   r!   r   ÚioÚBytesIOÚ	generatorÚBytesGeneratorÚflattenÚseekrS   ÚreplaceÚlinesepÚwriteÚ_append_newlineÚendswithÚstrÚbytesÚStringIOÚwarningsÚwarnÚDeprecationWarningÚgetvaluerP   rE   rT   ÚreadlineÚ
startswithÚ	TypeErrorÚtype)	r   r!   ÚtargetZmangle_from_rT   ÚgenÚdataZlastlineÚliner   r   r   Ú_dump_messageÑ   sZ    







zMailbox._dump_message)NT)N)N)N)F)$Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r"   r$   r%   r'   r(   r+   r)   r,   r5   r3   r/   r6   r8   r:   r;   r<   r=   r>   r?   r@   rA   rC   rD   rH   rI   rJ   rK   rL   rP   rc   rt   r   r   r   r   r   !   sB   

		
	
c               @   sÚ   e Zd ZdZdZd6dd„Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ ZdS )7r   zA qmail-style Maildir mailbox.ú:NTc             C   s°   t  | |||¡ tj | jd¡tj | jd¡tj | jd¡dœ| _tj | j¡sŽ|r„t | jd¡ x*| j 	¡ D ]}t |d¡ qnW n
t
| jƒ‚i | _dddœ| _d| _d| _d	S )
zInitialize a Maildir instance.ÚtmpÚnewÚcur)rz   r{   r|   iÀ  r   )r|   r{   gš™™™™™¹?N)r   r   r   r   Újoinr   Ú_pathsÚexistsÚmkdirr<   r   Ú_tocÚ_toc_mtimesÚ
_last_readÚ_skewfactor)r   Údirnamer   r   r   r   r   r   r     s    
zMaildir.__init__c          
   C   s~  |   ¡ }y|  ||¡ W n* tk
rB   | ¡  t |j¡ ‚ Y nX t|ƒ t|t	ƒr|| 
¡ }| j| ¡  }|| jkr„d}nd}d}tj |j¡ | j¡d }tj | j||| ¡}t|t	ƒrÞt |jtj |j¡| ¡ f¡ yLyt |j|¡ W n( ttfk
r   t |j|¡ Y nX t |j¡ W nN tk
rx } z.t |j¡ |jtjkrftd| ƒ‚n‚ W dd}~X Y nX |S )z$Add message and return assigned key.Ú r{   r   z$Name clash with existing message: %sN)Ú_create_tmprt   ÚBaseExceptionrL   r   r$   ÚnameÚ_sync_closerY   r	   Ú
get_subdirÚcolonÚget_infor   ÚbasenameÚsplitr}   r   ÚutimeÚgetatimeÚget_dateÚlinkÚAttributeErrorÚPermissionErrorÚrenameÚOSErrorÚerrnoZEEXISTr   )r   r!   Ztmp_fileÚsubdirÚsuffixÚuniqÚdestÚer   r   r   r"   !  sB    



zMaildir.addc             C   s    t  t j | j|  |¡¡¡ dS )z=Remove the keyed message; raise KeyError if it doesn't exist.N)r   r$   r   r}   r   Ú_lookup)r   r#   r   r   r   r$   K  s    zMaildir.removec          	   C   s,   y|   |¡ W n ttfk
r&   Y nX dS )z'If the keyed message exists, remove it.N)r$   r&   ÚFileNotFoundError)r   r#   r   r   r   r'   O  s    zMaildir.discardc             C   sÊ   |   |¡}|  |¡}|   |¡}t|tƒr.|}n|}tj |¡}| j|kr`| j| | j¡d  }nd}|  	|¡ tj 
| j|¡}	tj 
| j||| ¡}
t|tƒrºt |	tj |	¡| ¡ f¡ t |	|
¡ dS )z>Replace the keyed message; raise KeyError if it doesn't exist.rW   r†   N)rž   r"   rY   r	   r   r   r…   rŒ   r   r'   r}   r   r   r‘   r’   r–   )r   r#   r!   Zold_subpathZtemp_keyZtemp_subpathZdominant_subpathr™   rš   Ztmp_pathÚnew_pathr   r   r   r(   W  s"    






zMaildir.__setitem__c          	   C   s¢   |   |¡}ttj | j|¡dƒ }| jr4|  |¡}nt|ƒ}W dQ R X tj |¡\}}| 	|¡ | j
|kr€| | | j
¡d ¡ | tj tj | j|¡¡¡ |S )z4Return a Message representation or raise a KeyError.ÚrbNrW   )rž   Úopenr   r   r}   r   r   r	   r   Ú
set_subdirrŒ   Úset_infoÚset_dateÚgetmtime)r   r#   ZsubpathÚfÚmsgr™   r‰   r   r   r   r,   r  s    


zMaildir.get_messagec          	   C   s8   t tj | j|  |¡¡dƒ}| ¡  td¡S Q R X dS )z2Return a bytes representation or raise a KeyError.r¡   rQ   N)	r¢   r   r   r}   r   rž   rS   r`   ra   )r   r#   r§   r   r   r   r3     s    zMaildir.get_bytesc             C   s$   t tj | j|  |¡¡dƒ}t|ƒS )z6Return a file-like representation or raise a KeyError.r¡   )r¢   r   r   r}   r   rž   Ú
_ProxyFile)r   r#   r§   r   r   r   r/   †  s    zMaildir.get_filec          	   c   sH   |   ¡  x:| jD ]0}y|  |¡ W n tk
r8   wY nX |V  qW dS )zReturn an iterator over keys.N)Ú_refreshr   rž   r&   )r   r#   r   r   r   r6   ‹  s    zMaildir.iterkeysc             C   s   |   ¡  || jkS )z9Return True if the keyed message exists, False otherwise.)rª   r   )r   r#   r   r   r   r?   •  s    zMaildir.__contains__c             C   s   |   ¡  t| jƒS )z*Return a count of messages in the mailbox.)rª   Úlenr   )r   r   r   r   r@   š  s    zMaildir.__len__c             C   s   dS )z"Write any pending changes to disk.Nr   )r   r   r   r   rI   Ÿ  s    zMaildir.flushc             C   s   dS )zLock the mailbox.Nr   )r   r   r   r   rJ   ¥  s    zMaildir.lockc             C   s   dS )z#Unlock the mailbox if it is locked.Nr   )r   r   r   r   rK   ©  s    zMaildir.unlockc             C   s   dS )zFlush and close the mailbox.Nr   )r   r   r   r   rL   ­  s    zMaildir.closec             C   s`   g }xVt  | j¡D ]F}t|ƒdkr|d dkrt j t j | j|¡¡r| |dd… ¡ qW |S )zReturn a list of folder names.é   r   Ú.N)r   Úlistdirr   r«   r   Úisdirr}   Úappend)r   rB   Úentryr   r   r   Úlist_folders±  s    zMaildir.list_foldersc             C   s    t tj | jd| ¡| jddS )z/Return a Maildir instance for the named folder.r­   F)r   r   )r   r   r   r}   r   r   )r   Úfolderr   r   r   Ú
get_folderº  s    zMaildir.get_folderc             C   s\   t j | jd| ¡}t|| jd}t j |d¡}t j |¡sXt  t  |t j	t j
B d¡¡ |S )z>Create a folder and return a Maildir instance representing it.r­   )r   Zmaildirfolderi¶  )r   r   r}   r   r   r   r   rL   r¢   ÚO_CREATÚO_WRONLY)r   r³   r   rB   Zmaildirfolder_pathr   r   r   Ú
add_folderÀ  s    zMaildir.add_folderc             C   s,  t j | jd| ¡}xTt  t j |d¡¡t  t j |d¡¡ D ](}t|ƒdk sZ|d dkr>td| ƒ‚q>W xPt  |¡D ]B}|dkrv|dkrv|dkrvt j t j ||¡¡rvtd||f ƒ‚qvW x`t j|d	d
D ]N\}}}x |D ]}t  	t j ||¡¡ qÜW x |D ]}t  
t j ||¡¡ qþW qÌW t  
|¡ dS )z-Delete the named folder, which must be empty.r­   r{   r|   r¬   r   zFolder contains message(s): %srz   z%Folder contains subdirectory '%s': %sF)ÚtopdownN)r   r   r}   r   r®   r«   r   r¯   Úwalkr$   Úrmdir)r   r³   r   r±   ÚrootÚdirsÚfilesr   r   r   Úremove_folderÊ  s     

zMaildir.remove_folderc             C   s\   t   ¡ }xNt tj | jd¡¡D ]4}tj | jd|¡}|tj |¡ dkr t |¡ q W dS )zDelete old files in "tmp".rz   i@ú N)Útimer   r®   r   r}   r   r‘   r$   )r   Únowr±   r   r   r   r   ÚcleanÝ  s
    zMaildir.cleanr¬   c             C   sÒ   t   ¡ }t ¡ }d|kr$| dd¡}d|kr8| dd¡}dt|ƒt|d d ƒt ¡ tj|f }tj	 
| jd|¡}yt |¡ W n@ tk
rÀ   t jd7  _yt|ƒS  tk
rº   Y nX Y nX td	| ƒ‚d
S )z=Create a file in the tmp subdirectory and open and return it.ú/z\057ry   z\072z%s.M%sP%sQ%s.%sr¬   g    €„.Arz   z&Name clash prevented file creation: %sN)r¿   ÚsocketÚgethostnamer`   Úintr   Úgetpidr   Ú_countr   r}   r   ÚstatrŸ   Ú_create_carefullyÚFileExistsErrorr   )r   rÀ   Zhostnamer›   r   r   r   r   r‡   ç  s&    zMaildir._create_tmpc             C   sä   t   ¡ | j d| j krbd}x<| jD ]2}tj | j| ¡}|| j| krLd}|| j|< q$W |sbdS i | _xl| jD ]b}| j| }xRt 	|¡D ]D}tj 
||¡}tj |¡rªqŠ| | j¡d }tj 
||¡| j|< qŠW qpW t   ¡ | _dS )z!Update table of contents mapping.é   FTNr   )r¿   rƒ   r„   r‚   r   r   r¦   r~   r   r®   r}   r¯   r   rŒ   )r   Zrefreshr™   Úmtimer   r±   Úpr›   r   r   r   rª   ÿ  s&    
zMaildir._refreshc             C   s|   y,t j t j | j| j| ¡¡r*| j| S W n tk
r@   Y nX |  ¡  y
| j| S  tk
rv   td| ƒd‚Y nX dS )z=Use TOC to return subpath for given key, or raise a KeyError.zNo message with key: %sN)r   r   r   r}   r   r   r&   rª   )r   r#   r   r   r   rž   #  s    
zMaildir._lookupc             C   sV   t | dƒs|  ¡ | _x<y| t| jƒ S  tk
r8   dS  tk
rL   wY qX qW dS )z0Return the next message in a one-time iteration.Ú_onetime_keysN)rE   r6   rÎ   ÚnextÚStopIterationr&   )r   r   r   r   rÏ   1  s    

zMaildir.next)NT)ru   rv   rw   rx   rŒ   r   r"   r$   r'   r(   r,   r3   r/   r6   r?   r@   rI   rJ   rK   rL   r²   r´   r·   r¾   rÁ   rÇ   r‡   rª   rž   rÏ   r   r   r   r   r     s6   
*
	
$c               @   s”   e Zd ZdZd$dd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd%d d!„Zd"d#„ ZdS )&Ú_singlefileMailboxzA single-file mailbox.NTc          
   C   s¾   t  | |||¡ yt| jdƒ}W nn tk
rŽ } zP|jtjkr\|rPt| jdƒ}q~t| jƒ‚n"|jtjtj	fkr|t| jdƒ}n‚ W dd}~X Y nX || _
d| _d| _d| _d| _d| _d| _dS )z!Initialize a single-file mailbox.zrb+zwb+r¡   Nr   F)r   r   r¢   r   r—   r˜   ÚENOENTr   ÚEACCESÚEROFSÚ_filer   Ú	_next_keyÚ_pendingÚ_pending_syncÚ_lockedÚ_file_length)r   r   r   r   r§   r   r   r   r   r   A  s$    z_singlefileMailbox.__init__c             C   s8   |   ¡  |  |¡| j| j< |  jd7  _d| _| jd S )z$Add message and return assigned key.r¬   T)rž   Ú_append_messager   rÖ   rØ   )r   r!   r   r   r   r"   X  s
    z_singlefileMailbox.addc             C   s   |   |¡ | j|= d| _dS )z=Remove the keyed message; raise KeyError if it doesn't exist.TN)rž   r   r×   )r   r#   r   r   r   r$   b  s    
z_singlefileMailbox.removec             C   s$   |   |¡ |  |¡| j|< d| _dS )z>Replace the keyed message; raise KeyError if it doesn't exist.TN)rž   rÛ   r   r×   )r   r#   r!   r   r   r   r(   h  s    
z_singlefileMailbox.__setitem__c             c   s   |   ¡  | j ¡ E dH  dS )zReturn an iterator over keys.N)rž   r   r8   )r   r   r   r   r6   n  s    z_singlefileMailbox.iterkeysc             C   s   |   ¡  || jkS )z9Return True if the keyed message exists, False otherwise.)rž   r   )r   r#   r   r   r   r?   s  s    z_singlefileMailbox.__contains__c             C   s   |   ¡  t| jƒS )z*Return a count of messages in the mailbox.)rž   r«   r   )r   r   r   r   r@   x  s    z_singlefileMailbox.__len__c             C   s   | j st| jƒ d| _ dS )zLock the mailbox.TN)rÙ   Ú
_lock_filerÕ   )r   r   r   r   rJ   }  s    
z_singlefileMailbox.lockc             C   s   | j rt| jƒ d| _ dS )z#Unlock the mailbox if it is locked.FN)rÙ   Ú_unlock_filerÕ   )r   r   r   r   rK   ƒ  s    
z_singlefileMailbox.unlockc       
      C   sì  | j s | jrt| jƒ d| _dS | jdk	s.t‚| j dd¡ | j ¡ }|| jkrbt	d| j|f ƒ‚t
| jƒ}y¬i }|  |¡ xŽt| j ¡ ƒD ]|}| j| \}}| j |¡ |  |¡ | ¡ }x0| j td|| j ¡  ƒ¡}|sàP | |¡ q¾W || ¡ f||< |  |¡ qŒW | ¡ | _W n"   | ¡  t |j¡ ‚ Y nX t|ƒ | j ¡  t | j¡j}	t |j|	¡ yt |j| j¡ W n2 tk
r°   t | j¡ t |j| j¡ Y nX t| jdƒ| _|| _d| _ d| _| jrèt | jdd dS )	z"Write any pending changes to disk.FNr   rË   z4Size of mailbox file changed (expected %i, found %i)i   zrb+)Údotlock)!r×   rØ   Ú_sync_flushrÕ   r   ÚAssertionErrorr_   ÚtellrÚ   r   Ú_create_temporaryr   Ú_pre_mailbox_hookÚsortedr8   Ú_pre_message_hookrS   Úminrb   Ú_post_message_hookrL   r   r$   r‰   rŠ   rÈ   Úst_modeÚchmodr–   rÊ   r¢   rÙ   rÜ   )
r   Zcur_lenZnew_fileZnew_tocr#   ÚstartÚstopZ	new_startrT   Úmoder   r   r   rI   ‰  s`    







z_singlefileMailbox.flushc             C   s   dS )z,Called before writing the mailbox to file f.Nr   )r   r§   r   r   r   rã   É  s    z$_singlefileMailbox._pre_mailbox_hookc             C   s   dS )z-Called before writing each message to file f.Nr   )r   r§   r   r   r   rå   Í  s    z$_singlefileMailbox._pre_message_hookc             C   s   dS )z,Called after writing each message to file f.Nr   )r   r§   r   r   r   rç   Ñ  s    z%_singlefileMailbox._post_message_hookc             C   s4   z|   ¡  W dz| jr|  ¡  W d| j ¡  X X dS )zFlush and close the mailbox.N)rI   rÙ   rK   rÕ   rL   )r   r   r   r   rL   Õ  s    z_singlefileMailbox.closec             C   sL   | j dkr|  ¡  |dk	rHy
| j | S  tk
rF   td| ƒd‚Y nX dS )z'Return (start, stop) or raise KeyError.NzNo message with key: %s)r   Ú_generate_tocr&   )r   r#   r   r   r   rž   à  s    

z_singlefileMailbox._lookupc             C   sœ   | j  dd¡ | j  ¡ }t| jƒdkr8| js8|  | j ¡ y&|  | j ¡ |  |¡}|  	| j ¡ W n" t
k
r€   | j  |¡ ‚ Y nX | j  ¡  | j  ¡ | _|S )z;Append message to mailbox and return (start, stop) offsets.r   rË   )rÕ   r_   rá   r«   r   r×   rã   rå   Ú_install_messagerç   rˆ   ÚtruncaterI   rÚ   )r   r!   ZbeforeZoffsetsr   r   r   rÛ   ê  s    


z"_singlefileMailbox._append_message)NT)N)ru   rv   rw   rx   r   r"   r$   r(   r6   r?   r@   rJ   rK   rI   rã   rå   rç   rL   rž   rÛ   r   r   r   r   rÑ   >  s"   

@

rÑ   c               @   sB   e Zd ZdZdZdd„ Zddd„Zddd	„Zdd
d„Zdd„ Z	dS )Ú	_mboxMMDFzAn mbox or MMDF mailbox.Tc             C   sp   |   |¡\}}| j |¡ | j ¡  td¡}| j || j ¡  ¡}|  | td¡¡}| 	|dd…  
d¡¡ |S )z4Return a Message representation or raise a KeyError.ó    rQ   rX   Nr   )rž   rÕ   r_   rl   r`   ra   rS   rá   Ú_message_factoryÚset_fromÚdecode)r   r#   rê   rë   Ú	from_lineÚstringr¨   r   r   r   r,     s    z_mboxMMDF.get_messageFc             C   s   t  |  |¡¡j|dS )z3Return a string representation or raise a KeyError.)Úunixfrom)r1   r2   r3   r4   )r   r#   Úfrom_r   r   r   r5     s    z_mboxMMDF.get_stringc             C   sJ   |   |¡\}}| j |¡ |s(| j ¡  | j || j ¡  ¡}| td¡S )z3Return a string representation or raise a KeyError.rQ   )rž   rÕ   r_   rl   rS   rá   r`   ra   )r   r#   rø   rê   rë   rö   r   r   r   r3     s    
z_mboxMMDF.get_bytesc             C   s<   |   |¡\}}| j |¡ |s(| j ¡  t| j| j ¡ |ƒS )z6Return a file-like representation or raise a KeyError.)rž   rÕ   r_   rl   Ú_PartialFilerá   )r   r#   rø   rê   rë   r   r   r   r/     s
    
z_mboxMMDF.get_filec             C   s  d}t |tƒr|  |¡}t |tƒrf| d¡rf| d¡}|dkr\|d|… }||d d… }q°|}d}nJt |tƒrˆ| ¡  d¡}d| }n(t |t	j
jƒr°| ¡ }|dk	r°| d¡}|dkrÎdt t ¡ ¡ ¡  }| j ¡ }| j |t ¡ |  || j| j¡ | j ¡ }||fS )	z1Format a message and blindly write to self._file.Ns   From rQ   rW   r¬   rñ   r   s   From MAILER-DAEMON )rY   re   rP   rf   rm   ÚfindÚ_mboxMMDFMessageÚget_fromrM   r1   r!   r   Úget_unixfromr¿   ÚasctimeÚgmtimerÕ   rá   rb   ra   rt   Ú_mangle_from_)r   r!   rõ   ÚnewlineZauthorrê   rë   r   r   r   rî   &  s0    







z_mboxMMDF._install_messageN)F)F)F)
ru   rv   rw   rx   r   r,   r5   r3   r/   rî   r   r   r   r   rð     s   


	
rð   c               @   s2   e Zd ZdZdZdZd
dd„Zdd„ Zdd	„ ZdS )r   zA classic mbox mailbox.TNc             C   s   t | _t | |||¡ dS )zInitialize an mbox mailbox.N)r
   rò   rð   r   )r   r   r   r   r   r   r   r   L  s    zmbox.__init__c             C   s   |  t¡ dS )z,Called after writing each message to file f.N)rb   ra   )r   r§   r   r   r   rç   Q  s    zmbox._post_message_hookc             C   sì   g g  }}d}| j  d¡ x | j  ¡ }| j  ¡ }| d¡r|t|ƒt|ƒk rl|rb| |ttƒ ¡ n
| |¡ | |¡ d}q|s¦|r˜| |ttƒ ¡ n
| |¡ P q|tkr´d}qd}qW tt	t
||ƒƒƒ| _t| jƒ| _| j  ¡ | _dS )z0Generate key-to-(start, stop) table of contents.Fr   s   From TN)rÕ   r_   rá   rl   rm   r«   r°   ra   ÚdictÚ	enumerateÚzipr   rÖ   rÚ   )r   ÚstartsÚstopsZlast_was_emptyÚline_posrs   r   r   r   rí   U  s0    






zmbox._generate_toc)NT)	ru   rv   rw   rx   r   rc   r   rç   rí   r   r   r   r   r   C  s   
c               @   s2   e Zd ZdZddd„Zdd„ Zdd	„ Zd
d„ ZdS )r   zAn MMDF mailbox.NTc             C   s   t | _t | |||¡ dS )zInitialize an MMDF mailbox.N)r   rò   rð   r   )r   r   r   r   r   r   r   r   z  s    zMMDF.__init__c             C   s   |  dt ¡ dS )z-Called before writing each message to file f.s   N)rb   ra   )r   r§   r   r   r   rå     s    zMMDF._pre_message_hookc             C   s   |  td t ¡ dS )z,Called after writing each message to file f.s   N)rb   ra   )r   r§   r   r   r   rç   ƒ  s    zMMDF._post_message_hookc             C   sæ   g g  }}| j  d¡ d}xŒ|}| j  ¡ }| j  ¡ }| dt ¡rž| |¡ xV|}| j  ¡ }| j  ¡ }|dt krˆ| |ttƒ ¡ P qN|sN| |¡ P qNW q|sP qW tt	t
||ƒƒƒ| _t| jƒ| _| j  dd¡ | j  ¡ | _dS )z0Generate key-to-(start, stop) table of contents.r   s   rË   N)rÕ   r_   rl   rá   rm   ra   r°   r«   r  r  r  r   rÖ   rÚ   )r   r  r  Únext_posr  rs   r   r   r   rí   ‡  s2    






zMMDF._generate_toc)NT)ru   rv   rw   rx   r   rå   rç   rí   r   r   r   r   r   w  s
   
c               @   sÂ   e Zd ZdZd0dd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ ZdS )1r   zAn MH mailbox.NTc             C   st   t  | |||¡ tj | j¡sj|r`t | jd¡ t t tj 	| jd¡tj
tjB tjB d¡¡ n
t| jƒ‚d| _dS )zInitialize an MH instance.iÀ  z.mh_sequencesi€  FN)r   r   r   r   r   r   r€   rL   r¢   r}   rµ   ÚO_EXCLr¶   r   rÙ   )r   r   r   r   r   r   r   r   §  s    
zMH.__init__c             C   sä   |   ¡ }t|ƒdkrd}nt|ƒd }tj | jt|ƒ¡}t|ƒ}d}zŠ| j	rVt
|ƒ zfy|  ||¡ W n: tk
r¢   | j	r†t|ƒ t|ƒ d}t |¡ ‚ Y nX t|tƒrº|  ||¡ W d| j	rÌt|ƒ X W d|sÞt|ƒ X |S )z$Add message and return assigned key.r   r¬   FTN)r8   r«   Úmaxr   r   r}   r   re   rÉ   rÙ   rÜ   rt   rˆ   rÝ   rŠ   r$   rY   r   Ú_dump_sequences)r   r!   r8   Znew_keyr    r§   Úclosedr   r   r   r"   ³  s6    


zMH.addc          
   C   sx   t j | jt|ƒ¡}yt|dƒ}W n> tk
r` } z |jtjkrNt	d| ƒ‚n‚ W dd}~X Y nX | 
¡  t  |¡ dS )z=Remove the keyed message; raise KeyError if it doesn't exist.zrb+zNo message with key: %sN)r   r   r}   r   re   r¢   r—   r˜   rÒ   r&   rL   r$   )r   r#   r   r§   r   r   r   r   r$   Õ  s    z	MH.removec          
   C   sÖ   t j | jt|ƒ¡}yt|dƒ}W n> tk
r` } z |jtjkrNt	d| ƒ‚n‚ W dd}~X Y nX zd| j
rrt|ƒ z@t  t  |t jt jB ¡¡ |  ||¡ t|tƒr°|  ||¡ W d| j
rÂt|ƒ X W dt|ƒ X dS )z>Replace the keyed message; raise KeyError if it doesn't exist.zrb+zNo message with key: %sN)r   r   r}   r   re   r¢   r—   r˜   rÒ   r&   rÙ   rÜ   rL   r¶   ÚO_TRUNCrt   rY   r   r  rÝ   rŠ   )r   r#   r!   r   r§   r   r   r   r   r(   ã  s$    
zMH.__setitem__c          
   C   sì   y@| j r$ttj | jt|ƒ¡dƒ}nttj | jt|ƒ¡dƒ}W n> tk
r~ } z |jtj	krlt
d| ƒ‚n‚ W dd}~X Y nX |2 | j r”t|ƒ zt|ƒ}W d| j r°t|ƒ X W dQ R X x*|  ¡  ¡ D ]\}}||krÊ| |¡ qÊW |S )z4Return a Message representation or raise a KeyError.zrb+r¡   zNo message with key: %sN)rÙ   r¢   r   r   r}   r   re   r—   r˜   rÒ   r&   rÜ   r   rÝ   Úget_sequencesr>   Úadd_sequence)r   r#   r§   r   r¨   r‰   Úkey_listr   r   r   r,   û  s&    zMH.get_messagec          
   C   sÄ   y@| j r$ttj | jt|ƒ¡dƒ}nttj | jt|ƒ¡dƒ}W n> tk
r~ } z |jtj	krlt
d| ƒ‚n‚ W dd}~X Y nX |6 | j r”t|ƒ z| ¡  td¡S | j r´t|ƒ X W dQ R X dS )z2Return a bytes representation or raise a KeyError.zrb+r¡   zNo message with key: %sNrQ   )rÙ   r¢   r   r   r}   r   re   r—   r˜   rÒ   r&   rÜ   rS   r`   ra   rÝ   )r   r#   r§   r   r   r   r   r3     s    zMH.get_bytesc          
   C   sf   yt tj | jt|ƒ¡dƒ}W n> tk
r\ } z |jtjkrJt	d| ƒ‚n‚ W dd}~X Y nX t
|ƒS )z6Return a file-like representation or raise a KeyError.r¡   zNo message with key: %sN)r¢   r   r   r}   r   re   r—   r˜   rÒ   r&   r©   )r   r#   r§   r   r   r   r   r/   )  s    zMH.get_filec             C   s   t tdd„ t | j¡D ƒƒƒS )zReturn an iterator over keys.c             s   s   | ]}|  ¡ rt|ƒV  qd S )N)ÚisdigitrÅ   )Ú.0r±   r   r   r   ú	<genexpr>6  s    zMH.iterkeys.<locals>.<genexpr>)Úiterrä   r   r®   r   )r   r   r   r   r6   4  s    zMH.iterkeysc             C   s   t j t j | jt|ƒ¡¡S )z9Return True if the keyed message exists, False otherwise.)r   r   r   r}   r   re   )r   r#   r   r   r   r?   9  s    zMH.__contains__c             C   s   t t|  ¡ ƒƒS )z*Return a count of messages in the mailbox.)r«   r7   r6   )r   r   r   r   r@   =  s    z
MH.__len__c             C   s2   | j s.ttj | jd¡dƒ| _t| jƒ d| _ dS )zLock the mailbox.z.mh_sequenceszrb+TN)rÙ   r¢   r   r   r}   r   rÕ   rÜ   )r   r   r   r   rJ   A  s    
zMH.lockc             C   s(   | j r$t| jƒ t| jƒ | `d| _ dS )z#Unlock the mailbox if it is locked.FN)rÙ   rÝ   rÕ   rŠ   )r   r   r   r   rK   H  s
    

z	MH.unlockc             C   s   dS )z&Write any pending changes to the disk.Nr   )r   r   r   r   rI   P  s    zMH.flushc             C   s   | j r|  ¡  dS )zFlush and close the mailbox.N)rÙ   rK   )r   r   r   r   rL   T  s    zMH.closec             C   s@   g }x6t  | j¡D ]&}t j t j | j|¡¡r| |¡ qW |S )zReturn a list of folder names.)r   r®   r   r   r¯   r}   r°   )r   rB   r±   r   r   r   r²   Y  s
    zMH.list_foldersc             C   s   t tj | j|¡| jddS )z+Return an MH instance for the named folder.F)r   r   )r   r   r   r}   r   r   )r   r³   r   r   r   r´   a  s    zMH.get_folderc             C   s   t tj | j|¡| jdS )z:Create a folder and return an MH instance representing it.)r   )r   r   r   r}   r   r   )r   r³   r   r   r   r·   f  s    zMH.add_folderc             C   s`   t j | j|¡}t  |¡}|dgkr:t  t j |d¡¡ n|g krDntd| j ƒ‚t  |¡ dS )z-Delete the named folder, which must be empty.z.mh_sequenceszFolder not empty: %sN)r   r   r}   r   r®   r$   r   rº   )r   r³   r   Úentriesr   r   r   r¾   k  s    

zMH.remove_folderc       
   
      s  i }t tj | jd¡dddä}t|  ¡ ƒ‰ xÐ|D ]È}yž| d¡\}}tƒ }xT| ¡ D ]H}| ¡ rr| 	t
|ƒ¡ qVdd„ | d¡D ƒ\}}	| t||	d	 ƒ¡ qVW ‡ fd
d„t|ƒD ƒ||< t|| ƒdkrÒ||= W q2 tk
rø   td| ¡  ƒ‚Y q2X q2W W dQ R X |S )z=Return a name-to-key-list dictionary to define each sequence.z.mh_sequencesÚrÚASCII)Úencodingry   c             s   s   | ]}t |ƒV  qd S )N)rÅ   )r  Úxr   r   r   r  „  s    z#MH.get_sequences.<locals>.<genexpr>ú-r¬   c                s   g | ]}|ˆ kr|‘qS r   r   )r  r#   )Úall_keysr   r   ú
<listcomp>†  s    z$MH.get_sequences.<locals>.<listcomp>r   z"Invalid sequence specification: %sN)r¢   r   r   r}   r   Úsetr8   r   r  r"   rÅ   rH   Úrangerä   r«   rO   r   Úrstrip)
r   Zresultsr§   rs   r‰   Úcontentsr8   Úspecrê   rë   r   )r  r   r  w  s&    

 zMH.get_sequencesc             C   s
  t tj | jd¡ddd}zàt t  |jtjtjB ¡¡ x¾| 	¡ D ]²\}}t
|ƒdkrXqB| |d ¡ d}d}xbtt|ƒƒD ]R}|d	 |kr |sÊd
}| d¡ n*|r¼d}| d||f ¡ n| d| ¡ |}q|W |rê| t|ƒd ¡ qB| d¡ qBW W dt|ƒ X dS )z:Set sequences using the given name-to-key-list dictionary.z.mh_sequenceszr+r  )r  r   ry   NFr¬   Tr  z%s %sz %sÚ
)r¢   r   r   r}   r   rL   r‰   r¶   r  r>   r«   rb   rä   r  re   rŠ   )r   Ú	sequencesr§   r‰   r8   ÚprevZ
completingr#   r   r   r   Úset_sequences  s.    zMH.set_sequencesc       	      C   sL  |   ¡ }d}g }xÎ|  ¡ D ]Â}|d |krÔ| ||d f¡ y4t tj | jt|ƒ¡tj | jt|d ƒ¡¡ W nH t	t
fk
r¸   t tj | jt|ƒ¡tj | jt|d ƒ¡¡ Y nX t tj | jt|ƒ¡¡ |d7 }qW |d | _t|ƒdkrúdS xB| ¡ D ]6\}}x*|D ]"\}}||kr||| |¡< qW qW |  |¡ dS )z?Re-name messages to eliminate numbering gaps. Invalidates keys.r   r¬   N)r  r6   r°   r   r“   r   r}   r   re   r”   r•   r–   ÚunlinkrÖ   r«   r>   Úindexr%  )	r   r#  r$  Zchangesr#   r‰   r  Úoldr{   r   r   r   Úpack¬  s,     

zMH.packc             C   s|   |  ¡ }|   ¡ }x<| ¡ D ]0\}}||kr6| |¡ q||kr|| |¡= qW x|D ]}||krT|g||< qTW |  |¡ dS )z;Inspect a new MHMessage and update sequences appropriately.N)r  r>   r°   r'  r%  )r   r!   r#   Zpending_sequencesZall_sequencesr‰   r  Úsequencer   r   r   r  Æ  s    
zMH._dump_sequences)NT)ru   rv   rw   rx   r   r"   r$   r(   r,   r3   r/   r6   r?   r@   rJ   rK   rI   rL   r²   r´   r·   r¾   r  r%  r)  r  r   r   r   r   r   ¤  s.   
"c               @   s   e Zd ZdZedddddddhƒZd%dd„Zdd„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd	S )&r   zAn Rmail-style Babyl mailbox.ÚunseenÚdeletedZfiledÚansweredÚ	forwardedZeditedÚresentNTc             C   s   t  | |||¡ i | _dS )zInitialize a Babyl mailbox.N)rÑ   r   Ú_labels)r   r   r   r   r   r   r   r   Û  s    zBabyl.__init__c             C   s(   t  | |¡}t|tƒr$| ¡ | j|< |S )z$Add message and return assigned key.)rÑ   r"   rY   r   Ú
get_labelsr0  )r   r!   r#   r   r   r   r"   à  s    
z	Babyl.addc             C   s"   t  | |¡ || jkr| j|= dS )z=Remove the keyed message; raise KeyError if it doesn't exist.N)rÑ   r$   r0  )r   r#   r   r   r   r$   ç  s    
zBabyl.removec             C   s*   t  | ||¡ t|tƒr&| ¡ | j|< dS )z>Replace the keyed message; raise KeyError if it doesn't exist.N)rÑ   r(   rY   r   r1  r0  )r   r#   r!   r   r   r   r(   í  s    
zBabyl.__setitem__c       
      C   s  |   |¡\}}| j |¡ | j ¡  t ¡ }x2| j ¡ }|dt ksH|sJP | | td¡¡ q.W t ¡ }x.| j ¡ }|tks€|s‚P | | td¡¡ qjW || j 	¡  }|dks²t
‚| j |¡}| td¡}t| ¡ | ƒ}	|	 | ¡ ¡ || jkr|	 | j| ¡ |	S )z4Return a Message representation or raise a KeyError.s   *** EOOH ***rQ   r   )rž   rÕ   r_   rl   rZ   r[   ra   rb   r`   rá   rà   rS   r   rk   Úset_visibler0  Ú
set_labels)
r   r#   rê   rë   Úoriginal_headersrs   Zvisible_headersÚnZbodyr¨   r   r   r   r,   ó  s0    


zBabyl.get_messagec       	      C   sÀ   |   |¡\}}| j |¡ | j ¡  t ¡ }x2| j ¡ }|dt ksH|sJP | | td¡¡ q.W x| j ¡ }|tksx|sbP qbW | 	¡ }|| j 
¡  }|dks t‚| j |¡}| td¡}|| S )z3Return a string representation or raise a KeyError.s   *** EOOH ***rQ   r   )rž   rÕ   r_   rl   rZ   r[   ra   rb   r`   rk   rá   rà   rS   )	r   r#   rê   rë   r4  rs   Zheadersr5  rr   r   r   r   r3     s&    


zBabyl.get_bytesc             C   s   t  |  |¡ dt¡¡S )z6Return a file-like representation or raise a KeyError.rQ   )rZ   r[   r3   r`   ra   )r   r#   r   r   r   r/   %  s    zBabyl.get_filec             C   s@   |   ¡  tƒ }x| j ¡ D ]}| |¡ qW | | j¡ t|ƒS )z4Return a list of user-defined labels in the mailbox.)rž   r  r0  r<   rH   Údifference_updateÚ_special_labelsr7   )r   ÚlabelsZ
label_listr   r   r   r1  )  s    zBabyl.get_labelsc             C   s>  g g  }}| j  d¡ d}g }xÒ|}| j  ¡ }| j  ¡ }|dt kržt|ƒt|ƒk rf| |ttƒ ¡ | |¡ dd„ | j  ¡ dd…  d¡D ƒ}| |¡ q |dks²|dt krÖt|ƒt|ƒk rî| |ttƒ ¡ q |s | |ttƒ ¡ P q W tt	t
||ƒƒƒ| _tt	|ƒƒ| _t| jƒ| _| j  dd	¡ | j  ¡ | _dS )
z0Generate key-to-(start, stop) table of contents.r   s   c             S   s   g | ]}|  ¡ r|  ¡ ‘qS r   )Ústrip)r  Úlabelr   r   r   r  @  s    z'Babyl._generate_toc.<locals>.<listcomp>r¬   Nó   ,ó   rË   )rÕ   r_   rl   rá   ra   r«   r°   r   r  r  r  r   r0  rÖ   rÚ   )r   r  r  r  Zlabel_listsr  rs   r8  r   r   r   rí   2  s4    



zBabyl._generate_tocc             C   sV   dt  }|dt  7 }|  ¡ }dd„ |D ƒ}|dd |¡ t  7 }|d7 }| |¡ dS )	z,Called before writing the mailbox to file f.s   BABYL OPTIONS:s
   Version: 5c             s   s   | ]}|  ¡ V  qd S )N)rM   )r  r:  r   r   r   r  U  s    z*Babyl._pre_mailbox_hook.<locals>.<genexpr>s   Labels:r;  r<  N)ra   r1  r}   rb   )r   r§   Zbabylr8  r   r   r   rã   P  s    zBabyl._pre_mailbox_hookc             C   s   |  dt ¡ dS )z-Called before writing each message to file f.ó   N)rb   ra   )r   r§   r   r   r   rå   Z  s    zBabyl._pre_message_hookc             C   s   |  td ¡ dS )z,Called after writing each message to file f.r<  N)rb   ra   )r   r§   r   r   r   rç   ^  s    zBabyl._post_message_hookc             C   s”  | j  ¡ }t|tƒr¼g }g }x0| ¡ D ]$}|| jkr@| |¡ q&| |¡ q&W | j  d¡ x |D ]}| j  d| ¡  ¡ q`W | j  d¡ x$|D ]}| j  d| ¡  d ¡ qŽW | j  t	¡ n| j  dt	 ¡ t|t
jjƒr*t ¡ }t
j |dd¡}| |¡ | d¡ x4| ¡ }| j  | d	t	¡¡ |d	ks6|s
P q
W | j  d
t	 ¡ t|tƒr¸t ¡ }	t
j |	dd¡}
|
 | ¡ ¡ xv|	 ¡ }| j  | d	t	¡¡ |d	ks®|s‚P q‚W n@| d¡ x4| ¡ }| j  | d	t	¡¡ |d	ksð|sÄP qÄW x,| d¡}|sP | j  | d	t	¡¡ qúW nXt|tttjfƒr&t|tjƒrbt dtd¡ | ¡ }t|tƒrx|  |¡}| d¡d }|d dkrú| j  |d|…  d	t	¡¡ | j  d
t	 ¡ | j  |d|…  d	t	¡¡ | j  ||d…  d	t	¡¡ n(| j  d
t	 t	 ¡ | j  | d	t	¡¡ n\t |dƒrrt |dƒrRt dtd¡ |j!}| ¡ }d}x”| ¡ }| "d¡r†|dd… d	 }n| "d¡r¢|dd… d	 }| j  | d	t	¡¡ |d	ksÆ|s`|rìd}| j  d
t	 ¡ | |¡ nP q`W xŒ| ¡ }|sP | "d¡r$|dd… t	 }n:| "d¡rB|dd… t	 }n| "d	¡r^|dd… t	 }| j  |¡ qöW nt#dt$|ƒ ƒ‚| j  ¡ }||fS )z0Write message contents and return (start, stop).ó   1s   , s   ,,ó    r;  s   1,,Fr   rQ   s   *** EOOH ***i   z8Use of StringIO input is deprecated, use BytesIO insteadrR   s   

rË   rW   Nrl   rT   zDUse of text mode files is deprecated, use a binary mode file insteadTs   
rU   rV   zInvalid message type: %s)%rÕ   rá   rY   r   r1  r7  r°   rb   rM   ra   r1   r!   r   rZ   r[   r\   r]   r^   r_   rl   r`   Úget_visiblerS   rf   re   rg   rh   ri   rj   rk   rP   rú   rE   rT   rd   rn   ro   )r   r!   rê   Zspecial_labelsr8  r:  Zorig_bufferZorig_generatorrs   Z
vis_bufferZvis_generatorrT   Z
body_startZoriginal_posZ
first_passrë   r   r   r   rî   b  sÀ    











zBabyl._install_message)NT)ru   rv   rw   rx   Ú	frozensetr7  r   r"   r$   r(   r,   r3   r/   r1  rí   rã   rå   rç   rî   r   r   r   r   r   Õ  s    

	
c               @   s*   e Zd ZdZd	dd„Zdd„ Zdd„ ZdS )
r   z0Message with mailbox-format-specific properties.Nc             C   sÒ   t |tjjƒr4|  t |¡¡ t |tƒrÎ| | ¡ nšt |tƒrP|  t 	|¡¡ n~t |t
ƒrl|  t |¡¡ nbt |tjƒrŠ|  t |¡¡ nDt|dƒr¦|  t |¡¡ n(|dkr¾tjj | ¡ ntdt|ƒ ƒ‚dS )zInitialize a Message instance.rS   NzInvalid message type: %s)rY   r1   r!   r   Ú_become_messageÚcopyÚdeepcopyÚ_explain_torf   r2   re   Zmessage_from_stringrZ   ÚTextIOWrapperZmessage_from_filerE   Zmessage_from_binary_filer   rn   ro   )r   r!   r   r   r   r   Ñ  s    



zMessage.__init__c             C   s8   t |dg ƒ}x&|jD ]}||kr|j| | j|< qW dS )z0Assume the non-format-specific state of message.Ú_type_specific_attributesN)ÚgetattrÚ__dict__)r   r!   Ztype_specificr‰   r   r   r   rB  ä  s    zMessage._become_messagec             C   s   t |tƒrdS tdƒ‚dS )z:Copy format-specific state to message insofar as possible.Nz Cannot convert to specified type)rY   r   rn   )r   r!   r   r   r   rE  ë  s    
zMessage._explain_to)N)ru   rv   rw   rx   r   rB  rE  r   r   r   r   r   Î  s   
c               @   s|   e Zd ZdZdddgZddd„Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )r	   z)Message with Maildir-specific properties.Ú_subdirÚ_infoÚ_dateNc             C   s&   d| _ d| _t ¡ | _t | |¡ dS )z%Initialize a MaildirMessage instance.r{   r†   N)rJ  rK  r¿   rL  r   r   )r   r!   r   r   r   r   ø  s    
zMaildirMessage.__init__c             C   s   | j S )zReturn 'new' or 'cur'.)rJ  )r   r   r   r   r‹   ÿ  s    zMaildirMessage.get_subdirc             C   s(   |dks|dkr|| _ ntd| ƒ‚dS )zSet subdir to 'new' or 'cur'.r{   r|   z!subdir must be 'new' or 'cur': %sN)rJ  rO   )r   r™   r   r   r   r£     s    zMaildirMessage.set_subdirc             C   s"   | j  d¡r| j dd… S dS dS )z*Return as a string the flags that are set.z2,rË   Nr†   )rK  rm   )r   r   r   r   Ú	get_flags
  s    zMaildirMessage.get_flagsc             C   s   dd  t|ƒ¡ | _dS )z)Set the given flags and unset all others.z2,r†   N)r}   rä   rK  )r   Úflagsr   r   r   Ú	set_flags  s    zMaildirMessage.set_flagsc             C   s$   |   d t|  ¡ ƒt|ƒB ¡¡ dS )z.Set the given flag(s) without changing others.r†   N)rO  r}   r  rM  )r   Úflagr   r   r   Úadd_flag  s    zMaildirMessage.add_flagc             C   s,   |   ¡ r(|  d t|   ¡ ƒt|ƒ ¡¡ dS )z7Unset the given string flag(s) without changing others.r†   N)rM  rO  r}   r  )r   rP  r   r   r   Úremove_flag  s    zMaildirMessage.remove_flagc             C   s   | j S )z<Return delivery date of message, in seconds since the epoch.)rL  )r   r   r   r   r’     s    zMaildirMessage.get_datec             C   s6   yt |ƒ| _W n" tk
r0   td| ƒd‚Y nX dS )z9Set delivery date of message, in seconds since the epoch.zcan't convert to float: %sN)ÚfloatrL  rO   rn   )r   Zdater   r   r   r¥   "  s    zMaildirMessage.set_datec             C   s   | j S )z%Get the message's "info" as a string.)rK  )r   r   r   r   r   )  s    zMaildirMessage.get_infoc             C   s&   t |tƒr|| _ntdt|ƒ ƒ‚dS )z Set the message's "info" string.zinfo must be a string: %sN)rY   re   rK  rn   ro   )r   Úinfor   r   r   r¤   -  s    
zMaildirMessage.set_infoc             C   s¤  t |tƒr8| |  ¡ ¡ | |  ¡ ¡ | |  ¡ ¡ nht |tƒrÄt	|  ¡ ƒ}d|kr`| 
d¡ |  ¡ dkrv| 
d¡ d|krˆ| 
d¡ d|krš| 
d¡ d|kr¬| 
d¡ | d	t |  ¡ ¡¡ nÜt |tƒrt	|  ¡ ƒ}d|krî| d
¡ d|kr| d¡ d|kr | d¡ nˆt |tƒr‚t	|  ¡ ƒ}d|krD| d
¡ d|krX| d¡ d|krl| d¡ d|kr | d¡ nt |tƒrntdt|ƒ ƒ‚dS )z;Copy Maildir-specific state to message insofar as possible.ÚSÚRr|   ÚOÚTÚDÚFÚAzMAILER-DAEMONr+  ÚrepliedÚflaggedr,  r-  ÚPr.  z$Cannot convert to specified type: %sN)rY   r	   rO  rM  r£   r‹   r¥   r’   rû   r  rQ  ró   r¿   rÿ   r   r  r   Ú	add_labelr   rn   ro   )r   r!   rN  r   r   r   rE  4  sN    

















zMaildirMessage._explain_to)N)ru   rv   rw   rx   rG  r   r‹   r£   rM  rO  rQ  rR  r’   r¥   r   r¤   rE  r   r   r   r   r	   ó  s   

c               @   sZ   e Zd ZdZdgZddd„Zdd„ Zddd	„Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ ZdS )rû   z/Message with mbox- or MMDF-specific properties.Ú_fromNc             C   sV   |   dd¡ t|tjjƒrF| ¡ }|dk	rF| d¡rF|   |dd… ¡ t | |¡ dS )z'Initialize an mboxMMDFMessage instance.zMAILER-DAEMONTNzFrom rX   )ró   rY   r1   r!   r   rý   rm   r   )r   r!   r÷   r   r   r   r   e  s    z_mboxMMDFMessage.__init__c             C   s   | j S )z Return contents of "From " line.)r`  )r   r   r   r   rü   n  s    z_mboxMMDFMessage.get_fromc             C   s4   |dk	r*|dkrt  ¡ }|dt  |¡ 7 }|| _dS )z>Set "From " line, formatting and appending time_ if specified.NTú )r¿   rÿ   rþ   r`  )r   rø   Ztime_r   r   r   ró   r  s
    z_mboxMMDFMessage.set_fromc             C   s   |   dd¡|   dd¡ S )z*Return as a string the flags that are set.ÚStatusr†   zX-Status)r+   )r   r   r   r   rM  z  s    z_mboxMMDFMessage.get_flagsc             C   sÚ   t |ƒ}d\}}x&dD ]}||kr||7 }| |¡ qW x&dD ]}||kr>||7 }| |¡ q>W |d t|ƒ¡7 }y|  d|¡ W n  tk
r¢   |  d|¡ Y nX y|  d|¡ W n  tk
rÔ   |  d|¡ Y nX dS )z)Set the given flags and unset all others.)r†   r†   )rV  rW  )rY  rZ  r[  r†   rb  zX-StatusN)r  r$   r}   rä   Úreplace_headerr&   Z
add_header)r   rN  Zstatus_flagsZxstatus_flagsrP  r   r   r   rO  ~  s&    

z_mboxMMDFMessage.set_flagsc             C   s$   |   d t|  ¡ ƒt|ƒB ¡¡ dS )z.Set the given flag(s) without changing others.r†   N)rO  r}   r  rM  )r   rP  r   r   r   rQ  ”  s    z_mboxMMDFMessage.add_flagc             C   s4   d| ksd| kr0|   d t|  ¡ ƒt|ƒ ¡¡ dS )z7Unset the given string flag(s) without changing others.rb  zX-Statusr†   N)rO  r}   r  rM  )r   rP  r   r   r   rR  ˜  s    z_mboxMMDFMessage.remove_flagc          	   C   sÞ  t |tƒrÐt|  ¡ ƒ}d|kr(| d¡ d|kr:| d¡ d|krL| d¡ d|kr^| d¡ d|krp| d¡ |d	= |d
= d |  ¡  ¡ dd… ¡}y| 	t
 t |d¡¡¡ W n ttfk
rÊ   Y nX n
t |tƒrø| |  ¡ ¡ | |  ¡ ¡ nât |tƒrZt|  ¡ ƒ}d|kr$| d¡ d|kr8| d¡ d|krL| d¡ |d	= |d
= n€t |tƒr¼t|  ¡ ƒ}d|kr†| d¡ d|krš| d¡ d|kr®| d¡ |d	= |d
= nt |tƒrÊntdt|ƒ ƒ‚dS )zACopy mbox- or MMDF-specific state to message insofar as possible.rW  r|   rZ  r[  rV  rU  rY  rX  Zstatuszx-statusra  éûÿÿÿNz%a %b %d %H:%M:%S %Yr+  r\  r]  r,  r-  z$Cannot convert to specified type: %s)rY   r	   r  rM  r£   rQ  r}   rü   r   r¥   ÚcalendarZtimegmr¿   ZstrptimerO   ÚOverflowErrorrû   rO  ró   r   r  r   r_  r   rn   ro   )r   r!   rN  Z
maybe_dater   r   r   rE    s^    



















z_mboxMMDFMessage._explain_to)N)N)ru   rv   rw   rx   rG  r   rü   ró   rM  rO  rQ  rR  rE  r   r   r   r   rû   `  s   
	
rû   c               @   s   e Zd ZdZdS )r
   z&Message with mbox-specific properties.N)ru   rv   rw   rx   r   r   r   r   r
   Ñ  s   c               @   sH   e Zd ZdZdgZddd„Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dS )r   z$Message with MH-specific properties.Ú
_sequencesNc             C   s   g | _ t | |¡ dS )z!Initialize an MHMessage instance.N)rg  r   r   )r   r!   r   r   r   r   Ú  s    zMHMessage.__init__c             C   s   | j dd… S )z4Return a list of sequences that include the message.N)rg  )r   r   r   r   r  ß  s    zMHMessage.get_sequencesc             C   s   t |ƒ| _dS )z3Set the list of sequences that include the message.N)r7   rg  )r   r#  r   r   r   r%  ã  s    zMHMessage.set_sequencesc             C   s6   t |tƒr"|| jkr2| j |¡ ntdt|ƒ ƒ‚dS )z8Add sequence to list of sequences including the message.zsequence type must be str: %sN)rY   re   rg  r°   rn   ro   )r   r*  r   r   r   r  ç  s    

zMHMessage.add_sequencec             C   s*   y| j  |¡ W n tk
r$   Y nX dS )zARemove sequence from the list of sequences including the message.N)rg  r$   rO   )r   r*  r   r   r   Úremove_sequenceï  s    zMHMessage.remove_sequencec             C   sJ  t |tƒrdt|  ¡ ƒ}d|kr*| d¡ n| d¡ | d¡ d|krP| d¡ d|krb| d¡ nât |tƒr¾t|  ¡ ƒ}d|krŽ| d¡ n
| d	¡ d|krª| d¡ d|kr¼| d
¡ nˆt |tƒræx||  ¡ D ]}| |¡ qÒW n`t |t	ƒr(t|  ¡ ƒ}d|kr| 
d¡ d|krF| 
d¡ nt |tƒr6ntdt|ƒ ƒ‚dS )z6Copy MH-specific state to message insofar as possible.r+  r|   rU  r]  rZ  r\  rV  ÚROrW  r[  r-  z$Cannot convert to specified type: %sN)rY   r	   r  r  r£   rQ  rû   r   r  r   r_  r   rn   ro   )r   r!   r#  r*  r   r   r   rE  ö  s@    










zMHMessage._explain_to)N)ru   rv   rw   rx   rG  r   r  r%  r  rh  rE  r   r   r   r   r   Õ  s   
c               @   sb   e Zd ZdZddgZddd„Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )r   z'Message with Babyl-specific properties.r0  Ú_visibleNc             C   s   g | _ tƒ | _t | |¡ dS )z#Initialize a BabylMessage instance.N)r0  r   rj  r   )r   r!   r   r   r   r   "  s    zBabylMessage.__init__c             C   s   | j dd… S )z'Return a list of labels on the message.N)r0  )r   r   r   r   r1  (  s    zBabylMessage.get_labelsc             C   s   t |ƒ| _dS )z&Set the list of labels on the message.N)r7   r0  )r   r8  r   r   r   r3  ,  s    zBabylMessage.set_labelsc             C   s6   t |tƒr"|| jkr2| j |¡ ntdt|ƒ ƒ‚dS )z+Add label to list of labels on the message.zlabel must be a string: %sN)rY   re   r0  r°   rn   ro   )r   r:  r   r   r   r_  0  s    

zBabylMessage.add_labelc             C   s*   y| j  |¡ W n tk
r$   Y nX dS )z4Remove label from the list of labels on the message.N)r0  r$   rO   )r   r:  r   r   r   Úremove_label8  s    zBabylMessage.remove_labelc             C   s
   t | jƒS )z3Return a Message representation of visible headers.)r   rj  )r   r   r   r   r@  ?  s    zBabylMessage.get_visiblec             C   s   t |ƒ| _dS )z2Set the Message representation of visible headers.N)r   rj  )r   Zvisibler   r   r   r2  C  s    zBabylMessage.set_visiblec             C   sj   x6| j  ¡ D ](}|| kr,| j  || | ¡ q| j |= qW x,dD ]$}|| kr>|| j kr>| | | j |< q>W dS )z9Update and/or sensibly generate a set of visible headers.)ZDateZFromzReply-ToZToZCCZSubjectN)rj  r8   rc  )r   Úheaderr   r   r   Úupdate_visibleG  s    
zBabylMessage.update_visiblec             C   sv  t |tƒr~t|  ¡ ƒ}d|kr*| d¡ n| d¡ | d¡ d|ksNd|krX| d¡ d|krj| d¡ d	|kr|| d
¡ nôt |tƒrØt|  ¡ ƒ}d|kr¨| d¡ n
| d¡ d	|krÄ| d¡ d|krÖ| d¡ nšt |tƒrt|  ¡ ƒ}d|kr| d¡ d|krr| d¡ nXt |t	ƒrT| 
|  ¡ ¡ x<|  ¡ D ]}| |¡ q>W nt |tƒrbntdt|ƒ ƒ‚dS )z9Copy Babyl-specific state to message insofar as possible.r+  r|   rU  r.  r/  r^  r-  rV  r,  rX  ri  rW  rY  r[  r\  z$Cannot convert to specified type: %sN)rY   r	   r  r1  r£   rQ  rû   r   r  r   r2  r@  r_  r   rn   ro   )r   r!   r8  r:  r   r   r   rE  R  sF    










zBabylMessage._explain_to)N)ru   rv   rw   rx   rG  r   r1  r3  r_  rk  r@  r2  rm  rE  r   r   r   r   r     s   
c               @   s   e Zd ZdZdS )r   z&Message with MMDF-specific properties.N)ru   rv   rw   rx   r   r   r   r   r   |  s   c               @   s¨   e Zd ZdZd&dd„Zd'dd„Zd(dd„Zd)d	d
„Zd*dd„Zdd„ Z	dd„ Z
d+dd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zed$d%„ ƒZdS ),r©   zA read-only wrapper of a file.Nc             C   s$   || _ |dkr| ¡ | _n|| _dS )zInitialize a _ProxyFile.N)rÕ   rá   Ú_pos)r   r§   Úposr   r   r   r   ƒ  s    z_ProxyFile.__init__c             C   s   |   || jj¡S )zRead bytes.)Ú_readrÕ   rS   )r   Úsizer   r   r   rS   ‹  s    z_ProxyFile.readc             C   s   |   || jj¡S )zRead bytes.)rp  rÕ   Úread1)r   rq  r   r   r   rr    s    z_ProxyFile.read1c             C   s   |   || jj¡S )zRead a line.)rp  rÕ   rl   )r   rq  r   r   r   rl   “  s    z_ProxyFile.readlinec             C   s>   g }x4| D ],}|  |¡ |dk	r
|t|ƒ8 }|dkr
P q
W |S )zRead multiple lines.Nr   )r°   r«   )r   ÚsizehintrB   rs   r   r   r   Ú	readlines—  s    

z_ProxyFile.readlinesc             c   s    x|   ¡ }|sdS |V  qW dS )zIterate over lines.N)rl   )r   rs   r   r   r   r;   ¢  s
    z_ProxyFile.__iter__c             C   s   | j S )zReturn the position.)rn  )r   r   r   r   rá   ª  s    z_ProxyFile.tellr   c             C   s4   |dkr| j  | j¡ | j  ||¡ | j  ¡ | _dS )zChange position.r¬   N)rÕ   r_   rn  rá   )r   ÚoffsetÚwhencer   r   r   r_   ®  s    z_ProxyFile.seekc             C   s0   t | dƒr,zt | jdƒr"| j ¡  W d| `X dS )zClose the file.rÕ   rL   N)rE   rÕ   rL   )r   r   r   r   rL   µ  s
    
z_ProxyFile.closec             C   s2   |dkrd}| j  | j¡ ||ƒ}| j  ¡ | _|S )z"Read size bytes using read_method.NrW   )rÕ   r_   rn  rá   )r   rq  Úread_methodrB   r   r   r   rp  ¾  s    z_ProxyFile._readc             C   s   | S )z$Context management protocol support.r   )r   r   r   r   Ú	__enter__Ç  s    z_ProxyFile.__enter__c             G   s   |   ¡  d S )N)rL   )r   Úexcr   r   r   Ú__exit__Ë  s    z_ProxyFile.__exit__c             C   s
   | j  ¡ S )N)rÕ   Úreadable)r   r   r   r   r{  Î  s    z_ProxyFile.readablec             C   s
   | j  ¡ S )N)rÕ   Úwritable)r   r   r   r   r|  Ñ  s    z_ProxyFile.writablec             C   s
   | j  ¡ S )N)rÕ   Úseekable)r   r   r   r   r}  Ô  s    z_ProxyFile.seekablec             C   s
   | j  ¡ S )N)rÕ   rI   )r   r   r   r   rI   ×  s    z_ProxyFile.flushc             C   s&   t | dƒsdS t | jdƒsdS | jjS )NrÕ   Tr  F)rE   rÕ   r  )r   r   r   r   r  Ú  s
    
z_ProxyFile.closed)N)N)N)N)N)r   )ru   rv   rw   rx   r   rS   rr  rl   rt  r;   rá   r_   rL   rp  rx  rz  r{  r|  r}  rI   Úpropertyr  r   r   r   r   r©   €  s$   





		r©   c               @   s<   e Zd ZdZddd„Zdd„ Zddd	„Zd
d„ Zdd„ ZdS )rù   z&A read-only wrapper of part of a file.Nc             C   s   t  | ||¡ || _|| _dS )zInitialize a _PartialFile.N)r©   r   Ú_startÚ_stop)r   r§   rê   rë   r   r   r   r   æ  s    z_PartialFile.__init__c             C   s   t  | ¡| j S )z*Return the position with respect to start.)r©   rá   r  )r   r   r   r   rá   ì  s    z_PartialFile.tellr   c             C   s<   |dkr| j | _d}n|dkr*| j| _d}t | ||¡ dS )z8Change position, possibly with respect to start or stop.r   r¬   rË   N)r  rn  r€  r©   r_   )r   ru  rv  r   r   r   r_   ð  s    z_PartialFile.seekc             C   sB   | j | j }|dkrdS |dks0|dk s0||kr4|}t | ||¡S )z;Read size bytes using read_method, honoring start and stop.r   rñ   N)r€  rn  r©   rp  )r   rq  rw  Z	remainingr   r   r   rp  ú  s    z_PartialFile._readc             C   s   t | dƒr| `d S )NrÕ   )rE   rÕ   )r   r   r   r   rL     s    
z_PartialFile.close)NN)r   )	ru   rv   rw   rx   r   rá   r_   rp  rL   r   r   r   r   rù   ã  s   


	rù   Tc          
   C   sž  d}yZt rpyt  | t jt jB ¡ W nJ tk
rn } z,|jtjtjtjfkr\t	d| j
 ƒ‚n‚ W dd}~X Y nX |r^yt| j
d ƒ}| ¡  W n: tk
rÊ } z|jtjtjfkr¸dS ‚ W dd}~X Y nX y`yt |j
| j
d ¡ d}W n2 ttfk
r   t |j
| j
d ¡ d}Y nX t |j
¡ W n0 tk
r\   t |j
¡ t	d| j
 ƒ‚Y nX W n8   t r|t  | t j¡ |r’t | j
d ¡ ‚ Y nX dS )z(Lock file f using lockf and dot locking.Fzlockf: lock unavailable: %sNz.lockTzdot lock unavailable: %s)ÚfcntlÚlockfZLOCK_EXZLOCK_NBr—   r˜   ZEAGAINrÓ   rÔ   r   r‰   râ   rL   r   r“   r”   r•   r–   r&  rÊ   r$   ÚLOCK_UN)r§   rÞ   Zdotlock_doner   Zpre_lockr   r   r   rÜ   
  sH    
rÜ   c             C   s8   t rt  | t j¡ tj | jd ¡r4t | jd ¡ dS )z*Unlock file f using lockf and dot locking.z.lockN)r  r‚  rƒ  r   r   r   r‰   r$   )r§   r   r   r   rÝ   4  s    rÝ   c          	   C   s8   t  | t jt jB t jB d¡}z
t| dƒS t  |¡ X dS )zCCreate a file if it doesn't exist and open for reading and writing.i¶  zrb+N)r   r¢   rµ   r	  ÚO_RDWRrL   )r   Úfdr   r   r   rÉ   ;  s    
rÉ   c             C   s$   t d| tt ¡ ƒt ¡ t ¡ f ƒS )zBCreate a temp file based on path and open for reading and writing.z%s.%s.%s.%s)rÉ   rÅ   r¿   rÃ   rÄ   r   rÆ   )r   r   r   r   râ   C  s    râ   c             C   s$   |   ¡  ttdƒr t |  ¡ ¡ dS )z0Ensure changes to file f are physically on disk.ÚfsyncN)rI   rE   r   r†  Úfileno)r§   r   r   r   rß   I  s    
rß   c             C   s   t | ƒ |  ¡  dS )z:Close file f, ensuring all changes are physically on disk.N)rß   rL   )r§   r   r   r   rŠ   O  s    rŠ   c               @   s   e Zd ZdZdS )r   z"Raised for module-specific errors.N)ru   rv   rw   rx   r   r   r   r   r   U  s   c               @   s   e Zd ZdZdS )r   z:The specified mailbox does not exist and won't be created.N)ru   rv   rw   rx   r   r   r   r   r   X  s   c               @   s   e Zd ZdZdS )r   z>The specified mailbox is not empty and deletion was requested.N)ru   rv   rw   rx   r   r   r   r   r   [  s   c               @   s   e Zd ZdZdS )r   z)Another process caused an action to fail.N)ru   rv   rw   rx   r   r   r   r   r   ^  s   c               @   s   e Zd ZdZdS )r   z)A file appears to have an invalid format.N)ru   rv   rw   rx   r   r   r   r   r   a  s   )T)0rx   r   r¿   re  rÃ   r˜   rC  rh   r1   Zemail.messageZemail.generatorrZ   r-   r  ÚImportErrorÚ__all__ra   rM   r   r   rÑ   rð   r   r   r   r   r!   r   r	   rû   r
   r   r   r   r©   rù   rÜ   rÝ   rÉ   râ   rß   rŠ   Ú	Exceptionr   r   r   r   r   r   r   r   r   Ú<module>   sp   

 h  8 DB4-  3 z%mqH_c'
*