Bump imaplib2 from 2.43 to 2.48
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
55ca922dd1
commit
71dd03e88c
@ -17,9 +17,9 @@ Public functions: Internaldate2Time
|
|||||||
__all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream",
|
__all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream",
|
||||||
"Internaldate2Time", "ParseFlags", "Time2Internaldate")
|
"Internaldate2Time", "ParseFlags", "Time2Internaldate")
|
||||||
|
|
||||||
__version__ = "2.43"
|
__version__ = "2.48"
|
||||||
__release__ = "2"
|
__release__ = "2"
|
||||||
__revision__ = "43"
|
__revision__ = "48"
|
||||||
__credits__ = """
|
__credits__ = """
|
||||||
Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998.
|
Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998.
|
||||||
String method conversion by ESR, February 2001.
|
String method conversion by ESR, February 2001.
|
||||||
@ -46,18 +46,23 @@ Fix for offlineimap "indexerror: string index out of range" bug provided by Eyge
|
|||||||
Fix for missing idle_lock in _handler() provided by Franklin Brook <franklin@brook.se> August 2014.
|
Fix for missing idle_lock in _handler() provided by Franklin Brook <franklin@brook.se> August 2014.
|
||||||
Conversion to Python3 provided by F. Malina <fmalina@gmail.com> February 2015.
|
Conversion to Python3 provided by F. Malina <fmalina@gmail.com> February 2015.
|
||||||
Fix for READ-ONLY error from multiple EXAMINE/SELECT calls by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015.
|
Fix for READ-ONLY error from multiple EXAMINE/SELECT calls by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015.
|
||||||
Fix for null strings appended to untagged responses by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015."""
|
Fix for null strings appended to untagged responses by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015.
|
||||||
|
Fix for correct byte encoding for _CRAM_MD5_AUTH taken from python3.5 imaplib.py June 2015.
|
||||||
|
Fix for correct Python 3 exception handling by Tobias Brink <tobias.brink@gmail.com> August 2015.
|
||||||
|
Fix to allow interruptible IDLE command by Tim Peoples <dromedary512@users.sf.net> September 2015."""
|
||||||
__author__ = "Piers Lauder <piers@janeelix.com>"
|
__author__ = "Piers Lauder <piers@janeelix.com>"
|
||||||
__URL__ = "http://imaplib2.sourceforge.net"
|
__URL__ = "http://imaplib2.sourceforge.net"
|
||||||
__license__ = "Python License"
|
__license__ = "Python License"
|
||||||
|
|
||||||
import binascii, errno, os, random, re, select, socket, sys, time, threading, zlib
|
import binascii, errno, os, random, re, select, socket, sys, time, threading, zlib
|
||||||
|
|
||||||
try:
|
if bytes != str:
|
||||||
import queue # py3
|
# Python 3, but NB assumes strings in all I/O
|
||||||
|
# for backwards compatibility with python 2 usage.
|
||||||
|
import queue
|
||||||
string_types = str
|
string_types = str
|
||||||
except ImportError:
|
else:
|
||||||
import Queue as queue # py2
|
import Queue as queue
|
||||||
string_types = basestring
|
string_types = basestring
|
||||||
|
|
||||||
|
|
||||||
@ -179,7 +184,7 @@ class Request(object):
|
|||||||
def get_response(self, exc_fmt=None):
|
def get_response(self, exc_fmt=None):
|
||||||
self.callback = None
|
self.callback = None
|
||||||
if __debug__: self.parent._log(3, '%s:%s.ready.wait' % (self.name, self.tag))
|
if __debug__: self.parent._log(3, '%s:%s.ready.wait' % (self.name, self.tag))
|
||||||
self.ready.wait()
|
self.ready.wait(sys.float_info.max)
|
||||||
|
|
||||||
if self.aborted is not None:
|
if self.aborted is not None:
|
||||||
typ, val = self.aborted
|
typ, val = self.aborted
|
||||||
@ -441,19 +446,22 @@ class IMAP4(object):
|
|||||||
af, socktype, proto, canonname, sa = res
|
af, socktype, proto, canonname, sa = res
|
||||||
try:
|
try:
|
||||||
s = socket.socket(af, socktype, proto)
|
s = socket.socket(af, socktype, proto)
|
||||||
except socket.error as msg:
|
except socket.error as m:
|
||||||
|
msg = m
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
for i in (0, 1):
|
for i in (0, 1):
|
||||||
try:
|
try:
|
||||||
s.connect(sa)
|
s.connect(sa)
|
||||||
break
|
break
|
||||||
except socket.error as msg:
|
except socket.error as m:
|
||||||
|
msg = m
|
||||||
if len(msg.args) < 2 or msg.args[0] != errno.EINTR:
|
if len(msg.args) < 2 or msg.args[0] != errno.EINTR:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
raise socket.error(msg)
|
raise socket.error(msg)
|
||||||
except socket.error as msg:
|
except socket.error as m:
|
||||||
|
msg = m
|
||||||
s.close()
|
s.close()
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
@ -534,9 +542,9 @@ class IMAP4(object):
|
|||||||
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
||||||
|
|
||||||
if bytes != str:
|
if bytes != str:
|
||||||
self.sock.sendall(bytes(data, 'utf8'))
|
data = bytes(data, 'utf8')
|
||||||
else:
|
|
||||||
self.sock.sendall(data)
|
self.sock.sendall(data)
|
||||||
|
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
@ -881,7 +889,9 @@ class IMAP4(object):
|
|||||||
def _CRAM_MD5_AUTH(self, challenge):
|
def _CRAM_MD5_AUTH(self, challenge):
|
||||||
"""Authobject to use with CRAM-MD5 authentication."""
|
"""Authobject to use with CRAM-MD5 authentication."""
|
||||||
import hmac
|
import hmac
|
||||||
return self.user + " " + hmac.HMAC(self.password, challenge).hexdigest()
|
pwd = (self.password.encode('utf-8') if isinstance(self.password, str)
|
||||||
|
else self.password)
|
||||||
|
return self.user + " " + hmac.HMAC(pwd, challenge, 'md5').hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def logout(self, **kw):
|
def logout(self, **kw):
|
||||||
@ -1229,7 +1239,7 @@ class IMAP4(object):
|
|||||||
|
|
||||||
self.commands_lock.release()
|
self.commands_lock.release()
|
||||||
|
|
||||||
if __debug__: self._log(5, 'untagged_responses[%s] %s += ["%s"]' % (typ, len(urd)-1, dat))
|
if __debug__: self._log(5, 'untagged_responses[%s] %s += ["%.80s"]' % (typ, len(urd)-1, dat))
|
||||||
|
|
||||||
|
|
||||||
def _check_bye(self):
|
def _check_bye(self):
|
||||||
@ -1297,7 +1307,7 @@ class IMAP4(object):
|
|||||||
self.commands_lock.release()
|
self.commands_lock.release()
|
||||||
if need_event:
|
if need_event:
|
||||||
if __debug__: self._log(3, 'sync command %s waiting for empty commands Q' % name)
|
if __debug__: self._log(3, 'sync command %s waiting for empty commands Q' % name)
|
||||||
self.state_change_free.wait()
|
self.state_change_free.wait(sys.float_info.max)
|
||||||
if __debug__: self._log(3, 'sync command %s proceeding' % name)
|
if __debug__: self._log(3, 'sync command %s proceeding' % name)
|
||||||
|
|
||||||
if self.state not in Commands[name][CMD_VAL_STATES]:
|
if self.state not in Commands[name][CMD_VAL_STATES]:
|
||||||
@ -1316,7 +1326,7 @@ class IMAP4(object):
|
|||||||
while self._get_untagged_response(typ):
|
while self._get_untagged_response(typ):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self._get_untagged_response('READ-ONLY', leave=True) and not self.is_readonly:
|
if not self.is_readonly and self._get_untagged_response('READ-ONLY', leave=True):
|
||||||
self.literal = None
|
self.literal = None
|
||||||
raise self.readonly('mailbox status changed to READ-ONLY')
|
raise self.readonly('mailbox status changed to READ-ONLY')
|
||||||
|
|
||||||
@ -1402,7 +1412,7 @@ class IMAP4(object):
|
|||||||
def _command_completer(self, cb_arg_list):
|
def _command_completer(self, cb_arg_list):
|
||||||
|
|
||||||
# Called for callback commands
|
# Called for callback commands
|
||||||
(response, cb_arg, error) = cb_arg_list
|
response, cb_arg, error = cb_arg_list
|
||||||
rqb, kw = cb_arg
|
rqb, kw = cb_arg
|
||||||
rqb.callback = kw['callback']
|
rqb.callback = kw['callback']
|
||||||
rqb.callback_arg = kw.get('cb_arg')
|
rqb.callback_arg = kw.get('cb_arg')
|
||||||
@ -1420,6 +1430,7 @@ class IMAP4(object):
|
|||||||
if __debug__: self._print_log()
|
if __debug__: self._print_log()
|
||||||
rqb.abort(self.error, '%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data))
|
rqb.abort(self.error, '%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data))
|
||||||
return
|
return
|
||||||
|
if __debug__: self._log(4, '_command_completer(%s, %s, None) = %s' % (response, cb_arg, rqb.tag))
|
||||||
if 'untagged_response' in kw:
|
if 'untagged_response' in kw:
|
||||||
response = self._untagged_response(typ, dat, kw['untagged_response'])
|
response = self._untagged_response(typ, dat, kw['untagged_response'])
|
||||||
rqb.deliver(response)
|
rqb.deliver(response)
|
||||||
@ -1463,7 +1474,7 @@ class IMAP4(object):
|
|||||||
if not leave:
|
if not leave:
|
||||||
del self.untagged_responses[i]
|
del self.untagged_responses[i]
|
||||||
self.commands_lock.release()
|
self.commands_lock.release()
|
||||||
if __debug__: self._log(5, '_get_untagged_response(%s) => %s' % (name, dat))
|
if __debug__: self._log(5, '_get_untagged_response(%s) => %.80s' % (name, dat))
|
||||||
return dat
|
return dat
|
||||||
|
|
||||||
self.commands_lock.release()
|
self.commands_lock.release()
|
||||||
@ -1605,11 +1616,17 @@ class IMAP4(object):
|
|||||||
self.commands_lock.acquire()
|
self.commands_lock.acquire()
|
||||||
rqb = self.tagged_commands.pop(name)
|
rqb = self.tagged_commands.pop(name)
|
||||||
if not self.tagged_commands:
|
if not self.tagged_commands:
|
||||||
|
need_event = True
|
||||||
|
else:
|
||||||
|
need_event = False
|
||||||
|
self.commands_lock.release()
|
||||||
|
|
||||||
|
if __debug__: self._log(4, '_request_pop(%s, %s) [%d] = %s' % (name, data, len(self.tagged_commands), rqb.tag))
|
||||||
|
rqb.deliver(data)
|
||||||
|
|
||||||
|
if need_event:
|
||||||
if __debug__: self._log(3, 'state_change_free.set')
|
if __debug__: self._log(3, 'state_change_free.set')
|
||||||
self.state_change_free.set()
|
self.state_change_free.set()
|
||||||
self.commands_lock.release()
|
|
||||||
if __debug__: self._log(4, '_request_pop(%s, %s) = %s' % (name, data, rqb.tag))
|
|
||||||
rqb.deliver(data)
|
|
||||||
|
|
||||||
|
|
||||||
def _request_push(self, tag=None, name=None, **kw):
|
def _request_push(self, tag=None, name=None, **kw):
|
||||||
@ -1645,7 +1662,7 @@ class IMAP4(object):
|
|||||||
if not dat:
|
if not dat:
|
||||||
break
|
break
|
||||||
data += dat
|
data += dat
|
||||||
if __debug__: self._log(4, '_untagged_response(%s, ?, %s) => %s' % (typ, name, data))
|
if __debug__: self._log(4, '_untagged_response(%s, ?, %s) => %.80s' % (typ, name, data))
|
||||||
return typ, data
|
return typ, data
|
||||||
|
|
||||||
|
|
||||||
@ -1762,7 +1779,10 @@ class IMAP4(object):
|
|||||||
}
|
}
|
||||||
return ' '.join([PollErrors[s] for s in PollErrors.keys() if (s & state)])
|
return ' '.join([PollErrors[s] for s in PollErrors.keys() if (s & state)])
|
||||||
|
|
||||||
line_part = ''
|
if bytes != str:
|
||||||
|
line_part = b''
|
||||||
|
else:
|
||||||
|
line_part = ''
|
||||||
|
|
||||||
poll = select.poll()
|
poll = select.poll()
|
||||||
|
|
||||||
@ -1774,7 +1794,7 @@ class IMAP4(object):
|
|||||||
|
|
||||||
while not (terminate or self.Terminate):
|
while not (terminate or self.Terminate):
|
||||||
if self.state == LOGOUT:
|
if self.state == LOGOUT:
|
||||||
timeout = 1
|
timeout = 10
|
||||||
else:
|
else:
|
||||||
timeout = read_poll_timeout
|
timeout = read_poll_timeout
|
||||||
try:
|
try:
|
||||||
@ -1802,11 +1822,11 @@ class IMAP4(object):
|
|||||||
if bytes != str:
|
if bytes != str:
|
||||||
stop = data.find(b'\n', start)
|
stop = data.find(b'\n', start)
|
||||||
if stop < 0:
|
if stop < 0:
|
||||||
line_part += data[start:].decode()
|
line_part += data[start:]
|
||||||
break
|
break
|
||||||
stop += 1
|
stop += 1
|
||||||
line_part, start, line = \
|
line_part, start, line = \
|
||||||
'', stop, line_part + data[start:stop].decode()
|
b'', stop, (line_part + data[start:stop]).decode(errors='ignore')
|
||||||
else:
|
else:
|
||||||
stop = data.find('\n', start)
|
stop = data.find('\n', start)
|
||||||
if stop < 0:
|
if stop < 0:
|
||||||
@ -1846,7 +1866,10 @@ class IMAP4(object):
|
|||||||
|
|
||||||
if __debug__: self._log(1, 'starting using select')
|
if __debug__: self._log(1, 'starting using select')
|
||||||
|
|
||||||
line_part = ''
|
if bytes != str:
|
||||||
|
line_part = b''
|
||||||
|
else:
|
||||||
|
line_part = ''
|
||||||
|
|
||||||
rxzero = 0
|
rxzero = 0
|
||||||
terminate = False
|
terminate = False
|
||||||
@ -1878,11 +1901,11 @@ class IMAP4(object):
|
|||||||
if bytes != str:
|
if bytes != str:
|
||||||
stop = data.find(b'\n', start)
|
stop = data.find(b'\n', start)
|
||||||
if stop < 0:
|
if stop < 0:
|
||||||
line_part += data[start:].decode()
|
line_part += data[start:]
|
||||||
break
|
break
|
||||||
stop += 1
|
stop += 1
|
||||||
line_part, start, line = \
|
line_part, start, line = \
|
||||||
'', stop, line_part + data[start:stop].decode()
|
b'', stop, (line_part + data[start:stop]).decode(errors='ignore')
|
||||||
else:
|
else:
|
||||||
stop = data.find('\n', start)
|
stop = data.find('\n', start)
|
||||||
if stop < 0:
|
if stop < 0:
|
||||||
@ -2100,27 +2123,18 @@ class IMAP4_SSL(IMAP4):
|
|||||||
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
||||||
|
|
||||||
if bytes != str:
|
if bytes != str:
|
||||||
if hasattr(self.sock, "sendall"):
|
data = bytes(data, 'utf8')
|
||||||
self.sock.sendall(bytes(data, 'utf8'))
|
|
||||||
else:
|
if hasattr(self.sock, "sendall"):
|
||||||
dlen = len(data)
|
self.sock.sendall(data)
|
||||||
while dlen > 0:
|
|
||||||
sent = self.sock.write(bytes(data, 'utf8'))
|
|
||||||
if sent == dlen:
|
|
||||||
break # avoid copy
|
|
||||||
data = data[sent:]
|
|
||||||
dlen = dlen - sent
|
|
||||||
else:
|
else:
|
||||||
if hasattr(self.sock, "sendall"):
|
dlen = len(data)
|
||||||
self.sock.sendall(data)
|
while dlen > 0:
|
||||||
else:
|
sent = self.sock.write(data)
|
||||||
dlen = len(data)
|
if sent == dlen:
|
||||||
while dlen > 0:
|
break # avoid copy
|
||||||
sent = self.sock.write(data)
|
data = data[sent:]
|
||||||
if sent == dlen:
|
dlen = dlen - sent
|
||||||
break # avoid copy
|
|
||||||
data = data[sent:]
|
|
||||||
dlen = dlen - sent
|
|
||||||
|
|
||||||
|
|
||||||
def ssl(self):
|
def ssl(self):
|
||||||
@ -2195,9 +2209,9 @@ class IMAP4_stream(IMAP4):
|
|||||||
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
||||||
|
|
||||||
if bytes != str:
|
if bytes != str:
|
||||||
self.writefile.write(bytes(data, 'utf8'))
|
data = bytes(data, 'utf8')
|
||||||
else:
|
|
||||||
self.writefile.write(data)
|
self.writefile.write(data)
|
||||||
self.writefile.flush()
|
self.writefile.flush()
|
||||||
|
|
||||||
|
|
||||||
@ -2372,8 +2386,14 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
# To test: invoke either as 'python imaplib2.py [IMAP4_server_hostname]',
|
# To test: invoke either as 'python imaplib2.py [IMAP4_server_hostname]',
|
||||||
# or as 'python imaplib2.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"'
|
# or as 'python imaplib2.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"'
|
||||||
# or as 'python imaplib2.py -l "keyfile[:certfile]" [IMAP4_SSL_server_hostname]'
|
# or as 'python imaplib2.py -l keyfile[:certfile]|: [IMAP4_SSL_server_hostname]'
|
||||||
|
#
|
||||||
|
# Option "-d <level>" turns on debugging (use "-d 5" for everything)
|
||||||
# Option "-i" tests that IDLE is interruptible
|
# Option "-i" tests that IDLE is interruptible
|
||||||
|
# Option "-p <port>" allows alternate ports
|
||||||
|
|
||||||
|
if not __debug__:
|
||||||
|
raise ValueError('Please run without -O')
|
||||||
|
|
||||||
import getopt, getpass
|
import getopt, getpass
|
||||||
|
|
||||||
@ -2446,10 +2466,10 @@ if __name__ == '__main__':
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
AsyncError = None
|
AsyncError, M = None, None
|
||||||
|
|
||||||
def responder(cb_arg_list):
|
def responder(cb_arg_list):
|
||||||
(response, cb_arg, error) = cb_arg_list
|
response, cb_arg, error = cb_arg_list
|
||||||
global AsyncError
|
global AsyncError
|
||||||
cmd, args = cb_arg
|
cmd, args = cb_arg
|
||||||
if error is not None:
|
if error is not None:
|
||||||
@ -2569,7 +2589,7 @@ if __name__ == '__main__':
|
|||||||
print('All tests OK.')
|
print('All tests OK.')
|
||||||
|
|
||||||
except:
|
except:
|
||||||
if not idle_intr or not 'IDLE' in M.capabilities:
|
if not idle_intr or M is None or not 'IDLE' in M.capabilities:
|
||||||
print('Tests failed.')
|
print('Tests failed.')
|
||||||
|
|
||||||
if not debug:
|
if not debug:
|
||||||
|
Loading…
Reference in New Issue
Block a user