3
eb 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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jt jj|| _|| _dS )zInitialize a Mailbox instance.N)ospathabspath
expanduser_path_factory)selfr   factorycreate r   /usr/lib/python3.6/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   | j | d S )N)r$   )r   r#   r   r   r   __delitem__1   s    zMailbox.__delitem__c             C   s(   y| j | 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
| j |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| j|S tj| j|}| j |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 j| j|j S )zReturn 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 | j S )zReturn a list of keys.)listr6   )r   r   r   r   keyse   s    zMailbox.keysc             c   s@   x:| j  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   | j  S )N)r:   )r   r   r   r   __iter__r   s    zMailbox.__iter__c             C   s   t | j S )z,Return a list of messages. Memory intensive.)r7   r:   )r   r   r   r   valuesu   s    zMailbox.valuesc             c   sD   x>| j  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 | j 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| j  D ]}| j| 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 | j| |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$| j  D ]}|| j|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|j }nt |dr(|j }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
|j 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rxtj }tjj||d}|j| |j	d |j
 }|jdt}|j| | jrt|jt rt|jt nt |tttjfrt |tjrtjdtd |j }t |tr| j|}|r|jdd}|jdt}|j| | jo|jt r|jt nt|drt|dr4tjd	td |j}d
}x|j }|jdr`|d
d d }n|jdr||d
d d }|sP |r|jdrd|dd
  }|jdt}|j| |}q:W | jr|r|jt r|j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   re   rv   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 j| ||| tjj| jdtjj| jdtjj| jdd| _tjj| js|rtj| jd x*| jj	 D ]}tj|d qnW n
t
| ji | _ddd| _d| _d| _d	S )
zInitialize a Maildir instance.tmpnewcur)r|   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~  | j  }y| j|| W n* tk
rB   |j  tj|j  Y nX t| t|t	r||j
 }| j|j  }|| jkrd}nd}d}tjj|jj| jd }tjj| j||| }t|t	rtj|jtjj|j|j f yLytj|j| W n( ttfk
r   tj|j| Y nX tj|j W nN tk
rx } z0tj|j |jtjkrftd| n W Y dd}~X nX |S )z$Add message and return assigned key. r}   r   z$Name clash with existing message: %sN)_create_tmprv   BaseExceptionrL   r   r$   name_sync_closer[   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 jt jj| 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| j | 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   | j |}| j|}| j |}t|tr.|}n|}tjj|}| j|kr`| j|j| jd  }nd}| j	| tjj
| j|}	tjj
| j||| }
t|trtj|	tjj|	|j f tj|	|
 dS )z>Replace the keyed message; raise KeyError if it doesn't exist.rW   r   NrZ   )r   r"   r[   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   | j |}ttjj| j|d }| jr4| j|}nt|}W dQ R X tjj|\}}|j	| | j
|kr|j|j| j
d  |jtjjtjj| j| |S )z4Return a Message representation or raise a KeyError.rbNrW   rZ   )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| j| j|d}|j j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   rb   rc   )r   r#   r   r   r   r   r3     s    zMaildir.get_bytesc             C   s$   t tjj| 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   | j   x:| jD ]0}y| j| 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   || 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   | j   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| jD ]F}t|dkr|d dkrt jjt jj| j|r|j|dd  qW |S )zReturn a list of folder names.rW   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| 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| jd| }t|| jd}t jj|d}t jj|sXt jt j|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| jd| }xTt jt jj|dt jt jj|d D ](}t|dk sZ|d dkr>td| q>W xPt j|D ]B}|dkrv|dkrv|dkrvt jjt jj||rvtd||f qvW x`t j|d	d
D ]N\}}}x |D ]}t j	t jj|| qW x |D ]}t j
t jj|| qW qW t j
| dS )z-Delete the named folder, which must be empty.r   r}   r~   rW   r   zFolder contains message(s): %sr|   z%Folder contains subdirectory '%s': %sF)topdownN)r   r   r   r   r   r   r   r   walkr$   rmdir)r   r   r   r   rootdirsZfilesr   r   r   remove_folder  s     

zMaildir.remove_folderc             C   s\   t j  }xNtjtjj| jdD ]4}tjj| jd|}|tjj| dkr tj| q W dS )zDelete old files in "tmp".r|   i@ N)timer   r   r   r   r   r   r$   )r   nowr   r   r   r   r   clean  s
    zMaildir.cleanrW   c             C   s   t j  }tj }d|kr$|jdd}d|kr8|jdd}dt|t|d d tj tj|f }tj	j
| jd|}ytj| 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\057r{   z\072z%s.M%sP%sQ%s.%srW   g    .Ar|   z&Name clash prevented file creation: %sN)r   socketgethostnamerb   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  | j d| j krbd}x<| jD ]2}tjj| j| }|| j| krLd}|| j|< q$W |sbdS i | _xl| jD ]b}| j| }xRtj	|D ]D}tjj
||}tjj|rq|j| jd }tjj
||| j|< qW qpW t j  | _dS )z!Update table of contents mapping.rU   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   sz   y,t jjt jj| j| j| r*| j| S W n tk
r@   Y nX | j  y
| j| S  tk
rt   t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| j | _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)rw   rx   ry   rz   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 j| ||| yt| jd}W nn tk
r } zR|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 Y dd}~X 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| j< |  jd7  _d| _| jd S )z$Add message and return assigned key.rW   T)r   _append_messager   r   r   )r   r!   r   r   r   r"   X  s
    z_singlefileMailbox.addc             C   s   | j | | 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 | | j|| 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   | j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   || 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   | j   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jdd | jj }|| jkrbt	d| j|f t
| j}yi }| j| xt| jj D ]|}| j| \}}| jj| | j| |j }x0| jjtd|| jj  }|sP |j| qW ||j f||< | j| qW |j | _W n"   |j  tj|j  Y nX t| | jj  tj| jj}	tj|j|	 ytj|j| j W n2 tk
r   tj| j tj|j| j Y nX t| jd| _|| _d| _ d| _| jrt | jdd dS )	z"Write any pending changes to disk.FNr   rU   z4Size of mailbox file changed (expected %i, found %i)i   zrb+)dotlock)!r   r   _sync_flushr   r   AssertionErrorra   tellr   r   _create_temporaryr   _pre_mailbox_hooksortedr8   _pre_message_hookrS   minrd   _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| j   W dz| jr| j  W d| j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   sJ   | j dkr| j  |dk	rFy
| j | S  tk
rD   t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 jdd | j j }t| jdkr:| j r:| j| j  y&| j| j  | j|}| j	| j  W n" t
k
r   | j j|  Y nX | j j  | j j | _|S )z;Append message to mailbox and return (start, stop) offsets.r   rU   )r   ra   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)rw   rx   ry   rz   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j| | jj jtd}| jj|| jj  }| j|jtd}|j	|dd j
d |S )z4Return a Message representation or raise a KeyError.    rQ   rX   Nr   )r   r   ra   rn   rb   rc   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| j|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 |\}}| jj| |s(| jj  | jj|| jj  }|jtdS )z3Return a string representation or raise a KeyError.rQ   )r   r   ra   rn   rS   r   rb   rc   )r   r#   r   r   r   r   r   r   r   r3     s    
z_mboxMMDF.get_bytesc             C   s<   | j |\}}| jj| |s(| jj  t| j| jj |S )z6Return a file-like representation or raise a KeyError.)r   r   ra   rn   _PartialFiler   )r   r#   r   r   r   r   r   r   r/     s
    
z_mboxMMDF.get_filec             C   s  d}t |tr| j|}t |trf|jdrf|jd}|dkr\|d| }||d d }q|}d}nJt |tr|j jd}d| }n(t |t	j
jr|j }|dk	r|jd}|dkrdtjtj j  }| jj }| jj|t  | j|| j| j | jj }||fS )	z1Format a message and blindly write to self._file.Ns   From rQ   rW   r   r   s   From MAILER-DAEMON rZ   )r[   rg   rP   rh   ro   find_mboxMMDFMessageget_fromrM   r1   r!   r   get_unixfromr   asctimegmtimer   r   rd   rc   rv   _mangle_from_)r   r!   r   newlineZauthorr   r   r   r   r   r   &  s0    







z_mboxMMDF._install_messageN)F)F)F)
rw   rx   ry   rz   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j| ||| 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   |j t dS )z,Called after writing each message to file f.N)rd   rc   )r   r   r   r   r   r   Q  s    zmbox._post_message_hookc             C   s   g g  }}d}| j jd x| j j }| j j }|jdr|t|t|k rl|rb|j|tt  n
|j| |j| d}q|s|r|j|tt  n
|j| P q|tkrd}qd}qW tt	t
||| _t| j| _| j j | _dS )z0Generate key-to-(start, stop) table of contents.Fr   s   From TN)r   ra   r   rn   ro   r   r   rc   dict	enumeratezipr   r   r   )r   startsstopsZlast_was_emptyline_posru   r   r   r   r   U  s0    






zmbox._generate_toc)NT)	rw   rx   ry   rz   r   re   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j| ||| 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   |j dt  dS )z-Called before writing each message to file f.s   N)rd   rc   )r   r   r   r   r   r     s    zMMDF._pre_message_hookc             C   s   |j td t  dS )z,Called after writing each message to file f.s   N)rd   rc   )r   r   r   r   r   r     s    zMMDF._post_message_hookc             C   s   g g  }}| j jd d}x|}| j j }| j j }|jdt r|j| xV|}| j j }| j j }|dt kr|j|tt  P qN|sN|j| P qNW q|sP qW tt	t
||| _t| j| _| j jdd | j j | _dS )z0Generate key-to-(start, stop) table of contents.r   s   rU   N)r   ra   rn   r   ro   rc   r   r   r  r  r  r   r   r   )r   r  r  next_posr  ru   r   r   r   r     s2    






zMMDF._generate_toc)NT)rw   rx   ry   rz   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 j| ||| tjj| jsj|r`tj| jd tjtjtj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   | j  }t|dkrd}nt|d }tjj| jt|}t|}d}z| j	rVt
| zfy| j|| W n: tk
r   | j	rt| t| d}tj|  Y nX t|tr| j|| W d| j	rt| X W d|st| X |S )z$Add message and return assigned key.r   rW   FTN)r8   r   maxr   r   r   r   rg   r   r   r   rv   r   r   r   r$   r[   r   _dump_sequences)r   r!   r8   Znew_keyr   r   closedr   r   r   r"     s6    


zMH.addc             C   sx   t jj| jt|}yt|d}W n> tk
r` } z"|jtjkrNt	d| n W Y dd}~X nX |j
  t j| 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   rg   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| jt|}yt|d}W n> tk
r` } z"|jtjkrNt	d| n W Y dd}~X nX zd| j
rrt| z@t jt j|t jt jB  | j|| t|tr| j|| W d| j
rt| 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   rg   r   r   r   r   r&   r   r   rL   r   O_TRUNCrv   r[   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| jt|d}nttjj| jt|d}W n> tk
r~ } z"|jtj	krlt
d| n W Y dd}~X nX |2 | j rt| zt|}W d| j rt| X W dQ R X x*| j j D ]\}}||kr|j| qW |S )z4Return a Message representation or raise a KeyError.zrb+r   zNo message with key: %sN)r   r   r   r   r   r   rg   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| jt|d}nttjj| jt|d}W n> tk
r~ } z"|jtj	krlt
d| n W Y dd}~X nX |6 | j rt| z|j jtdS | j rt| 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   rg   r   r   r   r&   r   rS   rb   rc   r   )r   r#   r   r   r   r   r   r3     s    zMH.get_bytesc             C   sf   yt tjj| jt|d}W n> tk
r\ } z"|jtjkrJt	d| n W Y dd}~X 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   rg   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| jD S )zReturn an iterator over keys.c             s   s   | ]}|j  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jt jj| jt|S )z9Return True if the keyed message exists, False otherwise.)r   r   r   r   r   rg   )r   r#   r   r   r   r?   9  s    zMH.__contains__c             C   s   t t| j 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| 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| j  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| jD ]&}t jjt jj| j|r|j| 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|| 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|| 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| j|}t j|}|dgkr:t jt jj|d n|g krDntd| j t j| 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   Zentriesr   r   r   r   k  s    

zMH.remove_folderc       
         s  i }t tjj| jdddd}t| j  x|D ]}y|jd\}}t }xT|j D ]H}|j rr|j	t
| qVdd |jdD \}}	|jt||	d	  qVW  fd
dt|D ||< t|| dkr||= W q2 tk
r   td|j  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)encodingr{   c             s   s   | ]}t |V  qd S )N)r   )r  xr   r   r   r    s    z#MH.get_sequences.<locals>.<genexpr>-rW   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   ru   r   contentsr8   specr   r   r   )r  r   r  w  s&    

 zMH.get_sequencesc             C   s
  t tjj| jdddd}ztjtj |jtjtjB  x|j	 D ]\}}t
|dkrXqB|j|d  d}d}xbtt|D ]R}|d	 |kr|sd
}|jd n*|rd}|jd||f  n|jd|  |}q|W |r|jt|d  qB|j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   r{   NFrW   Tr  z%s %sz %s
)r   r   r   r   r   rL   r   r   r  r>   r   rd   r   r  rg   r   )r   	sequencesr   r   r8   prevZ
completingr#   r   r   r   set_sequences  s.    zMH.set_sequencesc       	      C   sL  | j  }d}g }x| j D ]}|d |kr|j||d f y4tjtjj| jt|tjj| jt|d  W nH t	t
fk
r   tjtjj| jt|tjj| jt|d  Y nX tjtjj| jt| |d7 }qW |d | _t|dkrdS xB|j D ]6\}}x*|D ]"\}}||kr|||j|< qW qW | j| dS )z?Re-name messages to eliminate numbering gaps. Invalidates keys.r   rW   N)r  r6   r   r   r   r   r   r   rg   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|   |j  }| j  }x<|j D ]0\}}||kr6|j| q||kr||j|= qW x|D ]}||krT|g||< qTW | j| 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)rw   rx   ry   rz   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 j| ||| 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 j| |}t|tr$|j | j|< |S )z$Add message and return assigned key.)r   r"   r[   r   
get_labelsr.  )r   r!   r#   r   r   r   r"     s    
z	Babyl.addc             C   s"   t j| | || jkr| j|= dS )z=Remove the keyed message; raise KeyError if it doesn't exist.N)r   r$   r.  )r   r#   r   r   r   r$     s    
zBabyl.removec             C   s*   t j| || t|tr&|j | j|< dS )z>Replace the keyed message; raise KeyError if it doesn't exist.N)r   r(   r[   r   r/  r.  )r   r#   r!   r   r   r   r(     s    
zBabyl.__setitem__c       
      C   s  | j |\}}| jj| | jj  tj }x4| jj }|dt ksJ| rLP |j|jtd q.W tj }x0| jj }|tks| rP |j|jtd qlW || jj	  }|dkst
| jj|}|jtd}t|j | }	|	j|j  || jkr|	j| j|  |	S )z4Return a Message representation or raise a KeyError.s   *** EOOH ***rQ   r   )r   r   ra   rn   r\   r]   rc   rd   rb   r   r   rS   r   rm   set_visibler.  
set_labels)
r   r#   r   r   original_headersru   Zvisible_headersnZbodyr   r   r   r   r,     s0    


zBabyl.get_messagec       	      C   s   | j |\}}| jj| | jj  tj }x4| jj }|dt ksJ| rLP |j|jtd q.W x| jj }|tks|| rdP qdW |j	 }|| jj
  }|dkst| jj|}|jtd}|| S )z3Return a string representation or raise a KeyError.s   *** EOOH ***rQ   r   )r   r   ra   rn   r\   r]   rc   rd   rb   rm   r   r   rS   )	r   r#   r   r   r2  ru   Zheadersr3  rt   r   r   r   r3     s&    


zBabyl.get_bytesc             C   s   t j| j|jdtS )z6Return a file-like representation or raise a KeyError.rQ   )r\   r]   r3   rb   rc   )r   r#   r   r   r   r/   %  s    zBabyl.get_filec             C   s@   | j   t }x| jj D ]}|j| qW |j| j t|S )z4Return a list of user-defined labels in the mailbox.)r   r  r.  r<   rH   difference_update_special_labelsr7   )r   labelsZ
label_listr   r   r   r/  )  s    zBabyl.get_labelsc             C   s>  g g  }}| j jd d}g }x|}| j j }| j j }|dt krt|t|k rf|j|tt  |j| dd | j j dd jdD }|j| q |dks|dt krt|t|k r|j|tt  q |s |j|tt  P q W tt	t
||| _tt	|| _t| j| _| j jdd	 | j j | _dS )
z0Generate key-to-(start, stop) table of contents.r   s   c             S   s   g | ]}|j  r|j  qS r   )strip)r  labelr   r   r   r  @  s    z'Babyl._generate_toc.<locals>.<listcomp>rW   N   ,   rU   )r   ra   rn   r   rc   r   r   r   r  r  r  r   r.  r   r   )r   r  r  r  Zlabel_listsr  ru   r6  r   r   r   r   2  s4    



zBabyl._generate_tocc             C   sV   dt  }|dt  7 }| j }dd |D }|ddj| t  7 }|d7 }|j| dS )	z,Called before writing the mailbox to file f.s   BABYL OPTIONS:s
   Version: 5c             s   s   | ]}|j  V  qd S )N)rM   )r  r8  r   r   r   r  U  s    z*Babyl._pre_mailbox_hook.<locals>.<genexpr>s   Labels:r9  r:  N)rc   r/  r   rd   )r   r   Zbabylr6  r   r   r   r   P  s    zBabyl._pre_mailbox_hookc             C   s   |j dt  dS )z-Called before writing each message to file f.   N)rd   rc   )r   r   r   r   r   r   Z  s    zBabyl._pre_message_hookc             C   s   |j td  dS )z,Called after writing each message to file f.r:  N)rd   rc   )r   r   r   r   r   r   ^  s    zBabyl._post_message_hookc             C   s  | j j }t|trg }g }x0|j D ]$}|| jkr@|j| q&|j| q&W | j jd x |D ]}| j jd|j   q`W | j jd x$|D ]}| j jd|j  d  qW | j jt	 n| j jdt	  t|t
jjr0tj }t
jj|dd}|j| |jd x6|j }| j j|jd	t	 |d	ks8| r
P q
W | j jd
t	  t|trtj }	t
jj|	dd}
|
j|j  xz|	j }| j j|jd	t	 |d	ks| rP qW nB|jd x6|j }| j j|jd	t	 |d	ks| rP qW x,|jd}|sP | j j|jd	t	 q W nZt|tttjfr,t|tjrhtjdtd |j }t|tr~| j|}|jdd }|d dkr | j j|d| jd	t	 | j jd
t	  | j j|d| jd	t	 | j j||d jd	t	 n(| j jd
t	 t	  | j j|jd	t	 n^t |drzt |drXtjdtd |j!}|j }d}x|j }|j"dr|dd d	 }n|j"dr|dd d	 }| j j|jd	t	 |d	ks| rf|rd}| j jd
t	  |j| nP qfW x|j }|sP |j"dr,|dd t	 }n:|j"drJ|dd t	 }n|j"d	rf|dd t	 }| j j| qW nt#dt$| | j j }||fS )z0Write message contents and return (start, stop).   1s   , s   ,,    r9  s   1,,Fr   rQ   s   *** EOOH ***i   z8Use of StringIO input is deprecated, use BytesIO insteadrR   s   

rU   rW   Nrn   rT   zDUse of text mode files is deprecated, use a binary mode file insteadTs   
rV   zInvalid message type: %srZ   rY   rZ   rY   rZ   rZ   )%r   r   r[   r   r/  r5  r   rd   rM   rc   r1   r!   r   r\   r]   r^   r_   r`   ra   rn   rb   get_visiblerS   rh   rg   ri   rj   rk   rl   rm   rP   r   rE   rT   rf   rp   rq   )r   r!   r   Zspecial_labelsr6  r8  Zorig_bufferZorig_generatorru   Z
vis_bufferZvis_generatorrT   Z
body_startZoriginal_posZ
first_passr   r   r   r   r   b  s    











zBabyl._install_message)NT)rw   rx   ry   rz   	frozensetr5  r   r"   r$   r(   r,   r3   r/   r/  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| jtj| t |tr|j|  nt |trP| jtj	| n~t |t
rl| jtj| nbt |tjr| jtj| nDt|dr| jtj| n(|dkrtjjj|  ntdt| dS )zInitialize a Message instance.rS   NzInvalid message type: %s)r[   r1   r!   r   _become_messagecopydeepcopy_explain_torh   r2   rg   Zmessage_from_stringr\   TextIOWrapperZmessage_from_filerE   Zmessage_from_binary_filer   rp   rq   )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   r@    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)r[   r   rp   )r   r!   r   r   r   rC    s    
zMessage._explain_to)N)rw   rx   ry   rz   r   r@  rC  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j | _tj| | dS )z%Initialize a MaildirMessage instance.r}   r   N)rH  rI  r   rJ  r   r   )r   r!   r   r   r   r     s    
zMaildirMessage.__init__c             C   s   | j S )zReturn 'new' or 'cur'.)rH  )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)rH  rO   )r   r   r   r   r   r     s    zMaildirMessage.set_subdirc             C   s"   | j jdr| j dd S dS dS )z*Return as a string the flags that are set.z2,rU   Nr   )rI  ro   )r   r   r   r   	get_flags
  s    zMaildirMessage.get_flagsc             C   s   ddj t| | _dS )z)Set the given flags and unset all others.z2,r   N)r   r   rI  )r   flagsr   r   r   	set_flags  s    zMaildirMessage.set_flagsc             C   s$   | j djt| j t|B  dS )z.Set the given flag(s) without changing others.r   N)rM  r   r  rK  )r   flagr   r   r   add_flag  s    zMaildirMessage.add_flagc             C   s,   | j  r(| jdjt| j  t|  dS )z7Unset the given string flag(s) without changing others.r   N)rK  rM  r   r  )r   rN  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.)rJ  )r   r   r   r   r     s    zMaildirMessage.get_datec             C   s4   yt || _W n  tk
r.   td| Y nX dS )z9Set delivery date of message, in seconds since the epoch.zcan't convert to float: %sN)floatrJ  rO   rp   )r   Zdater   r   r   r   "  s    zMaildirMessage.set_datec             C   s   | j S )z%Get the message's "info" as a string.)rI  )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)r[   rg   rI  rp   rq   )r   infor   r   r   r   -  s    
zMaildirMessage.set_infoc             C   s  t |tr8|j| j  |j| j  |j| j  nht |trt	| j }d|kr`|j
d | j dkrv|j
d d|kr|j
d d|kr|j
d d|kr|j
d |jd	tj| j  nt |trt	| j }d|kr|jd
 d|kr|jd d|kr|jd nt |trt	| j }d|krD|jd
 d|krX|jd d|krl|jd d|kr|j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)r[   r	   rM  rK  r   r   r   r   r   r  rO  r   r   r   r   r  r   	add_labelr   rp   rq   )r   r!   rL  r   r   r   rC  4  sN    

















zMaildirMessage._explain_to)N)rw   rx   ry   rz   rE  r   r   r   rK  rM  rO  rP  r   r   r   r   rC  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   | j dd t|tjjrF|j }|dk	rF|jdrF| j |dd  tj| | dS )z'Initialize an mboxMMDFMessage instance.zMAILER-DAEMONTNzFrom rX   )r   r[   r1   r!   r   r   ro   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 j }|dt j| 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   | j dd| j dd S )z*Return as a string the flags that are set.Statusr   zX-Status)r+   )r   r   r   r   rK  z  s    z_mboxMMDFMessage.get_flagsc             C   s   t |}d
\}}x&dD ]}||kr||7 }|j| qW x&dD ]}||kr>||7 }|j| q>W |djt|7 }y| jd| W n  tk
r   | jd| Y nX y| jd| W n  tk
r   | jd| Y nX d	S )z)Set the given flags and unset all others.r   rT  rU  rW  rX  rY  r`  zX-StatusN)r   r   )rT  rU  )rW  rX  rY  )r  r$   r   r   replace_headerr&   Z
add_header)r   rL  Zstatus_flagsZxstatus_flagsrN  r   r   r   rM  ~  s&    

z_mboxMMDFMessage.set_flagsc             C   s$   | j djt| j t|B  dS )z.Set the given flag(s) without changing others.r   N)rM  r   r  rK  )r   rN  r   r   r   rO    s    z_mboxMMDFMessage.add_flagc             C   s4   d| ksd| kr0| j djt| j t|  dS )z7Unset the given string flag(s) without changing others.r`  zX-Statusr   N)rM  r   r  rK  )r   rN  r   r   r   rP    s    z_mboxMMDFMessage.remove_flagc             C   s  t |trt| j }d|kr(|jd d|kr:|jd d|krL|jd d|kr^|jd d|krp|jd |d	= |d
= dj| j j dd }y|j	t
jtj|d W n ttfk
r   Y nX n
t |tr|j| j  |j| j  nt |trZt| j }d|kr$|jd d|kr8|jd d|krL|jd |d	= |d
= nt |trt| j }d|kr|jd d|kr|jd d|kr|jd |d	= |d
= nt |trntdt| dS )zACopy mbox- or MMDF-specific state to message insofar as possible.rU  r~   rX  rY  rT  rS  rW  rV  Zstatuszx-statusr_  rX   Nz%a %b %d %H:%M:%S %Yr)  rZ  r[  r*  r+  z$Cannot convert to specified type: %s)r[   r	   r  rK  r   rO  r   r   r   r   calendarZtimegmr   ZstrptimerO   OverflowErrorr   rM  r   r   r  r   r]  r   rp   rq   )r   r!   rL  Z
maybe_dater   r   r   rC    s^    



















z_mboxMMDFMessage._explain_to)N)N)rw   rx   ry   rz   rE  r   r   r   rK  rM  rO  rP  rC  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)rw   rx   ry   rz   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j| | dS )z!Initialize an MHMessage instance.N)re  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)re  )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   re  )r   r!  r   r   r   r#    s    zMHMessage.set_sequencesc             C   s6   t |tr"|| jkr2| jj| ntdt| dS )z8Add sequence to list of sequences including the message.zsequence type must be str: %sN)r[   rg   re  r   rp   rq   )r   r(  r   r   r   r    s    

zMHMessage.add_sequencec             C   s*   y| j j| W n tk
r$   Y nX dS )zARemove sequence from the list of sequences including the message.N)re  r$   rO   )r   r(  r   r   r   remove_sequence  s    zMHMessage.remove_sequencec             C   sJ  t |trdt| j }d|kr*|jd n|jd |jd d|krP|jd d|krb|jd nt |trt| j }d|kr|jd n
|jd	 d|kr|jd d|kr|jd
 nt |trx|| j D ]}|j| qW n`t |t	r(t| j }d|kr|j
d d|krF|j
d nt |tr6ntdt| dS )z6Copy MH-specific state to message insofar as possible.r)  r~   rS  r[  rX  rZ  rT  ROrU  rY  r+  z$Cannot convert to specified type: %sN)r[   r	   r  r  r   rO  r   r   r  r   r]  r   rp   rq   )r   r!   r!  r(  r   r   r   rC    s@    










zMHMessage._explain_to)N)rw   rx   ry   rz   rE  r   r  r#  r  rf  rC  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.r.  _visibleNc             C   s   g | _ t | _tj| | dS )z#Initialize a BabylMessage instance.N)r.  r   rh  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)r.  )r   r   r   r   r/  (  s    zBabylMessage.get_labelsc             C   s   t || _dS )z&Set the list of labels on the message.N)r7   r.  )r   r6  r   r   r   r1  ,  s    zBabylMessage.set_labelsc             C   s6   t |tr"|| jkr2| jj| ntdt| dS )z+Add label to list of labels on the message.zlabel must be a string: %sN)r[   rg   r.  r   rp   rq   )r   r8  r   r   r   r]  0  s    

zBabylMessage.add_labelc             C   s*   y| j j| W n tk
r$   Y nX dS )z4Remove label from the list of labels on the message.N)r.  r$   rO   )r   r8  r   r   r   remove_label8  s    zBabylMessage.remove_labelc             C   s
   t | jS )z3Return a Message representation of visible headers.)r   rh  )r   r   r   r   r>  ?  s    zBabylMessage.get_visiblec             C   s   t || _dS )z2Set the Message representation of visible headers.N)r   rh  )r   Zvisibler   r   r   r0  C  s    zBabylMessage.set_visiblec             C   sj   x6| j j D ](}|| kr,| j 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.DateFromReply-ToToCCSubjectN)rj  rk  rl  rm  rn  ro  )rh  r8   ra  )r   headerr   r   r   update_visibleG  s    
zBabylMessage.update_visiblec             C   sv  t |tr~t| j }d|kr*|jd n|jd |jd d|ksNd|krX|jd d|krj|jd d	|kr||jd
 nt |trt| j }d|kr|jd n
|jd d	|kr|jd d|kr|jd nt |trt| j }d|kr|jd d|krr|jd nXt |t	rT|j
| j  x<| j D ]}|j| q>W nt |trbntdt| dS )z9Copy Babyl-specific state to message insofar as possible.r)  r~   rS  r,  r-  r\  r+  rT  r*  rV  rg  rU  rW  rY  rZ  z$Cannot convert to specified type: %sN)r[   r	   r  r/  r   rO  r   r   r  r   r0  r>  r]  r   rp   rq   )r   r!   r6  r8  r   r   r   rC  R  sF    










zBabylMessage._explain_to)N)rw   rx   ry   rz   rE  r   r/  r1  r]  ri  r>  r0  rq  rC  r   r   r   r   r     s   
c               @   s   e Zd ZdZdS )r   z&Message with MMDF-specific properties.N)rw   rx   ry   rz   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|j | _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jS )zRead bytes.)_readr   rS   )r   sizer   r   r   rS     s    z_ProxyFile.readc             C   s   | j || jjS )zRead bytes.)rt  r   read1)r   ru  r   r   r   rv    s    z_ProxyFile.read1c             C   s   | j || jjS )zRead a line.)rt  r   rn   )r   ru  r   r   r   rn     s    z_ProxyFile.readlinec             C   s>   g }x4| D ],}|j | |dk	r
|t|8 }|dkr
P q
W |S )zRead multiple lines.Nr   )r   r   )r   sizehintrB   ru   r   r   r   	readlines  s    

z_ProxyFile.readlinesc             c   s    x| j  }|sdS |V  qW dS )zIterate over lines.N)rn   )r   ru   r   r   r   r;     s
    z_ProxyFile.__iter__c             C   s   | j S )zReturn the position.)rr  )r   r   r   r   r     s    z_ProxyFile.tellr   c             C   s4   |dkr| j j| j | j j|| | j j | _dS )zChange position.rW   N)r   ra   rr  r   )r   offsetwhencer   r   r   ra     s    z_ProxyFile.seekc          
   C   s0   t | dr,zt | jdr"| j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 ||}| j j | _|S )z"Read size bytes using read_method.NrW   rZ   )r   ra   rr  r   )r   ru  read_methodrB   r   r   r   rt    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   | j   d S )N)rL   )r   excr   r   r   __exit__  s    z_ProxyFile.__exit__c             C   s
   | j j S )N)r   readable)r   r   r   r   r    s    z_ProxyFile.readablec             C   s
   | j j S )N)r   writable)r   r   r   r   r    s    z_ProxyFile.writablec             C   s
   | j j S )N)r   seekable)r   r   r   r   r    s    z_ProxyFile.seekablec             C   s
   | j 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   )rw   rx   ry   rz   r   rS   rv  rn   rx  r;   r   ra   rL   rt  r|  r~  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 j| || || _|| _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| | 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j| || dS )z8Change position, possibly with respect to start or stop.r   rW   rU   N)r  rr  r  r   ra   )r   ry  rz  r   r   r   ra     s    z_PartialFile.seekc             C   sB   | j | j }|dkrdS |dks0|dk s0||kr4|}tj| ||S )z;Read size bytes using read_method, honoring start and stop.r   r   N)r  rr  r   rt  )r   ru  r{  Z	remainingr   r   r   rt    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   )	rw   rx   ry   rz   r   r   ra   rt  rL   r   r   r   r   r     s   


	r   Tc          4   C   s  d}yZt rpyt j| 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 Y dd}~X nX |r^yt| j
d }|j  W n: tk
r } z|jtjtjfkrdS  W Y dd}~X nX y`ytj|j
| j
d  d}W n2 ttfk
r   tj|j
| j
d  d}Y nX tj|j
 W n0 tk
r\   tj|j
 t	d| j
 Y nX W n8   t r|t j| t j |rtj| 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 j| t j tjj| jd r4tj| 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 j| t jt jB t jB d}z
t| dS t j| 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j tj tj 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$   | j   ttdr tj| j  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 |  | j  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)rw   rx   ry   rz   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)rw   rx   ry   rz   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)rw   rx   ry   rz   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)rw   rx   ry   rz   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)rw   rx   ry   rz   r   r   r   r   r   a  s   )T)0rz   r   r   rc  r   r   rA  rj   r1   Zemail.messageZemail.generatorr\   r-   r  ImportError__all__rc   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'
*