
    e2                         d dl Z d dlZd dlZd dlZd dlmZ d dlmZmZm	Z	 d dlm
Z
 d dlmZ ddlmZ d dlmZ d	Zd
Z G d de      Zy)    N)exc_info)imaputilimaplibutilOfflineImapError)globals)
MonthNames   )
BaseFolder)NoBoundaryInMultipartDefectz
MSGCOPY_c                        e Zd Zd$ fd	Zd%dZd Zd Zd Zd Zd Z	d Z
d	 Zd&d
Zd Zd&dZd Zd Zd Zd Zd'dZd Zd Zd'dZd Zd(dZd Zd Zd Zd Zd Zd Zd Zd Z d Z!d  Z"d! Z#d" Z$d# Z% xZ&S ))
IMAPFolderc                 N   t        j                  |      }|r+|j                  j                  rt        j                  |      }|j
                  | _        t        t        | '  ||       |j                         r$t        j                  | j                        | _        d| _        |j                         | _        d | _        || _        t%        j&                         | _        dg| _        | j,                  j/                  dd      | _        | j,                  j                  j3                  dd      }t5        j6                  d|      D cg c]  }|s|	 c}| _        |j;                  | j=                               | _        | j,                  jA                         rd| _        y y c c}w )	NFzBODY.PEEK[]
retrycount   filterheaders z\s*,\s*T)!r   dequoteaccountutf_8_support	IMAP_utf8delimsepsuperr   __init__getdecodefoldernamesdecode_mailbox_namevisiblename	idle_mode
getexpungeexpungeroot
imapserverrandomRandomrandomgenerator
imap_query
repository
getconfintr   getconfresplitr   get_copy_ignore_UIDsgetvisiblenamecopy_ignoreUIDsgetidlefolders)selfr#   namer(   decodefh_confh	__class__s          2/usr/share/offlineimap3/offlineimap/folder/IMAP.pyr   zIMAPFolder.__init__#   sN    %j((66%%d+D##j$(z:**,';;D<L<LMD!,,.	$%}}(/ //44\1E//))11/2F)+*g)FLA!aL  *>>! #??))+!DN , Ms   F"F"c                     	 |j                  | j                         |       y# |j                  $ r% |j                  | j                         d|       Y yw xY w)a  Select this folder when we do not need write access.

        Prefer SELECT to EXAMINE if we can, since some servers
        (Courier) do not stabilize UID validity until the folder is
        selected.
        .. todo: Still valid? Needs verification
        :param: Enforce new SELECT even if we are on that folder already.
        :returns: raises :exc:`OfflineImapError` severity FOLDER on error)forceT)readonlyr9   N)selectgetfullIMAPnamer:   )r1   imapobjr9   s      r7   
__selectrozIMAPFolder.__selectroF   sS    	ONN4//1N? 	ONN4//1DNN	Os   !$ 1AAc                     | j                         }| j                  j                  j                  rt	        j
                  |      }t	        j                  |      S N)getfullnamer(   r   r   r   	utf8_IMAPfoldername_to_imapname)r1   r2   s     r7   r<   zIMAPFolder.getfullIMAPnameT   sD    !??""00%%d+D..t44    c                     d}| j                   du rd}| j                  j                  d| j                  j	                         z  d|      }|du ryt
        j                  j                   S )NFTzRepository %ssinglethreadperfolder)r   configgetdefaultbooleanr(   getnamer   optionssinglethreading)r1   singlethreadperfolder_default	onethreads      r7   suggeststhreadszIMAPFolder.suggeststhreads[   sj    (-%>>T!,0)KK11doo5577#%BD	 ??2222rD   c                 8    | j                   j                          y r@   )r#   connectionwaitr1   s    r7   waitforthreadzIMAPFolder.waitforthreadh   s    &&(rD   c                     | j                   j                  d| j                  z  dd       r0t        dt        j                  j
                  t               d         y )Nz
Account %smaxagez)maxage is not supported on IMAP-IMAP syncr   )rG   
getdefaultaccountnamer   ERRORREPOr   rQ   s    r7   	getmaxagezIMAPFolder.getmaxagek   sX    ;;!!,"&"2"2#34<dD"; &&++
1 DrD   c                 D    t         | j                  j                         z   S r@   )MSGCOPY_NAMESPACEr(   rI   rQ   s    r7   getinstancelimitnamespacez$IMAPFolder.getinstancelimitnamespacet   s     4??#:#:#<<<rD   c                    t        | d      r| j                  S | j                  j                         }	 | j	                  |       |j                  d      \  }}|dgk7  r|J d       t        |d         | _        | j                  | j                  j                  |       S # | j                  j                  |       w xY w)zRetrieve the current connections UIDVALIDITY value

        UIDVALIDITY value will be cached on the first call.
        :returns: The UIDVALIDITY as (long) number._uidvalidityUIDVALIDITYNz(response('UIDVALIDITY') returned [None]!)hasattrr^   r#   acquireconnection_IMAPFolder__selectroresponseintreleaseconnection)r1   r=   typuidvals       r7   get_uidvalidityzIMAPFolder.get_uidvalidityx   s     4($$$//335		7OOG$!**=9KCdV#(: ;:;: #F2JD$$OO--g6DOO--g6s   AB" "B?c                 4   d}d }|r_d}| j                   j                         }	 |j                  | j                         dd      \  }}| j                   j	                  |       |r_|d gk(  ryd}|D ]  }t        t        |      |      } ||j                         k7  ryy# t
        $ rQ}| j                   j	                  |d       |j                  t
        j                  j                  k(  rd}n Y d }~d }~w | j                   j	                  |d        xY w)NTFr   )r#   rb   r;   r<   rf   r   severityrW   FOLDER_RETRYmaxre   getmessagecount)	r1   statusfolderretryimapdatar=   restypeemaxmsgidmsgids	            r7   quickchangedzIMAPFolder.quickchanged   s    Eoo779G$+NN43G3G3I437%9!11': . v 	1E3u:x0H	1 |3355/ $ 11'4@::!1!7!7!D!DD E 11'4@s   ?B   	D)AC55"Dc                      fd} j                         }j                  |dd      \  }}|dgk(  s|d   dk(  ry|D cg c]  }|j                  d       }}g }	||	j                  d|z         n)|'|	j                  d|d	   t        |d
      |d   fz          j                         }
|
|	j                  d|
z         t        |	      d
k\  r1ddj                  |	      z   |      }t        j                  |      S yc c}w )aX  Determines sequence numbers of messages to be fetched.

        Message sequence numbers (MSNs) are more easily compacted
        into ranges which makes transactions slightly faster.

        Arguments:
        - imapobj: instance of IMAPlib
        - min_date (optional): a time_struct; only fetch messages newer
          than this
        - min_uid (optional): only fetch messages with UID >= min_uid

        This function should be called with at MOST one of min_date OR
        min_uid set but not BOTH.

        Returns: range(s) for messages or None if no messages
        are to be fetched.c                    	 j                  d|       \  }}|dk7  rDdj                         ddd|d|d}t        |t        j                  j                        	 	 |D cg c]  }|j                  d
       }}t        |      dkD  r"d|d   v s|d   dk(  r|d   j                         }d|v r,j                  j                  d       |j                  d       |S # t
        $ rN}dj                         ddd	t        |      }t        |t        j                  j                        d}~ww xY wc c}w )zActually request the server with the specified conditions.

            Returns: range(s) for messages or None if no messages
            are to be fetched.NOKzSEARCH in folder []z failed. Search string was 'z'. Server responded '[] 'z
'. Error: utf-8r    r   z%server returned UID with 0; ignoring.)searchgetrepositoryr   rW   FOLDER	Exceptionstrr3   lenr,   uiwarnremove)	search_conditionsres_typeres_datamsgrs   xr=   search_condr1   s	         r7   r   z)IMAPFolder._msgs_to_fetch.<locals>.search   s<   
K%,^^D:K%L"(t#  --/{#X	/C
 +30@0F0F0M0MNN $ 4<<a)<H< 8}q cXa[&8HQK2<M#A;,,.H}DE"O9  K ))+T;AH 's,<,B,B,I,IJJ	K$ =s   AC# 'D=#	D:,A	D55D:TNr      0r}   zUID %d:*zSINCE %02d-%s-%dr   r	   z
SMALLER %d(%s)r~   z1:*)
r<   r;   r3   appendr   
getmaxsizer   joinr   uid_sequence)r1   r=   min_datemin_uidr   ar   rq   r   
conditionsmaxsizesearch_resultr   s   ``          @r7   _msgs_to_fetchzIMAPFolder._msgs_to_fetch   s+   $*	X   "$^^AtT:(v!!4
 088!AHHW%88
j723!0Z4hqk4C C D //#lW45z?a 388J#77K";/M((77 / 9s   Dc                     |t               ddS )Nr   )uidflagstime)setr1   r   s     r7   msglist_item_initializerz#IMAPFolder.msglist_item_initializer  s    SUA66rD   c           	          | j                   j                  | j                  |        | j                          | j                  j                         }	 | j                  |||      }|s	 | j                  j                  |       y d|z  }| j                   j                  dd|dd       |j                  |d      \  }}|dk7  rAd| j                         d	| d
|d|d	}t        |t        j                  j                        	 | j                  j                  |       |D ]  }	|	|	j                  d      j                  dd      d   }	t!        j"                  |	      }
d|
vr*| j                   j%                  dt'        |
      z  d       nt)        |
d         }| j+                  |      | j,                  |<   t!        j.                  |
d         }t!        j0                  |
d         }t3        j4                  |	j7                  d            }||||d| j,                  |<    | j                   j9                  | j                  | | j;                                y # | j                  j                  |       w xY w)N)r   r   z%simapz calling imaplib2 fetch command: r~   z(FLAGS UID INTERNALDATE)ry   zFETCHING UIDs in folder [rz   z failed. Server responded '[r{   r|   r}   r	   UIDz!No UID in message with options %s)minorFLAGS)r   r   r   keywords)r   loadmessagelistr(   dropmessagelistcacher#   rb   r   rf   debugfetchr   r   rW   r   r3   r,   r   
flags2hashr   r   re   r   messagelistflagsimap2maildirflagsimap2keywordsr   Internaldate2epochencodemessagelistloadedrn   )r1   r   r   r=   msgsToFetch	fetch_msgr   rd   r   
messagestrrJ   r   r   r   rtimes                  r7   cachemessagelistzIMAPFolder.cachemessagelist  sW   6!!#//335	7--(G . =K OO--g6 {*IGGMM&$&@#B C!(5"7Hh4 ))+T8XG 's,<,B,B,I,IJJ	   OO--g6" 	?J !#**7399#qA!DJ))*5GG#@ \*12  4 '%.)(,(E(Ec(J  % 22773CD#66ww7GH#66%%g.00327165=)?  %#	?* 	!!$//49M9M9OP/ OO--g6s   I  BI   I=c                 L   | j                  t        |      | j                        }|d   }| j                  j	                  d      r^|j                  | j                  d         }t        |      dkD  r|dd d|d	d }n|}| j                  j                  dd
||fz         |S )a;  Retrieve message with UID from the IMAP server (incl body).

        After this function all CRLFs will be transformed to '
'.

        :returns: the message body or throws and OfflineImapError
                  (probably severity MESSAGE) if e.g. no message with
                  this UID could be found.
        r	   r   8bit-RFCpolicy   N   ...z&Returned object from fetching %d: '%s')	_fetch_from_imapr   r   r   is_debugging	as_stringr   r   r   )r1   r   datar   msg_s
dbg_outputs         r7   
getmessagezIMAPFolder.getmessageM  s     $$SXt?
 1g77'MMZ)@MAE5zC*/+uST{C
"
GGMM&"J
+#, - 
rD   c                 &    | j                   |   d   S )Nr   r   r   s     r7   getmessagetimezIMAPFolder.getmessagetimel  s    $V,,rD   c                 &    | j                   |   d   S )Nr   r   r   s     r7   getmessageflagszIMAPFolder.getmessageflagsp  s    $W--rD   c                 &    | j                   |   d   S )Nr   r   r   s     r7   getmessagekeywordszIMAPFolder.getmessagekeywordst  s    $Z00rD   c                     d}|| j                   d   }n|}dj                  t        j                  |j	                  |            dz  | j
                  j                  dd            }||fS )a  Returns a unique X-OfflineIMAP header

         Generate an 'X-OfflineIMAP' mail header which contains a random
         unique value (which is based on the mail content, and a random
         number). This header allows us to fetch a mail after APPENDing
         it to an IMAP server and thus find out the UID that the server
         assigned it.

        :returns: (headername, headervalue) tuple, consisting of strings
                  headername == 'X-OfflineIMAP' and headervalue will be a
                  random string
        zX-OfflineIMAPr   z{}-{}r   l    r   l   c(	 )r   formatbinasciicrc32as_bytesr&   randint)r1   r   r   
headernameoutput_policyheadervalues         r7   __generate_randomheaderz"IMAPFolder.__generate_randomheaderw  sp     %
> KK
3M"M nn>>#,,m,<=
J



&
&q*
57 ;&&rD   c                    | j                   j                  dd|d|       |j                  |      }	 |j                  dd||      d   d   }|j	                  d      }| j                   j                  ddt        |      z          |dk(  r | j                   j                  dd|z         y|j                  d      }| j                   j                  ddt        |      z          t        |      dk7  s|d   3t        d|dt        |      t        j                  j                        t        |d         S # |j
                  $ r,}| j                   j                  dd	|d
|       Y d }~yd }~ww xY w)Nr   z)__savemessage_searchforheader called for : r   HEADERr	   r   r}   z/__savemessage_searchforheader: got IMAP error 'z9' while attempting to UID SEARCH for message with header z8__savemessage_searchforheader got initial matchinguids: r   zW__savemessage_searchforheader: UID SEARCH for message with header %s yielded no resultsr~   z0__savemessage_searchforheader: matchinguids now z5While attempting to find UID for message with header z", got wrong-sized matchinguids of )r   r   _quoter   r3   errorreprr,   r   r   r   rW   MESSAGEre   )r1   r=   r   r   matchinguidserrs         r7   __savemessage_searchforheaderz(IMAPFolder.__savemessage_searchforheader  s   f!;0	1 nn[1	";;x'1;@@ACCDFL (..w7L 	f')-l);<	= 2GGMM&J$%& #))#.fP\*+ 	,|!\!_%<" S.0 !&&..	  <?##9 }} 	GGMM& *-j:; 	s   +D: :E5	"E00E5c                    | j                   j                  dd|d|       | j                         r+dt        | j                         j	                               z   }nd}|j                  dd|z  d      }|d   d	k7  r;d
dj                  |d         z  }t        |t        j                  j                        |d   }d}|D ]  }|gt        |      t        k(  rU|D 	cg c]  }	|	j                  d       }}	t        j                  d|d|d|d   t        j                        sg|d   }m|pt!        |t"              r|j                  d      }t        j                  d|t        j                        }
|
rt%        |
j'                  d            c S t        j                  d|t        j                        }
|
rt%        |
j'                  d            c S | j                   j)                  d|z         | j                   j                  ddt+        |      z         a| j                   j)                  dt+        |      z          yc c}	w )ag   We fetch all new mail headers and search for the right
        X-OfflineImap line by hand. The response from the server has form:
        (
          'OK',
          [
            (
              '185 (RFC822.HEADER {1789}',
              '... mail headers ...'
            ),
            ' UID 2444)',
            (
              '186 (RFC822.HEADER {1789}',
              '... 2nd mail headers ...'
            ),
            ' UID 2445)'
          ]
        )
        We need to locate the UID just after mail headers containing our
        X-OfflineIMAP line.

        Returns UID when found, 0 when not found.r   z&__savemessage_fetchheaders called for r   r	   FETCHz%d:*zrfc822.headerr   ry   zError fetching mail headers: %s. Nr}   z(?:^|\r|\n)z:\s*z	(?:\r|\n))r   zUID\s+(\d+)z\d+\s+\(UID\s+(\d+)z0Can't parse FETCH response, can't find UID in %szGot: %sz1Can't parse FETCH response, we awaited string: %s)r   r   getmessagelistrm   keysr   r   r   rW   r   typetupler3   r+   r   
IGNORECASE
isinstancebytesre   groupr   r   )r1   r=   r   r   startresultr   founditemr   r   s              r7   __savemessage_fetchheadersz%IMAPFolder.__savemessage_fetchheaders  s   . 	f!;0 	1  D//166899E EWfunoF!93diiq	6JJC"3(8(>(>(F(FGG   !	GD}du!4378a)88 99(+7!!WBMM; !GE"dE*;;w/D))M4r}}MC"399Q<00 !ii(=u.0mm=#&syy|#44 &<>B&C Dfi$v,.FGGGLL "9;?:"F GA!	GF A 9s   Ic                    || j                  |      }|yt        j                  |      }	 |d   dk  rt        t        j                  t        j                  |            }|dd |dd k7  rt        	 ddd	d
ddddddddd}|j                  dk(  rt        j                   }nt        j                   }t        |dz  d      \  }}d|j                  ||j                     |j                  |j                  |j                   |j"                  ||fz  }	|	S # t        t
        f$ r" | j                  j                  dd|z         Y yw xY w)ak  Parses mail and returns an INTERNALDATE string

        It will use information in the following order, falling back as an
        attempt fails:
          - rtime parameter
          - Date header of email

        We return None, if we couldn't find a valid date. In this case
        the IMAP server will use the server local time when appening
        (per RFC).

        Note, that imaplib's Time2Internaldate is inherently broken as
        it returns localized date strings which are invalid for IMAP
        servers. However, that function is called for *every* append()
        internally. So we need to either pass in `None` or the correct
        string (in which case Time2Internaldate() will do nothing) to
        append(). The output of this function is designed to work as
        input to the imapobj.append() function.

        TODO: We should probably be returning a bytearray rather than a
        string here, because the IMAP server will expect plain
        ASCII. However, imaplib.Time2INternaldate currently returns a
        string so we go with the same for now.

        :param rtime: epoch timestamp to be used rather than analyzing
                  the email.
        :returns: string in the form of "DD-Mmm-YYYY HH:MM:SS +HHMM"
                  (including double quotes) or `None` in case of failure
                  (which is fine as value for append).Nr   i  r   r   z9Message with invalid date %s. Server will use local time.JanFebMarAprMayJunJulAugSepOctNovDec)r	   r                     	   
         r	   <   z'"%02d-%s-%04d %02d:%02d:%02d %+03d%02d")get_message_dater   	localtime
ValueErrormktimeOverflowErrorr   r   tm_isdstaltzonetimezonedivmodtm_mdaytm_montm_yeartm_hourtm_mintm_sec)
r1   r   r   	datetupledatetuple_checknum2monzoneoffset_hoffset_minternaldates
             r7   __getmessageinternaldatez#IMAPFolder.__getmessageinternaldate  sp   > =))#.E}NN5)		|d"   #nnT[[-CDO!} 33   4 %%%%U4 "LL=DMM>D#DBJ3(@!))793C3C+D!))9+<+<!(()*:*: (,, = M* 	
 GGMM& #@BK#L M	s   AD .EEc                    | j                   j                  d|||        |dkD  r%| j                  |      r| j                  ||       |S | j	                  || j
                         | j                  d   }| j                  ||      }| j                  |d      }|sd}d}| j                  j                         }		 |rd|	j                  v }
|
sI| j                  |      \  }}| j                   j                  dd|d	|       | j                  |||       | j                   j                  d      rS|j!                  |
      }t#        |      dkD  r|dd d|dd }n|}| j                   j                  dd|d|d       	 |	j%                  | j'                                	 |	j/                  | j'                         t1        j2                  |      ||j5                  |
            \  }}|dk7  rDd|d| d| j7                         d|d|d}t9        |t8        j:                  j<                        d}|r|	jI                         \  }}|dk(  sJ 
r|	jK                  d      }|dgk(  s|G| j                   jM                  d tA        |      z         	 |	r| j                  j-                  |	       yy	 |D cg c]  }|jO                  d!       }}tQ        |d"   jS                  d      d         }|dk(  r| j                   jM                  d$tA        |      z         nt	 | jY                  |	      }|dk(  r[| j                   j                  dd%       | j[                  |	||      }| j                   jM                  d&| j]                         z         |	r| j                  j-                  |	       	 |r0| j_                  |      | j`                  |<   || j`                  |   d(<   | j                   j                  dd)|z         |S # |	j(                  $ r? | j                   j+                  | |       |cY |	r| j                  j-                  |	       S S w xY w# |	j>                  $ r}|dz  }| j                  j-                  |	d       | j                  j                         }	|sTt9        d|d| d| j7                         dtA        |      d	t8        j:                  jB                  tE               d         | j                   jG                  |tE               d          Y d}~d}~w|	jF                  $ rw}| j                  j-                  |	d       d}	t9        d|d| d| j7                         dtA        |      d	t8        j:                  jB                  tE               d         d}~ww xY wc c}w # tT        $ r d}Y tV        $ r1 t9        d#tA        |      z  t8        j:                  jB                        w xY w# tV        $ r4 | j                   jM                  | j]                         d'd	d        w xY w# |	r| j                  j-                  |	       w w xY w)*ah  Save the message on the Server

        This backend always assigns a new uid, so the uid arg is ignored.

        This function will update the self.messagelist dict to contain
        the new message after sucessfully saving it.

        See folder/Base for details. Note that savemessage() does not
        check against dryrun settings, so you need to ensure that
        savemessage is never called in a dryrun mode.

        :param uid: Message UID
        :param msg: Message Object
        :param flags: Message flags
        :param rtime: A timestamp to be used as the mail date
        :returns: the UID of the new message as assigned by the server. If the
                  message is saved, but it's UID can not be found, it will
                  return 0. If the message can't be written (folder is
                  read-only for example) it will return -1.r   r   r   
message-idz[unknown message-id]r   UIDPLUSzsavemessage: header is: r   r   r   Nr   r   r   zsavemessage: date: z, content: 'r|   ry   zSaving msg (z) in folder 'z', repository 'z$' failed (abort). Server responded: r~   
r	   Tz
) folder 'z	', repo 'z#'failed (error). Server responded: 	APPENDUIDzJServer supports UIDPLUS but got no APPENDUID appending a message. Got: %s.r}   r`   zUnexpected response: %sz_savemessage: Server supports UIDPLUS, but we got no usable UID back. APPENDUID reponse was '%s'zHsavemessage: attempt to get new UID UID failed. Search headers manually.zZsavemessage: Searching mails for new Message-ID failed. Could not determine new UID on %s.zT: could not determine the UID while we got no error while appending the email with 'r   z!savemessage: returning new UID %d)1r   savemessage	uidexistssavemessageflagsdeletemessageheadersr   r   #_IMAPFolder__getmessageinternaldategetmessageheaderr#   rb   capabilities"_IMAPFolder__generate_randomheaderr   addmessageheaderr   r   r   r;   r<   r:   msgtoreadonlyrf   r   r   flagsmaildir2imapr   r   r   rW   rX   abortr   r   r   r   check_get_untagged_responser   r3   re   r,   r  r   (_IMAPFolder__savemessage_searchforheader%_IMAPFolder__savemessage_fetchheadersrI   r   r   )r1   r   r   r   r   r   datemsg_id
retry_leftr=   use_uidplusr   r   r   r   rg   daterr_msgrs   respr   s_uids                         r7   r&  zIMAPFolder.savemessageo  s   * 	FC5 7t~~c*!!#u-J 	!!#t'9'9: J/ ,,S%8 &&sL9+F
//335V	; (7+?+??"040L0L1-ZGGMM&#-{+< =))#z;G77''/MMM?E5zC'27+uST{%K
%*
GGMM&#'+5 6NN4#7#7#9:3'!(,,. 2259s||=|A"CJS# d{ $T4+=+=+?cK  
 /w8H8N8N8S8STT!"Jq p !JS#4K K  55kBD6>T\GGLL "ACFt9"M NZ 11': Y
K8<=1QXXg.=E=eBiooc2156C !8GGLL "469$i"@ A<<W=G=HJC
 axf'MN #==g>H>IK  &J &*\\^&4 5 11':$($A$A#$FDS!-2DS!'*fACGH
E ''  GG))$4Jl 11': u> }} 4!OJOO55gtD"oo??AG%. $T4+=+=+?QI -22::$JqM+ + GGMM!XZ]33}} ' OO55gtD"G*  t'9'9';SVE )..66 
1' ''B > " C  K*+D+.t9,5+;+A+A+I+IK KK< ! GGLL #',,.*k"K L  11': s   9C
Y P $BQ 7Y ;AY 8V7 <V2"V7 6-Y $A3X -Q5Y QY V/(B8T& Y &V/8A2V**V//Y 2V7 7W>Y 9W>>Y =X>>Y  Y!c           
         | j                   j                         }	 ddj                  | j                        z  }|}|r9	 |j	                  | j                         d       |j                  d||      \  }}	 | j                   j                  |       dk(  r D 
cg c]  }
t        |
t               r|
 }}
d
gk(  s|dk7  st#        |      dk7  rmt        j                  j                  }d| j%                         d|d|d|}|d
gk(  st#        |      dk  rd| j%                         d|d}t        ||      |d   d   j'                  d      }| j(                  d   j+                  |d   d         }t#        |j6                        dkD  r| j                  j9                  dj5                  ||j6                               t;        d |j6                  D              rN| j                  j9                  d       | j(                  d   j+                  | j=                  |d   d               }	 |j?                  | j@                  d         }||g}|S # |j                  $ r}|dz  }|dk  r7d||| j                  |fz  }	t        |	t        j                  j                        | j                  j                  d	||| j                  |||z
  |fz         | j                   j                  |d       | j                   j                         }Y d
}~nd
}~ww xY w|rߐ# | j                   j                  |       w xY wc c}
w #  t-               }t/        |d   d         j0                  }| j3                  |d   d         d   j'                  dd      }t        dj5                  |||d   j0                  |d         t        j                  j                        xY w# tB        $ rd}| jE                  |d      }|d}t        dj5                  ||t/        |      j0                  |      t        j                  j                        d
}~ww xY w)zFetches data from IMAP server.

        Arguments:
        - uids: message UIDS (OfflineIMAP3: First UID returned only)
        - retry_num: number of retries to make

        Returns: data obtained by this query.r   r~   T)r:   r   r	   r   z>%s, while fetching msg %r in folder %r. Max retry reached (%d)zB%s. While fetching msg %r in folder %r. Query: %s Retrying (%d/%d)Nry   zIMAP server 'z ' failed to fetch messages UID 'z'. Server responded: z$' does not have a message with UID 'r|   r}   r   asciisurrogateescape)errorszPException parsing message with ID ({}) from imaplib (response type: {}).
 {}: {}zUID {} has defects: {}c              3   <   K   | ]  }t        |t                y wr@   )r   r   ).0defects     r7   	<genexpr>z.IMAPFolder._fetch_from_imap.<locals>.<genexpr>  s     `v:f&AB`s   z% ... applying multipart boundary fix.r   r"  z<Unknown Message-ID>zDUID {} ({}) has defects preventing it from being processed!
  {}: {})#r#   rb   r   r'   r;   r<   r   r1  r2   r   rW   r   r   r   rf   r   r   r   r   r3   parser
parsebytesr   r   __name___extract_message_idr   defectsr   any_quote_boundary_fixr   r   UnicodeEncodeErrorr+  )r1   uids	retry_numr=   query
fails_leftr   r   rs   messageresrk   reasonndata0ndata1r   response_typer7  _ndatas                       r7   r   zIMAPFolder._fetch_from_imap?  s    //335	7chht78E"JBNN4#7#7#9DNI%,[[$%FNHd* OO--g6 t#'FCz#u/ECFDF D6>X-Ta'--55H262D2D2F2:DBF v~TQ -1,>,>,@$H"6844 a""7+kk*-88aDV v~~"GGLL188v~~NO`QWQ_Q_`` DEZ0;;D<T<TUYZ[U\]^U_<`a8OO4;;z+BOC  o }} B!OJ!Q$=$%tTYY	#B$C /w/?/E/E/M/MO OGGMM #@&'tyy%&/*&<iCI#I J
 OO55gtD"oo??AGB 2 OO--g6 G<	0*C a,55M--d1gaj9!<CCGSdCeF"cjjM3q6??CFD &&..0 0 & 8..v|D>3F&_ff &$s)*<*<cC(..668 88sg   "L 7I 6L L?1L?$M 0O L$B(LL LL L<BO	Q(AQQc                     |j                  | j                                |j                  d|||      \  }}|dk7  r>t        j                  j
                  }d| j                         ||||fz  }t        ||      |d   S )zStores data to IMAP server

        Arguments:
        - imapobj: instance of IMAPlib to use
        - uid: message UID
        - field: field name to be stored/updated
        - data: field contents
        storery   zPIMAP server '%s' failed to store %s for message UID '%d'.Server responded: %s %sr   )r;   r<   r   r   rW   r   r   )	r1   r=   r   fieldr   r   retdatark   rT  s	            r7   _store_to_imapzIMAPFolder._store_to_imap  s     	t++-.#KKeTB't'--55H/ ++-uc8W2NNF #6844qzrD   c                 ~   | j                   j                         }	 | j                  |t        |      dt	        j
                  |            }	 | j                   j                  |       |s|| j                  |   d<   yt	        j                  t	        j                  |      d         d   }t	        j                  |      | j                  |   d<   y# |j                  $ r< | j                  j                  | |g|       Y | j                   j                  |       yw xY w# | j                   j                  |       w xY w)zChange a message's flags to `flags`.

        Note that this function does not check against dryrun settings,
        so you need to ensure that it is never called in a
        dryrun mode.r   Nr   r	   )r#   rb   r^  r   r   r0  r:   r   flagstoreadonlyrf   r   r   	imapsplitr   )r1   r   r   r=   r   s        r7   r(  zIMAPFolder.savemessageflags  s    //335	7((#c(G)1)C)CE)JLF OO--g6-2DS!'*''(:(:6(B1(EFwOE-5-G-G-NDS!'*  	GG##D3%7OO--g6		 OO--g6s#   0C -D>D DD D<c                 *    | j                  |g|       y r@   )addmessagesflagsr1   r   r   s      r7   addmessageflagszIMAPFolder.addmessageflags  s    seU+rD   c                 *    | j                  d||       y )N+!_IMAPFolder__processmessagesflagsr1   uidlistr   s      r7   __addmessagesflags_noconvertz'IMAPFolder.__addmessagesflags_noconvert      ##C%8rD   c                 (    | j                  ||       y)zThis is here for the sake of UIDMaps.py -- deletemessages must
        add flags and get a converted UID, and if we don't have noconvert,
        then UIDMaps will try to convert it twice.N)'_IMAPFolder__addmessagesflags_noconvertrj  s      r7   rc  zIMAPFolder.addmessagesflags  s    
 	))'59rD   c                 *    | j                  |g|       y r@   )deletemessagesflagsrd  s      r7   deletemessageflagszIMAPFolder.deletemessageflags  s      #.rD   c                 *    | j                  d||       y )N-rh  rj  s      r7   rq  zIMAPFolder.deletemessagesflags  rm  rD   c                 d   | j                   j                         }	 	 |j                  | j                                |j                  dt        j                  |      |dz   t        j                  |            }|d   dk7  r9t        ddj                  |d         z  t        j                  j                        |d   }| j                   j                  |       t!        |      }|D ]  }|t        j"                  t        j$                  |      d         }d|v rd|v s:|d   }	t'        |d         }
t        j(                  |	      | j*                  |
   d	<   	 |j-                  |
        |D ]B  }
|d
k(  r| j*                  |
   d	xx   |z  cc<   #|dk(  s)| j*                  |
   d	xx   |z  cc<   D y # |j                  $ r; | j
                  j                  | ||       Y | j                   j                  |       y w xY w# | j                   j                  |       w xY w# t.        $ r Y Gw xY w)Nr[  r   r   ry   zError with store: %sr   r	   r   r   rg  rt  )r#   rb   r;   r<   r:   r   r`  rf   r   r   r   r0  r   r   rW   r   listr   ra  re   r   r   r   r  )r1   	operationrk  r   r=   rd   
needupdater   attributehashflagstrr   s              r7   __processmessagesflags_realz&IMAPFolder.__processmessagesflags_real  s,   //335	7t3356 {{7#+#8#8#A#,w#6#+#=#=e#DFH {d"&*TYYx{-CC$**224 4  {HOO--g6 ']
 	F~ $//0B0B60J10MNM]*w-/G#G,GmE*+C-5-G-G-PDS!'*!!#&	   	8CC  %g.%7.c!  %g.%7.		8E ## ''gu= OO--g6 OO--g6&  s;   F5 BH H"5,G?!H >G??H H"	H/.H/c                 p    d}t        dt        |      |      D ]  }| j                  |||||z    |        y )Nd   r   )ranger   &_IMAPFolder__processmessagesflags_real)r1   rw  rk  r   
batch_sizeis         r7   __processmessagesflagsz!IMAPFolder.__processmessagesflags  sK    
q#g,
3 	OA,,Y-4Qq:~-FO	O 	rD   c                 T    t        d||fz  t         j                  j                        )zyChange the message from existing uid to new_uid

        If the backend supports it. IMAP does not and will throw errors.z7IMAP backend cannot change a messages UID from %d to %d)r   rW   r   )r1   r   new_uids      r7   change_message_uidzIMAPFolder.change_message_uid#  s3    
   * #W~ ./?/E/E/M/MO 	OrD   c                 (    | j                  |g       y r@   %_IMAPFolder__deletemessages_noconvertr   s     r7   deletemessagezIMAPFolder.deletemessage-  s    ''.rD   c                 &    | j                  |       y r@   r  )r1   rk  s     r7   deletemessageszIMAPFolder.deletemessages1  s    ''0rD   c                 F   t        |      sy | j                  |t        d             | j                  j	                         }	 	 |j                  | j                                | j                  r|j                         d   dk(  sJ | j                  j                  |       |D ]  }| j                  |=  y # |j                  $ r: | j                  j                  | |       Y | j                  j                  |       y w xY w# | j                  j                  |       w xY w)NTr   ry   )r   ro  r   r#   rb   r;   r<   r:   r   deletereadonlyrf   r!   r   )r1   rk  r=   r   s       r7   __deletemessages_noconvertz%IMAPFolder.__deletemessages_noconvert4  s    7|))'3s8<//335		7t3356 ||)!,454OO--g6 	&C  %	& ## &&tW5 OO--g6 OO--g6s*   B7 #$D 7+D "D ?D  D D )T)F)NNr@   )r	   )'rH  
__module____qualname__r   rc   r<   rN   rR   rY   r\   ri   rv   r   r   r   r   r   r   r   r-  r4  r5  r*  r&  r   r^  r(  re  ro  rc  rr  rq  r  ri  r  r  r  r  __classcell__)r6   s   @r7   r   r   "   s    !"FO5
3)=7,%N_D7/Qd>-.1'@)$V[zM`N`iV*O0,9:/9+8ZO/1&rD   r   )r$   r   r+   r   sysr   offlineimapr   r   r   r   imaplib2r   Baser
   email.errorsr   CRLFr[   r    rD   r7   <module>r     sC   $   	   ? ?    4  c& c&rD   