
[[\1                @   s0  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 Wn e k
 r d Z Yn Xd d d d d d d	 d
 d d d d g Z e j j d  Z Gd d   d  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d	   d	 e j j  Z Gd d
   d
 e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd  d   d e  Z  Gd! d   d e  Z! Gd" d#   d#  Z" Gd$ d%   d% e"  Z# d& d' d(  Z$ d) d*   Z% d+ d,   Z& d- d.   Z' d/ d0   Z( d1 d2   Z) Gd3 d4   d4 e*  Z+ Gd5 d6   d6 e+  Z, Gd7 d8   d8 e+  Z- Gd9 d:   d: e+  Z. Gd; 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asciic               @   s  e  Z d  Z d Z d d 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 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 d0 d1  Z d2 d3   Z d d4 d5  Z d6 d7   Z d8 d9   Z d: d;   Z d< d=   Z  d> d?   Z! d@ Z" d@ dA dB  Z# d S)Cr   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.4/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__0   s    zMailbox.__delitem__c             C   s*   y |  j  |  Wn t k
 r% Yn Xd S)z'If the keyed message exists, remove it.N)r   KeyError)r   r   r   r   r   discard3   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  |  SWn t k
 r) | SYn Xd 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   sH   |  j  s |  j |  St j |  j |    } |  j  |  SWd QXd 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$   E   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'   M   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_stringQ   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   r.   X   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   iterkeys`   s    zMailbox.iterkeysc             C   s   t  |  j    S)zReturn a list of keys.)listr1   )r   r   r   r   keysd   s    zMailbox.keysc             c   sF   x? |  j    D]1 } y |  | } Wn t k
 r8 w Yn X| Vq Wd S)z%Return an iterator over all messages.N)r1   r!   )r   r   valuer   r   r   
itervaluesh   s    zMailbox.itervaluesc             C   s
   |  j    S)N)r5   )r   r   r   r   __iter__q   s    zMailbox.__iter__c             C   s   t  |  j    S)z,Return a list of messages. Memory intensive.)r2   r5   )r   r   r   r   valuest   s    zMailbox.valuesc             c   sL   xE |  j    D]7 } y |  | } Wn t k
 r8 w Yn X| | f Vq Wd S)z.Return an iterator over (key, message) tuples.N)r1   r!   )r   r   r4   r   r   r   	iteritemsx   s    zMailbox.iteritemsc             C   s   t  |  j    S)z9Return a list of (key, message) tuples. Memory intensive.)r2   r8   )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 Wd S)zDelete all messages.N)r3   r"   )r   r   r   r   r   clear   s    zMailbox.clearc             C   s8   y |  | } Wn t  k
 r& | SYn 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   s7   x0 |  j    D] } | |  j |  f SWt d   d S)z6Delete an arbitrary (key, message) pair and return it.zNo messages in mailboxN)r1   r>   r!   )r   r   r   r   r   popitem   s    zMailbox.popitemc             C   s   t  | d  r | j   } n$ t  | d  r< | j   } n | } d } x= | D]5 \ } } y | |  | <WqO t k
 r d } YqO XqO W| r t d   n  d S)z4Change the messages that correspond to certain keys.r8   r9   FTzNo message with key(s)N)hasattrr8   r9   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   s6   y | j  d  SWn t k
 r1 t d   Yn Xd  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  r t j   } t j j | | d  } | j |  | j	 d  | j
   } | j d t  } | j |  |  j r| j t  r| j t  qnt  | t t t j f  rt  | t j  r t j d t d  | j   } n  t  | t  r|  j |  } n  | r5| j d d  } n  | j d t  } | j |  |  j r| j t  r| j t  qnDt | d  rt | d  rt j d	 t d  | j } n  d
 } x | j   } | j d  r| d
 d  d } n& | j d  r| d
 d  d } n  | s(Pn  | rT| j d  rTd | d d
  } n  | j d t  } | j |  | } q|  j r| r| j t  r| j t  qn t d t |    d
 S)z%Dump message contents to target file.r   s   
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      s   From s   >From    zInvalid message type: %s)
isinstancer,   r   r   ioBytesIO	generatorBytesGeneratorflattenseekrM   replacelinesepwrite_append_newlineendswithstrbytesStringIOwarningswarnDeprecationWarninggetvaluerK   r@   rN   readline
startswith	TypeErrortype)	r   r   targetZmangle_from_rN   gendataZlastlineliner   r   r   _dump_message   sZ    	
	
	zMailbox._dump_message)$__name__
__module____qualname____doc__r   r   r   r    r"   r#   r&   r$   r'   r0   r.   r*   r1   r3   r5   r6   r7   r8   r9   r:   r;   r<   r>   r?   rC   rD   rE   rF   rG   rK   r^   ro   r   r   r   r   r       sB   			c               @   sH  e  Z d  Z d Z d Z d 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"   Z d# d$   Z d% d&   Z d' d(   Z d) d*   Z d+ d,   Z d- Z d. d/   Z d0 d1   Z d2 d3   Z d4 d5   Z d S)6r   zA qmail-style Maildir mailbox.:NTc             C   s  t  j |  | | |  i t j j |  j d  d 6t j j |  j d  d 6t j j |  j d  d 6|  _ t j j |  j  s | r t j |  j d  x9 |  j j	   D] } t j | d  q Wq t
 |  j   n  i  |  _ i d d 6d d 6|  _ d |  _ d |  _ d S)zInitialize a Maildir instance.tmpnewcuri  r   g?N)r   r   r   r   joinr   _pathsexistsmkdirr7   NoSuchMailboxError_toc_toc_mtimes
_last_read_skewfactor)r   dirnamer   r   r   r   r   r   r     s    		zMaildir.__init__c             C   s  |  j    } y |  j | |  Wn/ t k
 rQ | j   t j | j    Yn Xt |  t | t	  r | j
   } |  j | j   } | |  j k r d } q n d } d } t j j | j  j |  j  d } t j j |  j | | |  } t | t	  r5t j | j t j j | j  | j   f  n  yL t t d  rmt j | j |  t j | j  n t j | j |  Wn] t k
 r} z= t j | j  | j t j k rt d |   n   WYd d } ~ Xn X| S)z$Add message and return assigned key. rv   r   linkz$Name clash with existing message: %sN)_create_tmpro   BaseExceptionrG   r   r   name_sync_closerT   r	   
get_subdircolonget_infor   basenamesplitrx   r   utimegetatimeget_dater@   r   renameOSErrorerrnoEEXISTExternalClashError)r   r   Ztmp_filesubdirsuffixuniqdester   r   r   r      s@    

%%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   rx   r   _lookup)r   r   r   r   r   r   I  s    zMaildir.removec             C   s0   y |  j  |  Wn t t f k
 r+ Yn Xd S)z'If the keyed message exists, remove it.N)r   r!   FileNotFoundError)r   r   r   r   r   r"   M  s    zMaildir.discardc             C   s$  |  j  |  } |  j |  } |  j  |  } t | t  rE | } n | } t j j |  } |  j | k r |  j | j |  j  d } n d } |  j	 |  t j j
 |  j |  }	 t j j
 |  j | | |  }
 t | t  rt j |	 t j j |	  | j   f  n  t j |	 |
  d S)z>Replace the keyed message; raise KeyError if it doesn't exist.rP   r   NrS   )r   r   rT   r	   r   r   r   r   r   r"   rx   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#   U  s"    	 	"zMaildir.__setitem__c             C   s   |  j  |  } t t j j |  j |  d  . } |  j rN |  j |  } n t |  } Wd QXt j j |  \ } } | j	 |  |  j
 | k r | j | j |  j
  d  n  | j t j j t j j |  j |    | S)z4Return a Message representation or raise a KeyError.rbNrP   rS   )r   openr   r   rx   r   r   r	   r   
set_subdirr   set_infoset_dategetmtime)r   r   Zsubpathfmsgr   r   r   r   r   r'   p  s    $	 +zMaildir.get_messagec          
   C   sM   t  t j j |  j |  j |   d   } | j   j t d  SWd QXd S)z2Return a bytes representation or raise a KeyError.r   s   
N)	r   r   r   rx   r   r   rM   r[   r\   )r   r   r   r   r   r   r.     s    -zMaildir.get_bytesc             C   s4   t  t j j |  j |  j |   d  } t |  S)z6Return a file-like representation or raise a KeyError.r   )r   r   r   rx   r   r   
_ProxyFile)r   r   r   r   r   r   r*     s    *zMaildir.get_filec             c   sP   |  j    x? |  j D]4 } y |  j |  Wn t k
 rB w Yn X| Vq Wd S)zReturn an iterator over keys.N)_refreshr}   r   r!   )r   r   r   r   r   r1     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   rD     s    zMaildir.flushc             C   s   d S)zLock the mailbox.Nr   )r   r   r   r   rE     s    zMaildir.lockc             C   s   d S)z#Unlock the mailbox if it is locked.Nr   )r   r   r   r   rF     s    zMaildir.unlockc             C   s   d S)zFlush and close the mailbox.Nr   )r   r   r   r   rG     s    zMaildir.closec             C   s   g  } xz t  j |  j  D]f } t |  d k r | d d k r t  j j t  j j |  j |   r | j | d d   q q W| S)zReturn a list of folder names.rP   r   .N)r   listdirr   r   r   isdirrx   append)r   r=   entryr   r   r   list_folders  s    "$zMaildir.list_foldersc             C   s/   t  t j j |  j d |  d |  j d d S)z/Return a Maildir instance for the named folder.r   r   r   F)r   r   r   rx   r   r   )r   folderr   r   r   
get_folder  s    	zMaildir.get_folderc             C   s   t  j j |  j d |  } t | d |  j } t  j j | d  } t  j j |  s t  j t  j | t  j	 t  j
 Bd   n  | S)z>Create a folder and return a Maildir instance representing it.r   r   Zmaildirfolderi  )r   r   rx   r   r   r   rz   rG   r   O_CREATO_WRONLY)r   r   r   r=   Zmaildirfolder_pathr   r   r   
add_folder  s    zMaildir.add_folderc             C   s  t  j j |  j d |  } xw t  j t  j j | d   t  j t  j j | d   D]; } t |  d k  s | d d k rW t d |   qW qW Wxu t  j |  D]d } | d k r | d k r | d k r t  j j t  j j | |   r t d | | f   q q Wx t  j | d	 d
 D]i \ } } } x* | D]" } t  j	 t  j j | |   q:Wx* | D]" } t  j
 t  j j | |   qgWq$Wt  j
 |  d S)z-Delete the named folder, which must be empty.r   rv   rw   rP   r   zFolder contains message(s): %sru   z%Folder contains subdirectory '%s': %stopdownFN)r   r   rx   r   r   r   NotEmptyErrorr   walkr   rmdir)r   r   r   r   rootdirsZfilesr   r   r   remove_folder  s     #"$!% $zMaildir.remove_folderc             C   s   t  j    } xp t j t j j |  j d   D]M } t j j |  j d |  } | t j j |  d k r. t j |  q. q. Wd S)zDelete old files in "tmp".ru   i@ N)timer   r   r   rx   r   r   r   )r   nowr   r   r   r   r   clean  s
    (zMaildir.cleanrP   c             C   s  t  j    } t j   } d | k r9 | j d d  } n  d | k rZ | j d d  } n  d t |  t | d d  t j   t j | f } t j	 j
 |  j d |  } y t j |  WnD t k
 rt j d 7_ y t |  SWn t k
 r Yn XYn Xt d	 |   d
 S)z=Create a file in the tmp subdirectory and open and return it./z\057rt   z\072z%s.M%sP%sQ%s.%srP   g    .Aru   z&Name clash prevented file creation: %sN)r   socketgethostnamer[   intr   getpidr   _countr   rx   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 r d } xS |  j D]H } t j j |  j |  } | |  j | k rk d } n  | |  j | <q0 W| s d Sn  i  |  _ x |  j D] } |  j | } xv t j	 |  D]e } t j j
 | |  } t j j |  r q n  | j |  j  d } t j j
 | |  |  j | <q Wq Wt  j    |  _ d S)z!Update table of contents mapping.rO   FTNr   )r   r   r   r~   r   r   r   ry   r}   r   rx   r   r   r   )r   Zrefreshr   mtimer   r   pr   r   r   r   r     s&     		$zMaildir._refreshc             C   s   y: t  j j t  j j |  j |  j |   r9 |  j | SWn t k
 rN Yn X|  j   y |  j | SWn" t k
 r t d |   Yn Xd S)z=Use TOC to return subpath for given key, or raise a KeyError.zNo message with key: %sN)r   r   rz   rx   r   r}   r!   r   )r   r   r   r   r   r   !  s    +
zMaildir._lookupc             C   sm   t  |  d  s! |  j   |  _ n  xE y |  t |  j  SWq$ t k
 rQ d SYq$ t k
 re w$ Yq$ Xq$ d S)z0Return the next message in a one-time iteration._onetime_keysN)r@   r1   r   nextStopIterationr!   )r   r   r   r   r   /  s    zMaildir.next)rp   rq   rr   rs   r   r   r   r   r"   r#   r'   r.   r*   r1   r:   r;   rD   rE   rF   rG   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 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  } Wn t k
 r } zw | j t j k r | rn t |  j d  } q t |  j   n3 | j t j t j	 f k r t |  j d  } n   WYd d } ~ Xn 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   ?  s$    						z_singlefileMailbox.__init__c             C   sF   |  j    |  j |  |  j |  j <|  j d 7_ d |  _ |  j d S)z$Add message and return assigned key.rP   T)r   _append_messager}   r   r   )r   r   r   r   r   r   V  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   `  s    
z_singlefileMailbox.removec             C   s0   |  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#   f  s    z_singlefileMailbox.__setitem__c             c   s    |  j    |  j j   Dd Hd S)zReturn an iterator over keys.N)r   r}   r3   )r   r   r   r   r1   l  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:   q  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;   v  s    
z_singlefileMailbox.__len__c             C   s&   |  j  s" t |  j  d |  _  n  d S)zLock the mailbox.TN)r   
_lock_filer   )r   r   r   r   rE   {  s    	z_singlefileMailbox.lockc             C   s&   |  j  r" t |  j  d |  _  n  d S)z#Unlock the mailbox if it is locked.FN)r   _unlock_filer   )r   r   r   r   rF     s    	z_singlefileMailbox.unlockc       
      C   s  |  j  s/ |  j r+ t |  j  d |  _ n  d S|  j d k	 sD t  |  j j d d  |  j j   } | |  j k r t	 d |  j | f   n  t
 |  j  } y i  } |  j |  x t |  j j    D] } |  j | \ } } |  j j |  |  j |  | j   } xB |  j j t d | |  j j     } | sCPn  | j |  q| | j   f | | <|  j |  q W| j   |  _ Wn% | j   t j | j    Yn Xt |  |  j j   t j |  j  j }	 t j | j |	  y t j | j |  j  Wn8 t k
 rEt j |  j  t j | j |  j  Yn Xt |  j d  |  _ | |  _ d |  _  d |  _ |  j rt  |  j d d n  d S)	z"Write any pending changes to disk.FNr   rO   z4Size of mailbox file changed (expected %i, found %i)i   zrb+dotlock)!r   r   _sync_flushr   r}   AssertionErrorrZ   tellr   r   _create_temporaryr   _pre_mailbox_hooksortedr3   _pre_message_hookrM   minr]   _post_message_hookrG   r   r   r   r   r   st_modechmodr   r   r   r   r   )
r   Zcur_lenZnew_fileZnew_tocr   startstopZ	new_startrN   moder   r   r   rD     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   s1   |  j    |  j r  |  j   n  |  j j   d S)zFlush and close the mailbox.N)rD   r   rF   r   rG   )r   r   r   r   rG     s    
	z_singlefileMailbox.closec             C   sc   |  j  d k r |  j   n  | d k	 r_ y |  j  | SWq_ t k
 r[ t d |   Yq_ Xn  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 rT |  j rT |  j |  j   n  y3 |  j |  j   |  j |  } |  j	 |  j   Wn% t
 k
 r |  j  j |    Yn X|  j  j   |  j  j   |  _ | S)z;Append message to mailbox and return (start, stop) offsets.r   rO   )r   rZ   r   r   r}   r   r   r   _install_messager   r   truncaterD   r   )r   r   ZbeforeZoffsetsr   r   r   r     s    z"_singlefileMailbox._append_message)rp   rq   rr   rs   r   r   r   r#   r1   r:   r;   rE   rF   rD   r   r   r   rG   r   r   r   r   r   r   r   <  s"   
@
r   c               @   sa   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   s   |  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.    s   
rQ   Nr   )r   r   rZ   rg   r[   r\   rM   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)r,   r-   r.   r/   )r   r   from_r   r   r   r0   
  s    z_mboxMMDF.get_stringc             C   sj   |  j  |  \ } } |  j j |  | s; |  j j   n  |  j j | |  j j    } | j t d  S)z3Return a string representation or raise a KeyError.s   
)r   r   rZ   rg   rM   r   r[   r\   )r   r   r   r   r   r   r   r   r   r.     s    z_mboxMMDF.get_bytesc             C   sW   |  j  |  \ } } |  j j |  | s; |  j j   n  t |  j |  j j   |  S)z6Return a file-like representation or raise a KeyError.)r   r   rZ   rg   _PartialFiler   )r   r   r   r   r   r   r   r   r*     s
    z_mboxMMDF.get_filec             C   s  d } t  | t  r' |  j |  } n  t  | t  r | j d  r | j d  } | d k r | d |  } | | d d  } q	| } d } ns t  | t  r | j   j d  } d | } nB t  | t	 j
 j  r	| j   } | d k	 r	| j d  } q	n  | d k r7d t j t j    j   } n  |  j j   } |  j j | t  |  j | |  j |  j  |  j j   } | | f S)	z1Format a message and blindly write to self._file.Ns   From s   
rP   r   r   s   From MAILER-DAEMON rS   )rT   r`   rK   ra   rh   find_mboxMMDFMessageget_fromrH   r,   r   r   get_unixfromr   asctimegmtimer   r   r]   r\   ro   _mangle_from_)r   r   r   newlineZauthorr   r   r   r   r   r      s0    	"z_mboxMMDF._install_messageN)
rp   rq   rr   rs   r   r'   r0   r.   r*   r   r   r   r   r   r     s   
	r   c               @   sL   e  Z d  Z d Z d Z d Z d 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   F  s    	zmbox.__init__c             C   s   | j  t  d S)z,Called after writing each message to file f.N)r]   r\   )r   r   r   r   r   r   K  s    zmbox._post_message_hookc             C   sL  g  g  } } d } |  j  j d  x |  j  j   } |  j  j   } | j d  r t |  t |  k  r | r | j | t t   q | j |  n  | j |  d } q& | s | r | j | t t   n | j |  Pq& | t k r d } q& d } q& t t	 t
 | |    |  _ t |  j  |  _ |  j  j   |  _ d S)z0Generate key-to-(start, stop) table of contents.Fr   s   From TN)r   rZ   r   rg   rh   r   r   r\   dict	enumeratezipr}   r   r   )r   startsstopsZlast_was_emptyline_posrn   r   r   r   r   O  s0    			zmbox._generate_toc)	rp   rq   rr   rs   r   r^   r   r   r   r   r   r   r   r   =  s   c               @   sL   e  Z d  Z d Z d 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   t  s    	zMMDF.__init__c             C   s   | j  d t  d S)z-Called before writing each message to file f.s   N)r]   r\   )r   r   r   r   r   r   y  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)r]   r\   )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   Pqm | sm | j |  Pqm qm q& | s& Pq& q& t t	 t
 | |    |  _ t |  j  |  _ |  j  j d d  |  j  j   |  _ d S)z0Generate key-to-(start, stop) table of contents.r   s   rO   N)r   rZ   rg   r   rh   r\   r   r   r   r   r   r}   r   r   )r   r   r   next_posr  rn   r   r   r   r     s2    
zMMDF._generate_toc)rp   rq   rr   rs   r   r   r   r   r   r   r   r   r   q  s
   c               @   s$  e  Z d  Z d Z d 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!   Z d" d#   Z d$ d%   Z d& d'   Z d( d)   Z d* d+   Z d, d-   Z d. d/   Z d S)0r   zAn MH mailbox.NTc             C   s   t  j |  | | |  t j j |  j  s | r t j |  j d  t j t j t j j	 |  j d  t j
 t j Bt j Bd   q t |  j   n  d |  _ d S)zInitialize an MH instance.i  z.mh_sequencesi  FN)r   r   r   r   rz   r   r{   rG   r   rx   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	 r t
 |  n  z y |  j | |  WnH t k
 r |  j	 r t |  n  t |  d } t j |    Yn Xt | t  r|  j | |  n  Wd |  j	 rt |  n  XWd | s6t |  n  X| S)z$Add message and return assigned key.r   rP   FTN)r3   r   maxr   r   rx   r   r`   r   r   r   ro   r   r   r   r   rT   r   _dump_sequences)r   r   r3   Znew_keyr   r   closedr   r   r   r     s6    			
	zMH.addc             C   s   t  j j |  j t |   } y t | d  } WnM t k
 r } z- | j t j k rk t	 d |   n   WYd d } ~ Xn 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   rx   r   r`   r   r   r   r   r!   rG   r   )r   r   r   r   r   r   r   r   r     s    
z	MH.removec             C   s   t  j j |  j t |   } y t | d  } WnM t k
 r } z- | j t j k rk t	 d |   n   WYd d } ~ Xn Xz |  j
 r t |  n  zY t  j t  j | t  j t  j B  |  j | |  t | t  r |  j | |  n  Wd |  j
 rt |  n  XWd t |  Xd S)z>Replace the keyed message; raise KeyError if it doesn't exist.zrb+zNo message with key: %sN)r   r   rx   r   r`   r   r   r   r   r!   r   r   rG   r   O_TRUNCro   rT   r   r  r   r   )r   r   r   r   r   r   r   r   r   r#     s$    	#	zMH.__setitem__c              C   s>  y^ |  j  r6 t t j j |  j t |   d  } n' t t j j |  j t |   d  } WnM t k
 r } z- | j t j	 k r t
 d |   n   WYd d } ~ Xn X| E |  j  r t |  n  z t |  } Wd |  j  r t |  n  XWd QXx< |  j   j   D]( \ } } | | k r| j |  qqW| S)z4Return a Message representation or raise a KeyError.zrb+r   zNo message with key: %sN)r   r   r   r   rx   r   r`   r   r   r   r!   r   r   r   get_sequencesr9   add_sequence)r   r   r   r   r   r   key_listr   r   r   r'     s&    	*+		zMH.get_messagec              C   s	  y^ |  j  r6 t t j j |  j t |   d  } n' t t j j |  j t |   d  } WnM t k
 r } z- | j t j	 k r t
 d |   n   WYd d } ~ Xn X| O |  j  r t |  n  z | j   j t d  SWd |  j  r t |  n  XWd QXd S)z2Return a bytes representation or raise a KeyError.zrb+r   zNo message with key: %sNs   
)r   r   r   r   rx   r   r`   r   r   r   r!   r   rM   r[   r\   r   )r   r   r   r   r   r   r   r.     s    	*+		zMH.get_bytesc             C   s   y+ t  t j j |  j t |   d  } WnM t k
 rz } z- | j t j k re t	 d |   n   WYd d } ~ Xn Xt
 |  S)z6Return a file-like representation or raise a KeyError.r   zNo message with key: %sN)r   r   r   rx   r   r`   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>0  s    zMH.iterkeys.<locals>.<genexpr>)iterr   r   r   r   )r   r   r   r   r1   .  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   rz   rx   r   r`   )r   r   r   r   r   r:   3  s    zMH.__contains__c             C   s   t  t |  j     S)z*Return a count of messages in the mailbox.)r   r2   r1   )r   r   r   r   r;   7  s    z
MH.__len__c             C   sJ   |  j  sF t t j j |  j d  d  |  _ t |  j  d |  _  n  d S)zLock the mailbox.z.mh_sequenceszrb+TN)r   r   r   r   rx   r   r   r   )r   r   r   r   rE   ;  s    	$zMH.lockc             C   s9   |  j  r5 t |  j  t |  j  |  ` d |  _  n  d S)z#Unlock the mailbox if it is locked.FN)r   r   r   r   )r   r   r   r   rF   B  s
    	z	MH.unlockc             C   s   d S)z&Write any pending changes to the disk.Nr   )r   r   r   r   rD   J  s    zMH.flushc             C   s   |  j  r |  j   n  d S)zFlush and close the mailbox.N)r   rF   )r   r   r   r   rG   N  s    	zMH.closec             C   s[   g  } xN t  j |  j  D]: } t  j j t  j j |  j |   r | j |  q q W| S)zReturn a list of folder names.)r   r   r   r   r   rx   r   )r   r=   r   r   r   r   r   S  s
    $zMH.list_foldersc             C   s+   t  t j j |  j |  d |  j d d S)z+Return an MH instance for the named folder.r   r   F)r   r   r   rx   r   r   )r   r   r   r   r   r   [  s    zMH.get_folderc             C   s%   t  t j j |  j |  d |  j S)z:Create a folder and return an MH instance representing it.r   )r   r   r   rx   r   r   )r   r   r   r   r   r   `  s    zMH.add_folderc             C   s   t  j j |  j |  } t  j |  } | d g k rU t  j t  j j | d   n" | g  k rd n 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   rx   r   r   r   r   r   )r   r   r   Zentriesr   r   r   r   e  s    zMH.remove_folderc       
         sb  i  } t  t j j |  j d  d d d /} t |  j      x| D]} y | j d  \ } } t   } xr | j   D]d } | j   r | j	 t
 |   q} d d   | j d  D \ } }	 | j t | |	 d	   q} W  f d
 d   t |  D | | <t | |  d k r(| | =n  WqI t k
 rSt d | j     YqI XqI WWd QX| S)z=Return a name-to-key-list dictionary to define each sequence.z.mh_sequencesrencodingASCIIrt   c             s   s   |  ] } t  |  Vq d  S)N)r   )r  xr   r   r   r  ~  s    z#MH.get_sequences.<locals>.<genexpr>-rP   c                s"   g  |  ] } |   k r |  q Sr   r   )r  r   )all_keysr   r   
<listcomp>  s   	 z$MH.get_sequences.<locals>.<listcomp>r   z"Invalid sequence specification: %sN)r   r   r   rx   r   setr3   r   r  r   r   rC   ranger   r   rJ   FormatErrorrstrip)
r   Zresultsr   rn   r   contentsr3   specr   r   r   )r  r   r  q  s&    *	"#zMH.get_sequencesc             C   sk  t  t j j |  j d  d d d } z2t j t j  | j t j t j B  x| j	   D] \ } } t
 |  d k r q] n  | j | d  d } d } x t t |   D]r } | d	 | k r | sd
 } | j d  qn7 | rd } | j d | | f  n | j d |  | } q W| rG| j t |  d  q] | j d  q] WWd t |  Xd S)z:Set sequences using the given name-to-key-list dictionary.z.mh_sequenceszr+r  r  r   rt   NFrP   Tr  z%s %sz %s
)r   r   r   rx   r   rG   r   r   r  r9   r   r]   r   r  r`   r   )r   	sequencesr   r   r3   prevZ
completingr   r   r   r   set_sequences  s.    '&
zMH.set_sequencesc       	      C   s  |  j    } d } g  } x|  j   D] } | d | k r| j | | d f  t t d  r t j t j j |  j t	 |   t j j |  j t	 | d    t j
 t j j |  j t	 |    qt j t j j |  j t	 |   t j j |  j t	 | d    n  | d 7} q% W| d |  _ t |  d k rEd SxS | j   D]E \ } } x6 | D]. \ } } | | k re| | | j |  <qeqeWqRW|  j |  d S)z?Re-name messages to eliminate numbering gaps. Invalidates keys.r   rP   r   N)r  r1   r   r@   r   r   r   rx   r   r`   unlinkr   r   r   r9   indexr  )	r   r  r  Zchangesr   r   r
  oldrv   r   r   r   pack  s*    !#(!&zMH.packc             C   s   | j    } |  j    } xU | j   D]G \ } } | | k rM | j |  q% | | k r% | | j |  =q% q% Wx* | D]" } | | k rw | g | | <qw qw W|  j |  d S)z;Inspect a new MHMessage and update sequences appropriately.N)r  r9   r   r!  r  )r   r   r   Zpending_sequencesZall_sequencesr   r
  sequencer   r   r   r    s    zMH._dump_sequences)rp   rq   rr   rs   r   r   r   r#   r'   r.   r*   r1   r:   r;   rE   rF   rD   rG   r   r   r   r   r  r  r#  r  r   r   r   r   r     s.   "c               @   s   e  Z d  Z d Z e d%  Z d	 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deletedfiledanswered	forwarded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  r7 | j   |  j | <n  | S)z$Add message and return assigned key.)r   r   rT   r   
get_labelsr,  )r   r   r   r   r   r   r     s    z	Babyl.addc             C   s0   t  j |  |  | |  j k r, |  j | =n  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  r8 | j   |  j | <n  d S)z>Replace the keyed message; raise KeyError if it doesn't exist.N)r   r#   rT   r   r-  r,  )r   r   r   r   r   r   r#     s    zBabyl.__setitem__c       
      C   st  |  j  |  \ } } |  j j |  |  j j   t j   } xF |  j j   } | d t k sg | rk Pn  | j | j t d   qA t j   } xB |  j j   } | t k s | r Pn  | j | j t d   q | |  j j	   } | d k s t
  |  j j |  } | j t d  } t | j   |  }	 |	 j | j    | |  j k rp|	 j |  j |  n  |	 S)z4Return a Message representation or raise a KeyError.s   *** EOOH ***s   
r   )r   r   rZ   rg   rU   rV   r\   r]   r[   r   r   rM   r   rf   set_visibler,  
set_labels)
r   r   r   r   original_headersrn   Zvisible_headersnZbodyr   r   r   r   r'     s0    zBabyl.get_messagec       	      C   s  |  j  |  \ } } |  j j |  |  j j   t j   } xF |  j j   } | d t k sg | rk Pn  | j | j t d   qA x) |  j j   } | t k s | r Pq q | j	   } | |  j j
   } | d k s t  |  j j |  } | j t d  } | | S)z3Return a string representation or raise a KeyError.s   *** EOOH ***s   
r   )r   r   rZ   rg   rU   rV   r\   r]   r[   rf   r   r   rM   )	r   r   r   r   r0  rn   Zheadersr1  rm   r   r   r   r.     s&    zBabyl.get_bytesc             C   s"   t  j |  j |  j d t   S)z6Return a file-like representation or raise a KeyError.s   
)rU   rV   r.   r[   r\   )r   r   r   r   r   r*     s    zBabyl.get_filec             C   sT   |  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,  r7   rC   difference_update_special_labelsr2   )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 r t |  t |  k  r | j | t t   n  | j |  d d   |  j  j   d d  j d  D } | j |  q, | d k s | d t k r/t |  t |  k  rP| j | t t   qPq, | s, | j | t t   Pq, q, 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 Sr   )strip)r  labelr   r   r   r  9  s   	 z'Babyl._generate_toc.<locals>.<listcomp>rP   N   ,s   rO   )r   rZ   rg   r   r\   r   r   r   r   r   r   r}   r,  r   r   )r   r   r   r  Zlabel_listsr  rn   r4  r   r   r   r   +  s4    	&zBabyl._generate_tocc             C   sm   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)rH   )r  r6  r   r   r   r  N  s    z*Babyl._pre_mailbox_hook.<locals>.<genexpr>s   Labels:r7  s   N)r\   r-  rx   r]   )r   r   Zbabylr4  r   r   r   r   I  s    

zBabyl._pre_mailbox_hookc             C   s   | j  d t  d S)z-Called before writing each message to file f.s   N)r]   r\   )r   r   r   r   r   r   S  s    zBabyl._pre_message_hookc             C   s   | j  t d  d S)z,Called after writing each message to file f.s   N)r]   r\   )r   r   r   r   r   r   W  s    zBabyl._post_message_hookc             C   s  |  j  j   } t | t  r g  } g  } x@ | j   D]2 } | |  j k r\ | j |  q7 | j |  q7 W|  j  j d  x( | D]  } |  j  j d | j    q W|  j  j d  x, | D]$ } |  j  j d | j   d  q W|  j  j t	  n |  j  j d t	  t | t
 j j  rt j   } t
 j j | d d  } | j |  | j d  xB | j   } |  j  j | j d	 t	   | d	 k s| rdPqdqd|  j  j d
 t	  t | t  rHt j   }	 t
 j j |	 d d  }
 |
 j | j    x |	 j   } |  j  j | j d	 t	   | d	 k s>| rPqqnR | j d  xB | j   } |  j  j | j d	 t	   | d	 k s| rXPqXqXxU| j d  } | sPn  |  j  j | j d	 t	   qnt | t t t j f  r+t | t j  r't j d t d  | j   } n  t | t  rH|  j |  } n  | 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	   q|  j  j d
 t	 t	  |  j  j | j d	 t	   nt  | d  rt  | d  rht j d t d  | j! } n  | j   } d } x | j   } | j" d  r| d d  d	 } n& | j" d  r| d d  d	 } n  |  j  j | j d	 t	   | d	 k s| r}| r4d } |  j  j d
 t	  | j |  q8Pq}q}x | j   } | sTPn  | j" d  rz| d d  t	 } nL | j" d  r| d d  t	 } n& | j" d	  r| d d  t	 } n  |  j  j |  q>n t# d t$ |    |  j  j   } | | f S)z0Write message contents and return (start, stop).   1s   , s   ,,    r7  s   1,,Fr   s   
s   *** EOOH ***i   z8Use of StringIO input is deprecated, use BytesIO insteadrL   s   

rO   rP   Nrg   rN   zDUse of text mode files is deprecated, use a binary mode file insteadTs   
s   zInvalid message type: %srS   rR   rS   rR   rS   rS   )%r   r   rT   r   r-  r3  r   r]   rH   r\   r,   r   r   rU   rV   rW   rX   rY   rZ   rg   r[   get_visiblerM   ra   r`   rb   rc   rd   re   rf   rK   r   r@   rN   r_   ri   rj   )r   r   r   Zspecial_labelsr4  r6  Zorig_bufferZorig_generatorrn   Z
vis_bufferZvis_generatorrN   Z
body_startZoriginal_posZ
first_passr   r   r   r   r   [  s    "
"	
&&)	
zBabyl._install_message)r%  r&  r'  r(  r)  r*  r+  )rp   rq   rr   rs   	frozensetr3  r   r   r   r#   r'   r.   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  rM |  j t j |   t  | t  r(| j |   q(n t  | t  ru |  j t j	 |   n t  | t
  r |  j t j |   n t  | t j  r |  j t j |   n` t | d  r |  j t j |   n8 | d k rt j j j |   n t d t |    d S)zInitialize a Message instance.rM   NzInvalid message type: %s)rT   r,   r   r   _become_messagecopydeepcopy_explain_tora   r-   r`   Zmessage_from_stringrU   TextIOWrapperZmessage_from_filer@   Zmessage_from_binary_filer   ri   rj   )r   r   r   r   r   r     s    zMessage.__init__c             C   sM   t  | d g   } x4 | j D]) } | | k r | j | |  j | <q q Wd 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 St d   d S)z:Copy format-specific state to message insofar as possible.Nz Cannot convert to specified type)rT   r   ri   )r   r   r   r   r   r?    s    zMessage._explain_to)rp   rq   rr   rs   r   r<  r?  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   s5   d |  _  d |  _ t j   |  _ t j |  |  d S)z%Initialize a MaildirMessage instance.rv   r   N)rD  rE  r   rF  r   r   )r   r   r   r   r   r     s    		zMaildirMessage.__init__c             C   s   |  j  S)zReturn 'new' or 'cur'.)rD  )r   r   r   r   r     s    zMaildirMessage.get_subdirc             C   s8   | d k s | d k r$ | |  _  n t d |   d S)zSet subdir to 'new' or 'cur'.rv   rw   z!subdir must be 'new' or 'cur': %sN)rD  rJ   )r   r   r   r   r   r     s    zMaildirMessage.set_subdirc             C   s+   |  j  j d  r# |  j  d d  Sd Sd S)z*Return as a string the flags that are set.z2,rO   Nr   )rE  rh   )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)rx   r   rE  )r   flagsr   r   r   	set_flags
  s    zMaildirMessage.set_flagsc             C   s0   |  j  d j t |  j    t |  B  d S)z.Set the given flag(s) without changing others.r   N)rI  rx   r  rG  )r   flagr   r   r   add_flag  s    zMaildirMessage.add_flagc             C   s?   |  j    r; |  j d j t |  j     t |    n  d S)z7Unset the given string flag(s) without changing others.r   N)rG  rI  rx   r  )r   rJ  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.)rF  )r   r   r   r   r     s    zMaildirMessage.get_datec             C   s<   y t  |  |  _ Wn" t k
 r7 t d |   Yn Xd S)z9Set delivery date of message, in seconds since the epoch.zcan't convert to float: %sN)floatrF  rJ   ri   )r   Zdater   r   r   r     s    zMaildirMessage.set_datec             C   s   |  j  S)z%Get the message's "info" as a string.)rE  )r   r   r   r   r   "  s    zMaildirMessage.get_infoc             C   s5   t  | t  r | |  _ n t d t |    d S)z Set the message's "info" string.zinfo must be a string: %sN)rT   r`   rE  ri   rj   )r   infor   r   r   r   &  s    zMaildirMessage.set_infoc             C   sX  t  | t  rK | j |  j    | j |  j    | j |  j    n	t  | t  r t	 |  j    } d | k r | j
 d  n  |  j   d k r | j
 d  n  d | k r | j
 d  n  d | k r | j
 d  n  d | k r | j
 d  n  | j d	 t j |  j     n4t  | t  rt	 |  j    } d | k r]| j d
  n  d | k ry| j d  n  d | k rT| j d  qTn t  | t  r,t	 |  j    } d | k r| j d
  n  d | k r| j d  n  d | k r| j d  n  d | k rT| j d  qTn( t  | t  r>n t d t |    d S)z;Copy Maildir-specific state to message insofar as possible.SRrw   OTDFAzMAILER-DAEMONr%  repliedflaggedr&  r(  Pr)  z$Cannot convert to specified type: %sN)rT   r	   rI  rG  r   r   r   r   r   r  rK  r   r   r   r   r	  r   	add_labelr   ri   rj   )r   r   rH  r   r   r   r?  -  sN    "zMaildirMessage._explain_to)rp   rq   rr   rs   rA  r   r   r   rG  rI  rK  rL  r   r   r   r   r?  r   r   r   r   r	     s   c               @   s   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   s}   |  j  d d  t | t j j  ri | j   } | d k	 ri | j d  ri |  j  | d d   qi n  t j |  |  d S)z'Initialize an mboxMMDFMessage instance.zMAILER-DAEMONTNzFrom rQ   )r   rT   r,   r   r   r   rh   r   )r   r   r   r   r   r   r   ^  s    z_mboxMMDFMessage.__init__c             C   s   |  j  S)z Return contents of "From " line.)rZ  )r   r   r   r   r   g  s    z_mboxMMDFMessage.get_fromc             C   sN   | d k	 rA | d k r' t  j   } n  | d t  j |  7} n  | |  _ d S)z>Set "From " line, formatting and appending time_ if specified.NT )r   r   r   rZ  )r   r   Ztime_r   r   r   r   k  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   rG  s  s    z_mboxMMDFMessage.get_flagsc             C   s  t  |  } d
 \ } } x4 d D], } | | k r | | 7} | j |  q q Wx4 d D], } | | k rV | | 7} | j |  qV qV W| d j t |   7} y |  j d |  Wn" t k
 r |  j d |  Yn Xy |  j d |  Wn" t k
 r|  j d |  Yn Xd	 S)z)Set the given flags and unset all others.r   rP  rQ  rS  rT  rU  r\  zX-StatusN)r   r   )rP  rQ  )rS  rT  rU  )r  r   rx   r   replace_headerr!   Z
add_header)r   rH  Zstatus_flagsZxstatus_flagsrJ  r   r   r   rI  w  s&    

z_mboxMMDFMessage.set_flagsc             C   s0   |  j  d j t |  j    t |  B  d S)z.Set the given flag(s) without changing others.r   N)rI  rx   r  rG  )r   rJ  r   r   r   rK    s    z_mboxMMDFMessage.add_flagc             C   sK   d |  k s d |  k rG |  j  d j t |  j    t |    n  d S)z7Unset the given string flag(s) without changing others.r\  zX-Statusr   N)rI  rx   r  rG  )r   rJ  r   r   r   rL    s    z_mboxMMDFMessage.remove_flagc             C   s  t  | t  r$t |  j    } d | k r= | j d  n  d | k rY | j d  n  d | k ru | j d  n  d | k r | j d  n  d | k r | j d  n  | d	 =| d
 =d j |  j   j   d d   } y& | j	 t
 j t j | d    Wqt t f k
 r YqXnlt  | t  r\| j |  j    | j |  j    n4t  | t  rt |  j    } d | k r| j d  n  d | k r| j d  n  d | k r| j d  n  | d	 =| d
 =n t  | t  rht |  j    } d | k r| j d  n  d | k r;| j d  n  d | k rW| j d  n  | d	 =| d
 =n( t  | t  rzn t d t |    d S)zACopy mbox- or MMDF-specific state to message insofar as possible.rQ  rw   rT  rU  rP  rO  rS  rR  Zstatuszx-statusr[  rQ   Nz%a %b %d %H:%M:%S %Yr%  rV  rW  r&  r(  z$Cannot convert to specified type: %s)rT   r	   r  rG  r   rK  rx   r   r   r   calendarZtimegmr   ZstrptimerJ   OverflowErrorr   rI  r   r   r	  r   rY  r   ri   rj   )r   r   rH  Z
maybe_dater   r   r   r?    s^    %

z_mboxMMDFMessage._explain_to)rp   rq   rr   rs   rA  r   r   r   rG  rI  rK  rL  r?  r   r   r   r   r   Y  s   		r   c               @   s   e  Z d  Z d Z d S)r
   z&Message with mbox-specific properties.N)rp   rq   rr   rs   r   r   r   r   r
     s   c               @   sj   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)ra  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)ra  )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)r2   ra  )r   r  r   r   r   r    s    zMHMessage.set_sequencesc             C   sN   t  | t  r4 | |  j k rJ |  j j |  qJ n t d t |    d S)z8Add sequence to list of sequences including the message.zsequence type must be str: %sN)rT   r`   ra  r   ri   rj   )r   r$  r   r   r   r	    s    zMHMessage.add_sequencec             C   s-   y |  j  j |  Wn t k
 r( Yn Xd S)zARemove sequence from the list of sequences including the message.N)ra  r   rJ   )r   r$  r   r   r   remove_sequence  s    zMHMessage.remove_sequencec             C   s  t  | t  r t |  j    } d | k r= | j d  n | j d  | j d  d | k rs | j d  n  d | k r| j d  qn?t  | t  rt |  j    } d | k r | j d  n | j d	  d | k r | j d  n  d | k r| j d
  qn t  | t  rMx |  j   D] } | j |  q3Wn t  | t	  rt |  j    } d | k r| j
 d  n  d | k r| j
 d  qn( t  | t  rn t d t |    d S)z6Copy MH-specific state to message insofar as possible.r%  rw   rO  rW  rT  rV  rP  ROrQ  rU  r(  z$Cannot convert to specified type: %sN)rT   r	   r  r  r   rK  r   r   r	  r   rY  r   ri   rj   )r   r   r  r$  r   r   r   r?    s@    zMHMessage._explain_to)rp   rq   rr   rs   rA  r   r  r  r	  rb  r?  r   r   r   r   r     s   	c               @   s   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 an BabylMessage instance.N)r,  r   rd  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)r2   r,  )r   r4  r   r   r   r/  %  s    zBabylMessage.set_labelsc             C   sN   t  | t  r4 | |  j k rJ |  j j |  qJ n t d t |    d S)z+Add label to list of labels on the message.zlabel must be a string: %sN)rT   r`   r,  r   ri   rj   )r   r6  r   r   r   rY  )  s    zBabylMessage.add_labelc             C   s-   y |  j  j |  Wn t k
 r( Yn Xd S)z4Remove label from the list of labels on the message.N)r,  r   rJ   )r   r6  r   r   r   remove_label1  s    zBabylMessage.remove_labelc             C   s   t  |  j  S)z3Return a Message representation of visible headers.)r   rd  )r   r   r   r   r:  8  s    zBabylMessage.get_visiblec             C   s   t  |  |  _ d S)z2Set the Message representation of visible headers.N)r   rd  )r   Zvisibler   r   r   r.  <  s    zBabylMessage.set_visiblec             C   s   xG |  j  j   D]6 } | |  k r< |  j  j | |  |  q |  j  | =q Wx= d D]5 } | |  k rQ | |  j  k rQ |  | |  j  | <qQ qQ Wd S)	z9Update and/or sensibly generate a set of visible headers.DateFromReply-ToToCCSubjectN)rf  rg  rh  ri  rj  rk  )rd  r3   r]  )r   headerr   r   r   update_visible@  s    zBabylMessage.update_visiblec             C   s  t  | t  r t |  j    } d | k r= | j d  n | j d  | j d  d | k so d | k r | j d  n  d | k r | j d  n  d	 | k r| j d
  qnRt  | t  r?t |  j    } d | k r | j d  n | j d  d	 | k r | j d  n  d | k r| j d  qn t  | t  rt |  j    } d | k r|| j d  n  d | k r| j d  qnq t  | t	  r| j
 |  j    xL |  j   D] } | j |  qWn( t  | t  rn t d t |    d S)z9Copy Babyl-specific state to message insofar as possible.r%  rw   rO  r)  r+  rX  r(  rP  r&  rR  rc  rQ  rS  rU  rV  z$Cannot convert to specified type: %sN)rT   r	   r  r-  r   rK  r   r   r	  r   r.  r:  rY  r   ri   rj   )r   r   r4  r6  r   r   r   r?  K  sF    zBabylMessage._explain_to)rp   rq   rr   rs   rA  r   r-  r/  rY  re  r:  r.  rm  r?  r   r   r   r   r     s   c               @   s   e  Z d  Z d Z d S)r   z&Message with MMDF-specific properties.N)rp   rq   rr   rs   r   r   r   r   r   u  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   s4   | |  _  | 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   rM   )r   sizer   r   r   rM     s    z_ProxyFile.readc             C   s   |  j  | |  j j  S)zRead bytes.)rp  r   read1)r   rq  r   r   r   rr    s    z_ProxyFile.read1c             C   s   |  j  | |  j j  S)zRead a line.)rp  r   rg   )r   rq  r   r   r   rg     s    z_ProxyFile.readlinec             C   sW   g  } xJ |  D]B } | j  |  | d k	 r | t |  8} | d k rO PqO q q W| S)zRead multiple lines.Nr   )r   r   )r   sizehintr=   rn   r   r   r   	readlines  s    z_ProxyFile.readlinesc             c   s*   x# |  j    } | s t  n  | Vq d S)zIterate over lines.N)rg   r   )r   rn   r   r   r   r6     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   sK   | d k r" |  j  j |  j  n  |  j  j | |  |  j  j   |  _ d S)zChange position.rP   N)r   rZ   rn  r   )r   offsetwhencer   r   r   rZ     s    z_ProxyFile.seekc             C   s>   t  |  d  r: t  |  j d  r1 |  j j   n  |  ` n  d S)zClose the file.r   rG   N)r@   r   rG   )r   r   r   r   rG     s    z_ProxyFile.closec             C   sJ   | d k r d } n  |  j  j |  j  | |  } |  j  j   |  _ | S)z"Read size bytes using read_method.NrP   rS   )r   rZ   rn  r   )r   rq  read_methodr=   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   |  j    d  S)N)rG   )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   rD   )r   r   r   r   rD     s    z_ProxyFile.flushc             C   s3   t  |  d  s d St  |  j d  s) d S|  j j S)Nr   Tr  F)r@   r   r  )r   r   r   r   r    s
    z_ProxyFile.closed)rp   rq   rr   rs   r   rM   rr  rg   rt  r6   r   rZ   rG   rp  rx  rz  r{  r|  r}  rD   propertyr  r   r   r   r   r   y  s$   	r   c               @   s[   e  Z d  Z d Z d 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   sY   | d k r! |  j  |  _ d } n! | d k rB |  j |  _ d } n  t j |  | |  d S)z8Change position, possibly with respect to start or stop.r   rP   rO   N)r  rn  r  r   rZ   )r   ru  rv  r   r   r   rZ     s    		z_PartialFile.seekc             C   s`   |  j  |  j } | d k r  d S| d k sD | d k  sD | | k rM | } n  t j |  | |  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 |  ` n  d  S)Nr   )r@   r   )r   r   r   r   rG     s    z_PartialFile.close)	rp   rq   rr   rs   r   r   rZ   rp  rG   r   r   r   r   r     s   
	r   Tc          -   C   s  d } yt  r y t  j |  t  j t  j B Wq t k
 r } z? | j t j t j t j f k ry t	 d |  j
   n   WYd d } ~ Xq Xn  | ry! t |  j
 d  } | j   WnG t k
 r} z' | j t j t j f k r d S  WYd d } ~ Xn Xyf t t d  rHt j | j
 |  j
 d  d } t j | j
  n  t j | j
 |  j
 d  d } Wqt k
 rt j | j
  t	 d |  j
   YqXn  WnD t  rt  j |  t  j  n  | rt j |  j
 d  n    Yn Xd S)z(Lock file f using lockf and dot locking.Fzlockf: lock unavailable: %sNz.lockr   Tzdot lock unavailable: %s)fcntllockfZLOCK_EXZLOCK_NBr   r   ZEAGAINr   r   r   r   r   rG   r@   r   r   r   r   r   r   LOCK_UN)r   r   Zdotlock_doner   Zpre_lockr   r   r   r     sF    !
r   c             C   sP   t  r t  j |  t  j  n  t j j |  j d  rL t j |  j d  n  d S)z*Unlock file f using lockf and dot locking.z.lockN)r  r  r  r   r   rz   r   r   )r   r   r   r   r   *  s    r   c             C   sL   t  j |  t  j t  j Bt  j Bd  } z t |  d  SWd t  j |  Xd S)zCCreate a file if it doesn't exist and open for reading and writing.i  zrb+N)r   r   r   r  O_RDWRrG   )r   fdr   r   r   r   1  s    &r   c             C   s2   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   9  s    	r   c             C   s3   |  j    t t d  r/ t j |  j    n  d S)z0Ensure changes to file f are physically on disk.fsyncN)rD   r@   r   r  fileno)r   r   r   r   r   ?  s    
r   c             C   s   t  |   |  j   d S)z:Close file f, ensuring all changes are physically on disk.N)r   rG   )r   r   r   r   r   E  s    
r   c               @   s   e  Z d  Z d Z d S)Errorz"Raised for module-specific errors.N)rp   rq   rr   rs   r   r   r   r   r  K  s   r  c               @   s   e  Z d  Z d Z d S)r|   z:The specified mailbox does not exist and won't be created.N)rp   rq   rr   rs   r   r   r   r   r|   N  s   r|   c               @   s   e  Z d  Z d Z d S)r   z>The specified mailbox is not empty and deletion was requested.N)rp   rq   rr   rs   r   r   r   r   r   Q  s   r   c               @   s   e  Z d  Z d Z d S)r   z)Another process caused an action to fail.N)rp   rq   rr   rs   r   r   r   r   r   T  s   r   c               @   s   e  Z d  Z d Z d S)r  z)A file appears to have an invalid format.N)rp   rq   rr   rs   r   r   r   r   r  W  s   r  )0rs   r   r   r_  r   r   r=  rc   r,   Zemail.messageZemail.generatorrU   r(   r  ImportError__all__r\   rH   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>   sd    6B4- 1%mqH_a')