From f9360ba2d747f828c3c7af269a87ae8165c21d1c Mon Sep 17 00:00:00 2001 From: Nicolas Sebrecht Date: Sun, 5 Mar 2017 13:28:47 +0100 Subject: [PATCH] bump from imaplib2 v2.55 to v2.57 Signed-off-by: Nicolas Sebrecht --- offlineimap/bundled_imaplib2.py | 60 +++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/offlineimap/bundled_imaplib2.py b/offlineimap/bundled_imaplib2.py index d705021..1fd47d2 100755 --- a/offlineimap/bundled_imaplib2.py +++ b/offlineimap/bundled_imaplib2.py @@ -18,9 +18,9 @@ __all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream", "Internaldate2Time", "ParseFlags", "Time2Internaldate", "Mon2num", "MonthNames", "InternalDate") -__version__ = "2.55" +__version__ = "2.57" __release__ = "2" -__revision__ = "55" +__revision__ = "57" __credits__ = """ Authentication code contributed by Donn Cave June 1998. String method conversion by ESR, February 2001. @@ -109,6 +109,7 @@ Commands = { 'CREATE': ((AUTH, SELECTED), True), 'DELETE': ((AUTH, SELECTED), True), 'DELETEACL': ((AUTH, SELECTED), True), + 'ENABLE': ((AUTH,), False), 'EXAMINE': ((AUTH, SELECTED), False), 'EXPUNGE': ((SELECTED,), True), 'FETCH': ((SELECTED,), True), @@ -300,17 +301,18 @@ class IMAP4(object): class readonly(abort): pass # Mailbox status changed to READ-ONLY + # These must be encoded according to utf8 setting in _mode_xxx(): + _literal = br'.*{(?P\d+)}$' + _untagged_status = br'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?' + continuation_cre = re.compile(r'\+( (?P.*))?') - literal_cre = re.compile(r'.*{(?P\d+)}$') mapCRLF_cre = re.compile(r'\r\n|\r|\n') # Need to quote "atom-specials" :- # "(" / ")" / "{" / SP / 0x00 - 0x1f / 0x7f / "%" / "*" / DQUOTE / "\" / "]" # so match not the inverse set mustquote_cre = re.compile(r"[^!#$&'+,./0-9:;<=>?@A-Z\[^_`a-z|}~-]") response_code_cre = re.compile(r'\[(?P[A-Z-]+)( (?P[^\]]*))?\]') - # sequence_set_cre = re.compile(r"^[0-9]+(:([0-9]+|\*))?(,[0-9]+(:([0-9]+|\*))?)*$") untagged_response_cre = re.compile(r'\* (?P[A-Z-]+)( (?P.*))?') - untagged_status_cre = re.compile(r'\* (?P\d+) (?P[A-Z-]+)( (?P.*))?') def __init__(self, host=None, port=None, debug=None, debug_file=None, identifier=None, timeout=None, debug_buf_lvl=None): @@ -342,6 +344,8 @@ class IMAP4(object): + self.tagpre + r'\d+) (?P[A-Z]+) (?P.*)') + self._mode_ascii() # Only option in py2 + if __debug__: self._init_debug(debug, debug_file, debug_buf_lvl) self.resp_timeout = timeout # Timeout waiting for command response @@ -428,6 +432,28 @@ class IMAP4(object): raise AttributeError("Unknown IMAP4 command: '%s'" % attr) + def _mode_ascii(self): + self.utf8_enabled = False + self._encoding = 'ascii' + if bytes != str: + self.literal_cre = re.compile(self._literal, re.ASCII) + self.untagged_status_cre = re.compile(self._untagged_status, re.ASCII) + else: + self.literal_cre = re.compile(self._literal) + self.untagged_status_cre = re.compile(self._untagged_status) + + + def _mode_utf8(self): + self.utf8_enabled = True + self._encoding = 'utf-8' + if bytes != str: + self.literal_cre = re.compile(self._literal) + self.untagged_status_cre = re.compile(self._untagged_status) + else: + self.literal_cre = re.compile(self._literal, re.UNICODE) + self.untagged_status_cre = re.compile(self._untagged_status, re.UNICODE) + + # Overridable methods @@ -676,7 +702,10 @@ class IMAP4(object): date_time = Time2Internaldate(date_time) else: date_time = None - self.literal = self.mapCRLF_cre.sub(CRLF, message) + literal = self.mapCRLF_cre.sub(CRLF, message) + if self.utf8_enabled: + literal = b'UTF8 (' + literal + b')' + self.literal = literal try: return self._simple_command(name, mailbox, flags, date_time, **kw) finally: @@ -774,6 +803,19 @@ class IMAP4(object): return self._simple_command('DELETEACL', mailbox, who, **kw) + def enable(self, capability): + """Send an RFC5161 enable string to the server. + + (typ, [data]) = .enable(capability) + """ + if 'ENABLE' not in self.capabilities: + raise self.error("Server does not support ENABLE") + typ, data = self._simple_command('ENABLE', capability) + if typ == 'OK' and 'UTF8=ACCEPT' in capability.upper(): + self._mode_utf8() + return typ, data + + def examine(self, mailbox='INBOX', **kw): """(typ, [data]) = examine(mailbox='INBOX') Select a mailbox for READ-ONLY access. (Flushes all untagged responses.) @@ -1025,11 +1067,14 @@ class IMAP4(object): def search(self, charset, *criteria, **kw): """(typ, [data]) = search(charset, criterion, ...) Search mailbox for matching messages. + If UTF8 is enabled, charset MUST be None. 'data' is space separated list of matching message numbers.""" name = 'SEARCH' kw['untagged_response'] = name if charset: + if self.utf8_enabled: + raise self.error("Non-None charset not valid in UTF8 mode") return self._simple_command(name, 'CHARSET', charset, *criteria, **kw) return self._simple_command(name, *criteria, **kw) @@ -1412,6 +1457,9 @@ class IMAP4(object): if not ok: break + if data == 'go ahead': # Apparently not uncommon broken IMAP4 server response to AUTHENTICATE command + data = '' + # Send literal if literator is not None: