[imaplib2 removal] Revert "use latest version of imaplib2"

This reverts commit fadbd38ef9.
This commit is contained in:
John Goerzen 2009-08-12 14:49:50 -05:00
parent 3869af9e0b
commit 36e0971adb

View File

@ -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,
@ -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)