[imaplib2 removal] Revert "use latest version of imaplib2"
This reverts commit fadbd38ef9
.
This commit is contained in:
parent
3869af9e0b
commit
36e0971adb
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python2.5
|
||||||
|
|
||||||
"""Threaded IMAP4 client.
|
"""Threaded IMAP4 client.
|
||||||
|
|
||||||
@ -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.11"
|
__version__ = "2.6"
|
||||||
__release__ = "2"
|
__release__ = "2"
|
||||||
__revision__ = "11"
|
__revision__ = "6"
|
||||||
__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.
|
||||||
@ -29,11 +29,11 @@ GET/SETQUOTA contributed by Andreas Zeidler <az@kreativkombinat.de> June 2002.
|
|||||||
PROXYAUTH contributed by Rick Holbert <holbert.13@osu.edu> November 2002.
|
PROXYAUTH contributed by Rick Holbert <holbert.13@osu.edu> November 2002.
|
||||||
IDLE via threads suggested by Philippe Normand <phil@respyre.org> January 2005.
|
IDLE via threads suggested by Philippe Normand <phil@respyre.org> January 2005.
|
||||||
GET/SETANNOTATION contributed by Tomas Lindroos <skitta@abo.fi> June 2005.
|
GET/SETANNOTATION contributed by Tomas Lindroos <skitta@abo.fi> June 2005.
|
||||||
COMPRESS/DEFLATE contributed by Bron Gondwana <brong@brong.net> May 2009."""
|
New socket open code from http://www.python.org/doc/lib/socket-example.html."""
|
||||||
__author__ = "Piers Lauder <piers@janeelix.com>"
|
__author__ = "Piers Lauder <piers@janeelix.com>"
|
||||||
__URL__ = "http://janeelix.com/piers/python/imaplib2"
|
# Source URL: http://www.cs.usyd.edu.au/~piers/python/imaplib2
|
||||||
|
|
||||||
import binascii, os, Queue, random, re, select, socket, sys, time, threading, zlib
|
import binascii, os, Queue, random, re, select, socket, sys, time, threading
|
||||||
|
|
||||||
select_module = select
|
select_module = select
|
||||||
|
|
||||||
@ -62,7 +62,6 @@ Commands = {
|
|||||||
'CAPABILITY': ((NONAUTH, AUTH, SELECTED), True),
|
'CAPABILITY': ((NONAUTH, AUTH, SELECTED), True),
|
||||||
'CHECK': ((SELECTED,), True),
|
'CHECK': ((SELECTED,), True),
|
||||||
'CLOSE': ((SELECTED,), False),
|
'CLOSE': ((SELECTED,), False),
|
||||||
'COMPRESS': ((AUTH,), False),
|
|
||||||
'COPY': ((SELECTED,), True),
|
'COPY': ((SELECTED,), True),
|
||||||
'CREATE': ((AUTH, SELECTED), True),
|
'CREATE': ((AUTH, SELECTED), True),
|
||||||
'DELETE': ((AUTH, SELECTED), True),
|
'DELETE': ((AUTH, SELECTED), True),
|
||||||
@ -265,9 +264,6 @@ class IMAP4(object):
|
|||||||
self._accumulated_data = [] # Message data accumulated so far
|
self._accumulated_data = [] # Message data accumulated so far
|
||||||
self._literal_expected = None # Message data descriptor
|
self._literal_expected = None # Message data descriptor
|
||||||
|
|
||||||
self.compressor = None # COMPRESS/DEFLATE if not None
|
|
||||||
self.decompressor = None
|
|
||||||
|
|
||||||
# Create unique tag for this session,
|
# Create unique tag for this session,
|
||||||
# and compile tagged response matcher.
|
# and compile tagged response matcher.
|
||||||
|
|
||||||
@ -362,8 +358,7 @@ class IMAP4(object):
|
|||||||
|
|
||||||
|
|
||||||
def open_socket(self):
|
def open_socket(self):
|
||||||
"""open_socket()
|
"""Open socket choosing first address family available."""
|
||||||
Open socket choosing first address family available."""
|
|
||||||
|
|
||||||
msg = (-1, 'could not open socket')
|
msg = (-1, 'could not open socket')
|
||||||
for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM):
|
for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM):
|
||||||
@ -384,38 +379,17 @@ class IMAP4(object):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def start_compressing(self):
|
|
||||||
"""start_compressing()
|
|
||||||
Enable deflate compression on the socket (RFC 4978)."""
|
|
||||||
|
|
||||||
# rfc 1951 - pure DEFLATE, so use -15 for both windows
|
|
||||||
self.decompressor = zlib.decompressobj(-15)
|
|
||||||
self.compressor = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, -15)
|
|
||||||
|
|
||||||
|
|
||||||
def read(self, size):
|
def read(self, size):
|
||||||
"""data = read(size)
|
"""data = read(size)
|
||||||
Read at most 'size' bytes from remote."""
|
Read at most 'size' bytes from remote."""
|
||||||
|
|
||||||
if self.decompressor is None:
|
return self.sock.recv(size)
|
||||||
return self.sock.recv(size)
|
|
||||||
|
|
||||||
if self.decompressor.unconsumed_tail:
|
|
||||||
data = self.decompressor.unconsumed_tail
|
|
||||||
else:
|
|
||||||
data = self.sock.recv(8192)
|
|
||||||
|
|
||||||
return self.decompressor.decompress(data, size)
|
|
||||||
|
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
"""send(data)
|
"""send(data)
|
||||||
Send 'data' to remote."""
|
Send 'data' to remote."""
|
||||||
|
|
||||||
if self.compressor is not None:
|
|
||||||
data = self.compressor.compress(data)
|
|
||||||
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
|
||||||
|
|
||||||
self.sock.sendall(data)
|
self.sock.sendall(data)
|
||||||
|
|
||||||
|
|
||||||
@ -437,22 +411,6 @@ class IMAP4(object):
|
|||||||
# Utility methods
|
# Utility methods
|
||||||
|
|
||||||
|
|
||||||
def enable_compression(self):
|
|
||||||
"""enable_compression()
|
|
||||||
Ask the server to start compressing the connection.
|
|
||||||
Should be called from user of this class after instantiation, as in:
|
|
||||||
if 'COMPRESS=DEFLATE' in imapobj.capabilities:
|
|
||||||
imapobj.enable_compression()"""
|
|
||||||
|
|
||||||
try:
|
|
||||||
typ, dat = self._simple_command('COMPRESS', 'DEFLATE')
|
|
||||||
if typ == 'OK':
|
|
||||||
self.start_compressing()
|
|
||||||
if __debug__: self._log(1, 'Enabled COMPRESS=DEFLATE')
|
|
||||||
finally:
|
|
||||||
self.state_change_pending.release()
|
|
||||||
|
|
||||||
|
|
||||||
def recent(self, **kw):
|
def recent(self, **kw):
|
||||||
"""(typ, [data]) = recent()
|
"""(typ, [data]) = recent()
|
||||||
Return most recent 'RECENT' responses if any exist,
|
Return most recent 'RECENT' responses if any exist,
|
||||||
@ -475,7 +433,7 @@ class IMAP4(object):
|
|||||||
|
|
||||||
typ, dat = self._untagged_response(code, [None], code.upper())
|
typ, dat = self._untagged_response(code, [None], code.upper())
|
||||||
return self._deliver_dat(typ, dat, kw)
|
return self._deliver_dat(typ, dat, kw)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -689,9 +647,9 @@ class IMAP4(object):
|
|||||||
List mailbox names in directory matching pattern.
|
List mailbox names in directory matching pattern.
|
||||||
'data' is list of LIST responses.
|
'data' is list of LIST responses.
|
||||||
|
|
||||||
NB: for 'pattern':
|
NB: for 'pattern':
|
||||||
% matches all except separator ( so LIST "" "%" returns names at root)
|
% matches all except separator ( so LIST "" "%" returns names at root)
|
||||||
* matches all (so LIST "" "*" returns whole directory tree from root)"""
|
* matches all (so LIST "" "*" returns whole directory tree from root)"""
|
||||||
|
|
||||||
name = 'LIST'
|
name = 'LIST'
|
||||||
kw['untagged_response'] = name
|
kw['untagged_response'] = name
|
||||||
@ -855,7 +813,7 @@ class IMAP4(object):
|
|||||||
self.state = AUTH
|
self.state = AUTH
|
||||||
if __debug__: self._log(1, 'state => AUTH')
|
if __debug__: self._log(1, 'state => AUTH')
|
||||||
if typ == 'BAD':
|
if typ == 'BAD':
|
||||||
self._deliver_exc(self.error, '%s command error: %s %s. Data: %.100s' % (name, typ, dat, mailbox), kw)
|
self._deliver_exc(self.error, '%s command error: %s %s' % (name, typ, dat), kw)
|
||||||
return self._deliver_dat(typ, dat, kw)
|
return self._deliver_dat(typ, dat, kw)
|
||||||
self.state = SELECTED
|
self.state = SELECTED
|
||||||
if __debug__: self._log(1, 'state => SELECTED')
|
if __debug__: self._log(1, 'state => SELECTED')
|
||||||
@ -1085,25 +1043,20 @@ class IMAP4(object):
|
|||||||
literal = self.literal
|
literal = self.literal
|
||||||
if literal is not None:
|
if literal is not None:
|
||||||
self.literal = None
|
self.literal = None
|
||||||
if isinstance(literal, basestring):
|
if isinstance(literal, str):
|
||||||
literator = None
|
literator = None
|
||||||
data = '%s {%s}' % (data, len(literal))
|
data = '%s {%s}' % (data, len(literal))
|
||||||
else:
|
else:
|
||||||
literator = literal
|
literator = literal
|
||||||
|
|
||||||
if __debug__: self._log(4, 'data=%s' % data)
|
|
||||||
|
|
||||||
rqb.data = '%s%s' % (data, CRLF)
|
rqb.data = '%s%s' % (data, CRLF)
|
||||||
|
self.ouq.put(rqb)
|
||||||
|
|
||||||
if literal is None:
|
if literal is None:
|
||||||
self.ouq.put(rqb)
|
|
||||||
return rqb
|
return rqb
|
||||||
|
|
||||||
# Must setup continuation expectancy *before* ouq.put
|
|
||||||
crqb = self._request_push(tag='continuation')
|
crqb = self._request_push(tag='continuation')
|
||||||
|
|
||||||
self.ouq.put(rqb)
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# Wait for continuation response
|
# Wait for continuation response
|
||||||
|
|
||||||
@ -1123,10 +1076,6 @@ class IMAP4(object):
|
|||||||
if literal is None:
|
if literal is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
if literator is not None:
|
|
||||||
# Need new request for next continuation response
|
|
||||||
crqb = self._request_push(tag='continuation')
|
|
||||||
|
|
||||||
if __debug__: self._log(4, 'write literal size %s' % len(literal))
|
if __debug__: self._log(4, 'write literal size %s' % len(literal))
|
||||||
crqb.data = '%s%s' % (literal, CRLF)
|
crqb.data = '%s%s' % (literal, CRLF)
|
||||||
self.ouq.put(crqb)
|
self.ouq.put(crqb)
|
||||||
@ -1134,6 +1083,10 @@ class IMAP4(object):
|
|||||||
if literator is None:
|
if literator is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
self.commands_lock.acquire()
|
||||||
|
self.tagged_commands['continuation'] = crqb
|
||||||
|
self.commands_lock.release()
|
||||||
|
|
||||||
return rqb
|
return rqb
|
||||||
|
|
||||||
|
|
||||||
@ -1145,7 +1098,7 @@ class IMAP4(object):
|
|||||||
self._check_bye()
|
self._check_bye()
|
||||||
if typ == 'BAD':
|
if typ == 'BAD':
|
||||||
if __debug__: self._print_log()
|
if __debug__: self._print_log()
|
||||||
raise self.error('%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data))
|
raise self.error('%s command error: %s %s' % (rqb.name, typ, dat))
|
||||||
if 'untagged_response' in kw:
|
if 'untagged_response' in kw:
|
||||||
return self._untagged_response(typ, dat, kw['untagged_response'])
|
return self._untagged_response(typ, dat, kw['untagged_response'])
|
||||||
return typ, dat
|
return typ, dat
|
||||||
@ -1169,11 +1122,12 @@ class IMAP4(object):
|
|||||||
typ, dat = response
|
typ, dat = response
|
||||||
if typ == 'BAD':
|
if typ == 'BAD':
|
||||||
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' % (rqb.name, typ, dat))
|
||||||
return
|
return
|
||||||
if 'untagged_response' in kw:
|
if 'untagged_response' in kw:
|
||||||
response = self._untagged_response(typ, dat, kw['untagged_response'])
|
rqb.deliver(self._untagged_response(typ, dat, kw['untagged_response']))
|
||||||
rqb.deliver(response)
|
else:
|
||||||
|
rqb.deliver(response)
|
||||||
|
|
||||||
|
|
||||||
def _deliver_dat(self, typ, dat, kw):
|
def _deliver_dat(self, typ, dat, kw):
|
||||||
@ -1193,13 +1147,12 @@ class IMAP4(object):
|
|||||||
def _end_idle(self):
|
def _end_idle(self):
|
||||||
|
|
||||||
irqb = self.idle_rqb
|
irqb = self.idle_rqb
|
||||||
if irqb is None:
|
if irqb is not None:
|
||||||
return
|
self.idle_rqb = None
|
||||||
self.idle_rqb = None
|
self.idle_timeout = None
|
||||||
self.idle_timeout = None
|
irqb.data = 'DONE%s' % CRLF
|
||||||
irqb.data = 'DONE%s' % CRLF
|
self.ouq.put(irqb)
|
||||||
self.ouq.put(irqb)
|
if __debug__: self._log(2, 'server IDLE finished')
|
||||||
if __debug__: self._log(2, 'server IDLE finished')
|
|
||||||
|
|
||||||
|
|
||||||
def _match(self, cre, s):
|
def _match(self, cre, s):
|
||||||
@ -1384,7 +1337,7 @@ class IMAP4(object):
|
|||||||
|
|
||||||
threading.currentThread().setName('hdlr')
|
threading.currentThread().setName('hdlr')
|
||||||
|
|
||||||
time.sleep(0.1) # Don't start handling before main thread ready
|
time.sleep(0.1) # Don't start handling before main thread ready
|
||||||
|
|
||||||
if __debug__: self._log(1, 'starting')
|
if __debug__: self._log(1, 'starting')
|
||||||
|
|
||||||
@ -1413,7 +1366,7 @@ class IMAP4(object):
|
|||||||
if line is None:
|
if line is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
if not isinstance(line, basestring):
|
if not isinstance(line, str):
|
||||||
typ, val = line
|
typ, val = line
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -1711,12 +1664,7 @@ class IMAP4_SSL(IMAP4):
|
|||||||
self.host = host is not None and host or ''
|
self.host = host is not None and host or ''
|
||||||
self.port = port is not None and port or IMAP4_SSL_PORT
|
self.port = port is not None and port or IMAP4_SSL_PORT
|
||||||
self.sock = self.open_socket()
|
self.sock = self.open_socket()
|
||||||
|
self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile)
|
||||||
try:
|
|
||||||
import ssl
|
|
||||||
self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
|
|
||||||
except ImportError:
|
|
||||||
self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile)
|
|
||||||
|
|
||||||
self.read_fd = self.sock.fileno()
|
self.read_fd = self.sock.fileno()
|
||||||
|
|
||||||
@ -1725,25 +1673,13 @@ class IMAP4_SSL(IMAP4):
|
|||||||
"""data = read(size)
|
"""data = read(size)
|
||||||
Read at most 'size' bytes from remote."""
|
Read at most 'size' bytes from remote."""
|
||||||
|
|
||||||
if self.decompressor is None:
|
return self.sslobj.read(size)
|
||||||
return self.sslobj.read(size)
|
|
||||||
|
|
||||||
if self.decompressor.unconsumed_tail:
|
|
||||||
data = self.decompressor.unconsumed_tail
|
|
||||||
else:
|
|
||||||
data = self.sslobj.read(8192)
|
|
||||||
|
|
||||||
return self.decompressor.decompress(data, size)
|
|
||||||
|
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
"""send(data)
|
"""send(data)
|
||||||
Send 'data' to remote."""
|
Send 'data' to remote."""
|
||||||
|
|
||||||
if self.compressor is not None:
|
|
||||||
data = self.compressor.compress(data)
|
|
||||||
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
|
||||||
|
|
||||||
# NB: socket.ssl needs a "sendall" method to match socket objects.
|
# NB: socket.ssl needs a "sendall" method to match socket objects.
|
||||||
bytes = len(data)
|
bytes = len(data)
|
||||||
while bytes > 0:
|
while bytes > 0:
|
||||||
@ -1800,24 +1736,12 @@ class IMAP4_stream(IMAP4):
|
|||||||
def read(self, size):
|
def read(self, size):
|
||||||
"""Read 'size' bytes from remote."""
|
"""Read 'size' bytes from remote."""
|
||||||
|
|
||||||
if self.decompressor is None:
|
return os.read(self.read_fd, size)
|
||||||
return os.read(self.read_fd, size)
|
|
||||||
|
|
||||||
if self.decompressor.unconsumed_tail:
|
|
||||||
data = self.decompressor.unconsumed_tail
|
|
||||||
else:
|
|
||||||
data = os.read(self.read_fd, 8192)
|
|
||||||
|
|
||||||
return self.decompressor.decompress(data, size)
|
|
||||||
|
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
"""Send data to remote."""
|
"""Send data to remote."""
|
||||||
|
|
||||||
if self.compressor is not None:
|
|
||||||
data = self.compressor.compress(data)
|
|
||||||
data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
|
|
||||||
|
|
||||||
self.writefile.write(data)
|
self.writefile.write(data)
|
||||||
self.writefile.flush()
|
self.writefile.flush()
|
||||||
|
|
||||||
@ -1996,7 +1920,7 @@ if __name__ == '__main__':
|
|||||||
import getopt, getpass
|
import getopt, getpass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
optlist, args = getopt.getopt(sys.argv[1:], 'd:l:s:p:v')
|
optlist, args = getopt.getopt(sys.argv[1:], 'd:l:s:p:')
|
||||||
except getopt.error, val:
|
except getopt.error, val:
|
||||||
optlist, args = (), ()
|
optlist, args = (), ()
|
||||||
|
|
||||||
@ -2014,9 +1938,6 @@ if __name__ == '__main__':
|
|||||||
elif opt == '-s':
|
elif opt == '-s':
|
||||||
stream_command = val
|
stream_command = val
|
||||||
if not args: args = (stream_command,)
|
if not args: args = (stream_command,)
|
||||||
elif opt == '-v':
|
|
||||||
print __version__
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if not args: args = ('',)
|
if not args: args = ('',)
|
||||||
if not port: port = (keyfile is not None) and IMAP4_SSL_PORT or IMAP4_PORT
|
if not port: port = (keyfile is not None) and IMAP4_SSL_PORT or IMAP4_PORT
|
||||||
@ -2026,7 +1947,7 @@ if __name__ == '__main__':
|
|||||||
USER = getpass.getuser()
|
USER = getpass.getuser()
|
||||||
|
|
||||||
test_mesg = 'From: %(user)s@localhost%(lf)sSubject: IMAP4 test%(lf)s%(lf)s%(data)s' \
|
test_mesg = 'From: %(user)s@localhost%(lf)sSubject: IMAP4 test%(lf)s%(lf)s%(data)s' \
|
||||||
% {'user':USER, 'lf':'\n', 'data':open(__file__).read()}
|
% {'user':USER, 'lf':'\n', 'data':open(__file__).read()}
|
||||||
test_seq1 = [
|
test_seq1 = [
|
||||||
('list', ('""', '%')),
|
('list', ('""', '%')),
|
||||||
('create', ('/tmp/imaplib2_test.0',)),
|
('create', ('/tmp/imaplib2_test.0',)),
|
||||||
@ -2107,8 +2028,6 @@ if __name__ == '__main__':
|
|||||||
test_seq1.insert(0, ('login', (USER, PASSWD)))
|
test_seq1.insert(0, ('login', (USER, PASSWD)))
|
||||||
M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
|
M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
|
||||||
M._mesg('CAPABILITIES = %r' % (M.capabilities,))
|
M._mesg('CAPABILITIES = %r' % (M.capabilities,))
|
||||||
if 'COMPRESS=DEFLATE' in M.capabilities:
|
|
||||||
M.enable_compression()
|
|
||||||
|
|
||||||
for cmd,args in test_seq1:
|
for cmd,args in test_seq1:
|
||||||
run(cmd, args, cb=1)
|
run(cmd, args, cb=1)
|
||||||
|
Loading…
Reference in New Issue
Block a user