OfflineIMAP: upgrade to 6.3.4
- removed applied upstream patch; - added patch for MANUAL.rst that eliminates RST -> HTML translation error. Relevant changelog entries since 6.3.3: OfflineIMAP v6.3.4 (2011-08-10) =============================== * CHANGE: Handle when UID can't be found on saved messages. OfflineIMAP v6.3.4-rc4 (2011-07-27) =================================== * CHANGE: Manual improved. OfflineIMAP v6.3.4-rc3 (2011-07-07) =================================== * NEW FEATURE: Added StartTLS support, it will automatically be used if the server supports it. * BUG FIX: We protect more robustly against asking for inexistent messages from the IMAP server, when someone else deletes or moves messages while we sync. OfflineIMAP v6.3.4-rc2 (2011-06-15) =================================== * NEW FEATURE: Implement experimental IDLE feature. * CHANGE: Maildirs use less memory while syncing. * BUG FIX: Saving to Maildirs now checks for file existence without race conditions. * BUG FIX: A bug in the underlying imap library has been fixed that could potentially lead to data loss if the server interrupted responses with unexpected but legal server status responses. This would mainly occur in folders with many thousands of emails. Upgrading from the previous release is strongly recommended. NOTE: the latter bug fix was already integrated into FreeBSD port version 6.3.3_1. OfflineIMAP v6.3.4-rc1 (2011-05-16) =================================== * NEW FEATURE: Begin sphinx-based documentation for the code. * NEW FEATURE: Enable 1-way synchronization by settting a [Repository ...] to readonly = True. When e.g. using offlineimap for backup purposes you can thus make sure that no changes in your backup trickle back into the main IMAP server. * NEW FEATURE: Optional: experimental SQLite-based backend for the LocalStatus cache. Plain text remains the default. * CHANGE: Start a enhanced error handling background system. This is designed to not stop a whole sync process on all errors (not much used, yet). * CHANGE: Documentation improvements: the FAQ wins new entries and add a new HACKING file for developers. * CHANGE: Lot of code cleanups. * CHANGE: Reduced our sync logic from 4 passes to 3 passes (integrating upload of "new" and "existing" messages into one function). This should result in a slight speedup. * CHANGE: No whitespace is stripped from comma-separated arguments passed via the -f option. * CHANGE: Give more detailed error when encountering a corrupt UID mapping file. * BUG FIX: Drop connection if synchronization failed. This is needed if resuming the system from suspend mode gives a wrong connection. * BUG FIX: Fix the offlineimap crash when invoking debug option 'thread'. * BUG FIX: Make 'thread' command line option work. PR: ports/159815 Approved-by: sergei (maintainer timeout) Feature-safe: yes
This commit is contained in:
parent
c5c68361eb
commit
94b08c8e01
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=281639
5 changed files with 35 additions and 869 deletions
|
@ -6,13 +6,12 @@
|
|||
#
|
||||
|
||||
PORTNAME= offlineimap
|
||||
DISTVERSION= 6.3.3
|
||||
PORTREVISION= 1
|
||||
DISTVERSION= 6.3.4
|
||||
CATEGORIES= mail python
|
||||
MASTER_SITES= http://download.github.com/ \
|
||||
http://dist.codelabs.ru/fbsd/offlineimap/ \
|
||||
LOCAL/rea/offlineimap
|
||||
DISTNAME= ${GITHUB_USER}-${PORTNAME}-v${DISTVERSION}-0-g3b09695
|
||||
DISTNAME= ${GITHUB_USER}-${PORTNAME}-v${DISTVERSION}-${GITHUB_VER_SUFX}
|
||||
|
||||
MAINTAINER= sergei@FreeBSD.org
|
||||
COMMENT= Powerful IMAP/Maildir synchronization and reader support
|
||||
|
@ -24,10 +23,12 @@ LICENSE_FILE_GPLv2=${WRKSRC}/COPYING
|
|||
|
||||
OPTIONS= HTMLDOCS "Generate HTML documentation" Off
|
||||
|
||||
WRKSRC= ${WRKDIR}/${GITHUB_USER}-${PORTNAME}-cf325d5
|
||||
WRKSRC= ${WRKDIR}/${GITHUB_USER}-${PORTNAME}-${GITHUB_SRC_SUFX}
|
||||
SUB_FILES= pkg-message
|
||||
|
||||
GITHUB_USER= nicolas33
|
||||
GITHUB_VER_SUFX= 0-g61e50b3
|
||||
GITHUB_SRC_SUFX= 94450e9
|
||||
|
||||
USE_PYTHON= yes
|
||||
USE_PYDISTUTILS= yes
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
SHA256 (nicolas33-offlineimap-v6.3.3-0-g3b09695.tar.gz) = 762591144f13423da6020ba840e2eb216c4ed45839f1881ac90d9e3dd57f4eca
|
||||
SIZE (nicolas33-offlineimap-v6.3.3-0-g3b09695.tar.gz) = 117153
|
||||
SHA256 (nicolas33-offlineimap-v6.3.4-0-g61e50b3.tar.gz) = a2ac69a58605338e971658e930e095e4c2611383837a9378b88c0749cd374333
|
||||
SIZE (nicolas33-offlineimap-v6.3.4-0-g61e50b3.tar.gz) = 137313
|
||||
|
|
|
@ -1,863 +0,0 @@
|
|||
commit 520e39d35536172d03b22d012cf4d8828687f2ff
|
||||
Author: Sebastian Spaeth <Sebastian@SSpaeth.de>
|
||||
Date: Thu Jun 9 15:26:14 2011 +0200
|
||||
|
||||
Update imaplib2 to 2.24
|
||||
|
||||
In some cases we had offlineimap trying to delete emails that shouldn't
|
||||
be deleted. E.g. https://bugzilla.redhat.com/show_bug.cgi?id=708898.
|
||||
|
||||
It turns out that imaplib2 does not like FETCH responses that are
|
||||
interrupted by other unsolicited server responses, e.g.
|
||||
|
||||
* OK Searched 43% of the mailbox, ETA 0:12\r\n
|
||||
|
||||
Bump imaplib2 to a version that can cope with these (legal) responses by
|
||||
the IMAP server.
|
||||
|
||||
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
|
||||
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
|
||||
|
||||
diff --git offlineimap/imaplib2.py offlineimap/imaplib2.py
|
||||
index be34025..ec6cd0d 100644
|
||||
--- offlineimap/imaplib2.py
|
||||
+++ offlineimap/imaplib2.py
|
||||
@@ -17,9 +17,9 @@ Public functions: Internaldate2Time
|
||||
__all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream",
|
||||
"Internaldate2Time", "ParseFlags", "Time2Internaldate")
|
||||
|
||||
-__version__ = "2.22"
|
||||
+__version__ = "2.24"
|
||||
__release__ = "2"
|
||||
-__revision__ = "22"
|
||||
+__revision__ = "24"
|
||||
__credits__ = """
|
||||
Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998.
|
||||
String method conversion by ESR, February 2001.
|
||||
@@ -36,9 +36,11 @@ Improved untagged responses handling suggested by Dave Baggett <dave@baggett.org
|
||||
Improved thread naming, and 0 read detection contributed by Grant Edwards <grant.b.edwards@gmail.com> June 2010.
|
||||
Improved timeout handling contributed by Ivan Vovnenko <ivovnenko@gmail.com> October 2010.
|
||||
Timeout handling further improved by Ethan Glasser-Camp <glasse@cs.rpi.edu> December 2010.
|
||||
-Time2Internaldate() patch to match RFC2060 specification of English month names from http://bugs.python.org/issue11024 March 2011."""
|
||||
+Time2Internaldate() patch to match RFC2060 specification of English month names from bugs.python.org/issue11024 March 2011.
|
||||
+starttls() bug fixed with the help of Sebastian Spaeth <sebastian@sspaeth.de> April 2011.
|
||||
+Threads now set the "daemon" flag (suggested by offlineimap-project)."""
|
||||
__author__ = "Piers Lauder <piers@janeelix.com>"
|
||||
-__URL__ = "http://janeelix.com/piers/python/imaplib2"
|
||||
+__URL__ = "http://imaplib2.sourceforge.net"
|
||||
__license__ = "Python License"
|
||||
|
||||
import binascii, errno, os, Queue, random, re, select, socket, sys, time, threading, zlib
|
||||
@@ -55,6 +57,9 @@ IMAP4_SSL_PORT = 993
|
||||
IDLE_TIMEOUT_RESPONSE = '* IDLE TIMEOUT\r\n'
|
||||
IDLE_TIMEOUT = 60*29 # Don't stay in IDLE state longer
|
||||
READ_POLL_TIMEOUT = 30 # Without this timeout interrupted network connections can hang reader
|
||||
+READ_SIZE = 32768 # Consume all available in socket
|
||||
+
|
||||
+DFLT_DEBUG_BUF_LVL = 3 # Level above which the logging output goes directly to stderr
|
||||
|
||||
AllowedVersions = ('IMAP4REV1', 'IMAP4') # Most recent first
|
||||
|
||||
@@ -133,6 +138,7 @@ class Request(object):
|
||||
"""Private class to represent a request awaiting response."""
|
||||
|
||||
def __init__(self, parent, name=None, callback=None, cb_arg=None):
|
||||
+ self.parent = parent
|
||||
self.name = name
|
||||
self.callback = callback # Function called to process result
|
||||
self.callback_arg = cb_arg # Optional arg passed to "callback"
|
||||
@@ -147,12 +153,16 @@ class Request(object):
|
||||
|
||||
|
||||
def abort(self, typ, val):
|
||||
+ """Called whenever we abort a command
|
||||
+
|
||||
+ Sets self.aborted reason, and deliver()s nothing"""
|
||||
self.aborted = (typ, val)
|
||||
self.deliver(None)
|
||||
|
||||
|
||||
def get_response(self, exc_fmt=None):
|
||||
self.callback = None
|
||||
+ if __debug__: self.parent._log(3, '%s:%s.ready.wait' % (self.name, self.tag))
|
||||
self.ready.wait()
|
||||
|
||||
if self.aborted is not None:
|
||||
@@ -171,6 +181,7 @@ class Request(object):
|
||||
|
||||
self.response = response
|
||||
self.ready.set()
|
||||
+ if __debug__: self.parent._log(3, '%s:%s.ready.set' % (self.name, self.tag))
|
||||
|
||||
|
||||
|
||||
@@ -180,14 +191,15 @@ class IMAP4(object):
|
||||
"""Threaded IMAP4 client class.
|
||||
|
||||
Instantiate with:
|
||||
- IMAP4(host=None, port=None, debug=None, debug_file=None, identifier=None, timeout=None)
|
||||
+ IMAP4(host=None, port=None, debug=None, debug_file=None, identifier=None, timeout=None, debug_buf_lvl=None)
|
||||
|
||||
- host - host's name (default: localhost);
|
||||
- port - port number (default: standard IMAP4 port);
|
||||
- debug - debug level (default: 0 - no debug);
|
||||
- debug_file - debug stream (default: sys.stderr);
|
||||
- identifier - thread identifier prefix (default: host);
|
||||
- timeout - timeout in seconds when expecting a command response (default: no timeout).
|
||||
+ host - host's name (default: localhost);
|
||||
+ port - port number (default: standard IMAP4 port);
|
||||
+ debug - debug level (default: 0 - no debug);
|
||||
+ debug_file - debug stream (default: sys.stderr);
|
||||
+ identifier - thread identifier prefix (default: host);
|
||||
+ timeout - timeout in seconds when expecting a command response (default: no timeout),
|
||||
+ debug_buf_lvl - debug level at which buffering is turned off.
|
||||
|
||||
All IMAP4rev1 commands are supported by methods of the same name.
|
||||
|
||||
@@ -267,7 +279,7 @@ class IMAP4(object):
|
||||
untagged_status_cre = re.compile(r'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?')
|
||||
|
||||
|
||||
- def __init__(self, host=None, port=None, debug=None, debug_file=None, identifier=None, timeout=None):
|
||||
+ def __init__(self, host=None, port=None, debug=None, debug_file=None, identifier=None, timeout=None, debug_buf_lvl=None):
|
||||
|
||||
self.state = NONAUTH # IMAP4 protocol state
|
||||
self.literal = None # A literal argument to a command
|
||||
@@ -295,7 +307,7 @@ class IMAP4(object):
|
||||
+ self.tagpre
|
||||
+ r'\d+) (?P<type>[A-Z]+) (?P<data>.*)')
|
||||
|
||||
- if __debug__: self._init_debug(debug, debug_file)
|
||||
+ if __debug__: self._init_debug(debug, debug_file, debug_buf_lvl)
|
||||
|
||||
self.resp_timeout = timeout # Timeout waiting for command response
|
||||
|
||||
@@ -303,6 +315,7 @@ class IMAP4(object):
|
||||
self.read_poll_timeout = timeout
|
||||
else:
|
||||
self.read_poll_timeout = READ_POLL_TIMEOUT
|
||||
+ self.read_size = READ_SIZE
|
||||
|
||||
# Open socket to server.
|
||||
|
||||
@@ -321,20 +334,26 @@ class IMAP4(object):
|
||||
if self.identifier:
|
||||
self.identifier += ' '
|
||||
|
||||
- self.Terminate = False
|
||||
+ self.Terminate = self.TerminateReader = False
|
||||
|
||||
self.state_change_free = threading.Event()
|
||||
self.state_change_pending = threading.Lock()
|
||||
self.commands_lock = threading.Lock()
|
||||
+ """commands_lock prevents self.untagged_responses to be
|
||||
+ manipulated concurrently"""
|
||||
+ self.idle_lock = threading.Lock()
|
||||
|
||||
self.ouq = Queue.Queue(10)
|
||||
self.inq = Queue.Queue()
|
||||
|
||||
self.wrth = threading.Thread(target=self._writer)
|
||||
+ self.wrth.setDaemon(True)
|
||||
self.wrth.start()
|
||||
self.rdth = threading.Thread(target=self._reader)
|
||||
+ self.rdth.setDaemon(True)
|
||||
self.rdth.start()
|
||||
self.inth = threading.Thread(target=self._handler)
|
||||
+ self.inth.setDaemon(True)
|
||||
self.inth.start()
|
||||
|
||||
# Get server welcome message,
|
||||
@@ -387,8 +406,8 @@ class IMAP4(object):
|
||||
This connection will be used by the routines:
|
||||
read, send, shutdown, socket."""
|
||||
|
||||
- self.host = host is not None and host or ''
|
||||
- self.port = port is not None and port or IMAP4_PORT
|
||||
+ self.host = self._choose_nonull_or_dflt('', host)
|
||||
+ self.port = self._choose_nonull_or_dflt(IMAP4_PORT, port)
|
||||
self.sock = self.open_socket()
|
||||
self.read_fd = self.sock.fileno()
|
||||
|
||||
@@ -490,7 +509,7 @@ class IMAP4(object):
|
||||
self.start_compressing()
|
||||
if __debug__: self._log(1, 'Enabled COMPRESS=DEFLATE')
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def pop_untagged_responses(self):
|
||||
@@ -515,16 +534,9 @@ class IMAP4(object):
|
||||
else list of RECENT responses, most recent last."""
|
||||
|
||||
name = 'RECENT'
|
||||
-
|
||||
- data = []
|
||||
- while True:
|
||||
- dat = self._get_untagged_response(name)
|
||||
- if not dat:
|
||||
- break
|
||||
- data += dat
|
||||
-
|
||||
- if data:
|
||||
- return self._deliver_dat(name, data, kw)
|
||||
+ typ, dat = self._untagged_response(None, [None], name)
|
||||
+ if dat != [None]:
|
||||
+ return self._deliver_dat(typ, dat, kw)
|
||||
kw['untagged_response'] = name
|
||||
return self.noop(**kw) # Prod server for response
|
||||
|
||||
@@ -564,7 +576,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command(name, mailbox, flags, date_time, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def authenticate(self, mechanism, authobject, **kw):
|
||||
@@ -592,7 +604,7 @@ class IMAP4(object):
|
||||
self.state = AUTH
|
||||
if __debug__: self._log(1, 'state => AUTH')
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
return self._deliver_dat(typ, dat, kw)
|
||||
|
||||
|
||||
@@ -626,7 +638,7 @@ class IMAP4(object):
|
||||
finally:
|
||||
self.state = AUTH
|
||||
if __debug__: self._log(1, 'state => AUTH')
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
return self._deliver_dat(typ, dat, kw)
|
||||
|
||||
|
||||
@@ -753,7 +765,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command(name, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def list(self, directory='""', pattern='*', **kw):
|
||||
@@ -782,7 +794,7 @@ class IMAP4(object):
|
||||
self.state = AUTH
|
||||
if __debug__: self._log(1, 'state => AUTH')
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
return self._deliver_dat(typ, dat, kw)
|
||||
|
||||
|
||||
@@ -810,14 +822,15 @@ class IMAP4(object):
|
||||
if __debug__: self._log(1, 'state => LOGOUT')
|
||||
|
||||
try:
|
||||
- typ, dat = self._simple_command('LOGOUT')
|
||||
- except:
|
||||
- typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]]
|
||||
- if __debug__: self._log(1, dat)
|
||||
-
|
||||
- self._close_threads()
|
||||
+ try:
|
||||
+ typ, dat = self._simple_command('LOGOUT')
|
||||
+ except:
|
||||
+ typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]]
|
||||
+ if __debug__: self._log(1, dat)
|
||||
|
||||
- self.state_change_pending.release()
|
||||
+ self._close_threads()
|
||||
+ finally:
|
||||
+ self._release_state_change()
|
||||
|
||||
if __debug__: self._log(1, 'connection closed')
|
||||
|
||||
@@ -882,7 +895,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command('PROXYAUTH', user, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def rename(self, oldmailbox, newmailbox, **kw):
|
||||
@@ -937,7 +950,7 @@ class IMAP4(object):
|
||||
self.state = SELECTED
|
||||
if __debug__: self._log(1, 'state => SELECTED')
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
if self._get_untagged_response('READ-ONLY', leave=True) and not readonly:
|
||||
if __debug__: self._dump_ur(1)
|
||||
@@ -953,7 +966,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command('SETACL', mailbox, who, what, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def setannotation(self, *args, **kw):
|
||||
@@ -972,7 +985,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command('SETQUOTA', root, limits, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def sort(self, sort_criteria, charset, *search_criteria, **kw):
|
||||
@@ -998,23 +1011,46 @@ class IMAP4(object):
|
||||
if hasattr(self, '_tls_established') and self._tls_established:
|
||||
raise self.abort('TLS session already established')
|
||||
|
||||
+ # Must now shutdown reader thread after next response, and restart after changing read_fd
|
||||
+
|
||||
+ self.read_size = 1 # Don't consume TLS handshake
|
||||
+ self.TerminateReader = True
|
||||
+
|
||||
try:
|
||||
typ, dat = self._simple_command(name)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
+ self.rdth.join()
|
||||
+ self.TerminateReader = False
|
||||
+ self.read_size = READ_SIZE
|
||||
+
|
||||
+ if typ != 'OK':
|
||||
+ # Restart reader thread and error
|
||||
+ self.rdth = threading.Thread(target=self._reader)
|
||||
+ self.rdth.setDaemon(True)
|
||||
+ self.rdth.start()
|
||||
+ raise self.error("Couldn't establish TLS session: %s" % dat)
|
||||
+
|
||||
+ try:
|
||||
+ try:
|
||||
+ import ssl
|
||||
+ self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
|
||||
+ except ImportError:
|
||||
+ self.sock = socket.ssl(self.sock, keyfile, certfile)
|
||||
|
||||
- if typ == 'OK':
|
||||
- import ssl
|
||||
- self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
|
||||
self.read_fd = self.sock.fileno()
|
||||
+ finally:
|
||||
+ # Restart reader thread
|
||||
+ self.rdth = threading.Thread(target=self._reader)
|
||||
+ self.rdth.setDaemon(True)
|
||||
+ self.rdth.start()
|
||||
|
||||
- typ, dat = self.capability()
|
||||
- if dat == [None]:
|
||||
- raise self.error('no CAPABILITY response from server')
|
||||
- self.capabilities = tuple(dat[-1].upper().split())
|
||||
- self._tls_established = True
|
||||
- else:
|
||||
- raise self.error("Couldn't establish TLS session: %s" % dat)
|
||||
+ typ, dat = self.capability()
|
||||
+ if dat == [None]:
|
||||
+ raise self.error('no CAPABILITY response from server')
|
||||
+ self.capabilities = tuple(dat[-1].upper().split())
|
||||
+
|
||||
+ self._tls_established = True
|
||||
|
||||
typ, dat = self._untagged_response(typ, dat, name)
|
||||
return self._deliver_dat(typ, dat, kw)
|
||||
@@ -1046,7 +1082,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command('SUBSCRIBE', mailbox, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def thread(self, threading_algorithm, charset, *search_criteria, **kw):
|
||||
@@ -1081,7 +1117,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command('UNSUBSCRIBE', mailbox, **kw)
|
||||
finally:
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
def xatom(self, name, *args, **kw):
|
||||
@@ -1096,8 +1132,7 @@ class IMAP4(object):
|
||||
try:
|
||||
return self._simple_command(name, *args, **kw)
|
||||
finally:
|
||||
- if self.state_change_pending.locked():
|
||||
- self.state_change_pending.release()
|
||||
+ self._release_state_change()
|
||||
|
||||
|
||||
|
||||
@@ -1105,34 +1140,29 @@ class IMAP4(object):
|
||||
|
||||
|
||||
def _append_untagged(self, typ, dat):
|
||||
+ """Append new untagged response
|
||||
|
||||
- # Append new 'dat' to end of last untagged response if same 'typ',
|
||||
- # else append new response.
|
||||
-
|
||||
+ Append new 'dat' to end of last untagged response if same 'typ',
|
||||
+ else append new response."""
|
||||
if dat is None: dat = ''
|
||||
+ ur_data = []
|
||||
|
||||
- self.commands_lock.acquire()
|
||||
+ self.commands_lock.acquire() # protect untagged_responses
|
||||
|
||||
- if self.untagged_responses:
|
||||
- urn, urd = self.untagged_responses[-1]
|
||||
- if urn != typ:
|
||||
- urd = None
|
||||
+ if self.untagged_responses and self.untagged_responses[-1][0] == typ:
|
||||
+ # last respons is of type 'typ', get ur_data for appending
|
||||
+ ur_data = self.untagged_responses[-1][1]
|
||||
else:
|
||||
- urd = None
|
||||
-
|
||||
- if urd is None:
|
||||
- urd = []
|
||||
- self.untagged_responses.append([typ, urd])
|
||||
-
|
||||
- urd.append(dat)
|
||||
+ # need to create new untagged response of this type
|
||||
+ self.untagged_responses.append([typ, ur_data])
|
||||
|
||||
+ ur_data.append(dat)
|
||||
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 += ["%s"]' % (typ, len(ur_data)-1, dat))
|
||||
|
||||
|
||||
def _check_bye(self):
|
||||
-
|
||||
+ """raise Exception if untagged responses contains a 'BYE'"""
|
||||
bye = self._get_untagged_response('BYE', leave=True)
|
||||
if bye:
|
||||
raise self.abort(bye[-1])
|
||||
@@ -1152,6 +1182,16 @@ class IMAP4(object):
|
||||
return self._quote(arg)
|
||||
|
||||
|
||||
+ def _choose_nonull_or_dflt(self, dflt, *args):
|
||||
+ dflttyp = type(dflt)
|
||||
+ for arg in args:
|
||||
+ if arg is not None:
|
||||
+ if type(arg) is dflttyp:
|
||||
+ return arg
|
||||
+ if __debug__: self._log(1, 'bad arg type is %s, expecting %s' % (type(arg), dflttyp))
|
||||
+ return dflt
|
||||
+
|
||||
+
|
||||
def _command(self, name, *args, **kw):
|
||||
|
||||
if Commands[name][CMD_VAL_ASYNC]:
|
||||
@@ -1161,12 +1201,14 @@ class IMAP4(object):
|
||||
|
||||
if __debug__: self._log(1, '[%s] %s %s' % (cmdtyp, name, args))
|
||||
|
||||
+ if __debug__: self._log(3, 'state_change_pending.acquire')
|
||||
self.state_change_pending.acquire()
|
||||
|
||||
self._end_idle()
|
||||
|
||||
if cmdtyp == 'async':
|
||||
self.state_change_pending.release()
|
||||
+ if __debug__: self._log(3, 'state_change_pending.release')
|
||||
else:
|
||||
# Need to wait for all async commands to complete
|
||||
self._check_bye()
|
||||
@@ -1178,9 +1220,9 @@ class IMAP4(object):
|
||||
need_event = False
|
||||
self.commands_lock.release()
|
||||
if need_event:
|
||||
- if __debug__: self._log(4, '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()
|
||||
- if __debug__: self._log(4, '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]:
|
||||
self.literal = None
|
||||
@@ -1232,7 +1274,7 @@ class IMAP4(object):
|
||||
# Wait for continuation response
|
||||
|
||||
ok, data = crqb.get_response('command: %s => %%s' % name)
|
||||
- if __debug__: self._log(3, 'continuation => %s, %s' % (ok, data))
|
||||
+ if __debug__: self._log(4, 'continuation => %s, %s' % (ok, data))
|
||||
|
||||
# NO/BAD response?
|
||||
|
||||
@@ -1316,18 +1358,25 @@ class IMAP4(object):
|
||||
|
||||
def _end_idle(self):
|
||||
|
||||
+ self.idle_lock.acquire()
|
||||
irqb = self.idle_rqb
|
||||
if irqb is None:
|
||||
+ self.idle_lock.release()
|
||||
return
|
||||
self.idle_rqb = None
|
||||
self.idle_timeout = None
|
||||
+ self.idle_lock.release()
|
||||
irqb.data = 'DONE%s' % CRLF
|
||||
self.ouq.put(irqb)
|
||||
if __debug__: self._log(2, 'server IDLE finished')
|
||||
|
||||
|
||||
def _get_untagged_response(self, name, leave=False):
|
||||
+ """Return an untagged response of type 'name'
|
||||
|
||||
+ :param leave: If leave (default: False) is True, we keep the
|
||||
+ fetched responsem; otherwise it will be deleted. Returns
|
||||
+ None if no such response found."""
|
||||
self.commands_lock.acquire()
|
||||
|
||||
for i, (typ, dat) in enumerate(self.untagged_responses):
|
||||
@@ -1434,7 +1483,7 @@ class IMAP4(object):
|
||||
|
||||
self._append_untagged(typ, dat)
|
||||
|
||||
- if typ != 'OK':
|
||||
+ if typ != 'OK': # NO, BYE, IDLE
|
||||
self._end_idle()
|
||||
|
||||
# Bracketed response information?
|
||||
@@ -1460,14 +1509,22 @@ class IMAP4(object):
|
||||
return '"%s"' % arg.replace('\\', '\\\\').replace('"', '\\"')
|
||||
|
||||
|
||||
+ def _release_state_change(self):
|
||||
+
|
||||
+ if self.state_change_pending.locked():
|
||||
+ self.state_change_pending.release()
|
||||
+ if __debug__: self._log(3, 'state_change_pending.release')
|
||||
+
|
||||
+
|
||||
def _request_pop(self, name, data):
|
||||
|
||||
- if __debug__: self._log(4, '_request_pop(%s, %s)' % (name, data))
|
||||
self.commands_lock.acquire()
|
||||
rqb = self.tagged_commands.pop(name)
|
||||
if not self.tagged_commands:
|
||||
+ if __debug__: self._log(3, '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)
|
||||
|
||||
|
||||
@@ -1479,7 +1536,7 @@ class IMAP4(object):
|
||||
tag = rqb.tag
|
||||
self.tagged_commands[tag] = rqb
|
||||
self.commands_lock.release()
|
||||
- if __debug__: self._log(4, '_request_push(%s, %s, %s)' % (tag, name, `kw`))
|
||||
+ if __debug__: self._log(4, '_request_push(%s, %s, %s) = %s' % (tag, name, `kw`, rqb.tag))
|
||||
return rqb
|
||||
|
||||
|
||||
@@ -1493,12 +1550,28 @@ class IMAP4(object):
|
||||
|
||||
|
||||
def _untagged_response(self, typ, dat, name):
|
||||
-
|
||||
+ """Returns an untagged response for 'name' of type 'typ'
|
||||
+
|
||||
+ :param typ: 'OK, 'NO', etc... which will be used for the type of
|
||||
+ the response.
|
||||
+ :param dat: The fallback data to be used in case `typ` is
|
||||
+ 'NO'. Otherwise the data from the existing untagged
|
||||
+ responses will be searched for data to be returned. If there
|
||||
+ is no such response, we return `[None]` as data.
|
||||
+ :param name: The name of the response.
|
||||
+ :returns: (typ, data)
|
||||
+ """
|
||||
if typ == 'NO':
|
||||
return typ, dat
|
||||
data = self._get_untagged_response(name)
|
||||
if not data:
|
||||
return typ, [None]
|
||||
+ while True:
|
||||
+ dat = self._get_untagged_response(name)
|
||||
+ if not dat:
|
||||
+ break
|
||||
+ data += dat
|
||||
+ if __debug__: self._log(4, '_untagged_response(%s, ?, %s) => %s' % (typ, name, data))
|
||||
return typ, data
|
||||
|
||||
|
||||
@@ -1588,6 +1661,7 @@ class IMAP4(object):
|
||||
rqb.abort(typ, val)
|
||||
self.state_change_free.set()
|
||||
self.commands_lock.release()
|
||||
+ if __debug__: self._log(3, 'state_change_free.set')
|
||||
|
||||
if __debug__: self._log(1, 'finished')
|
||||
|
||||
@@ -1615,9 +1689,10 @@ class IMAP4(object):
|
||||
poll.register(self.read_fd, select.POLLIN)
|
||||
|
||||
rxzero = 0
|
||||
+ terminate = False
|
||||
read_poll_timeout = self.read_poll_timeout * 1000 # poll() timeout is in millisecs
|
||||
|
||||
- while not self.Terminate:
|
||||
+ while not (terminate or self.Terminate):
|
||||
if self.state == LOGOUT:
|
||||
timeout = 1
|
||||
else:
|
||||
@@ -1631,7 +1706,7 @@ class IMAP4(object):
|
||||
fd,state = r[0]
|
||||
|
||||
if state & select.POLLIN:
|
||||
- data = self.read(32768) # Drain ssl buffer if present
|
||||
+ data = self.read(self.read_size) # Drain ssl buffer if present
|
||||
start = 0
|
||||
dlen = len(data)
|
||||
if __debug__: self._log(5, 'rcvd %s' % dlen)
|
||||
@@ -1652,6 +1727,8 @@ class IMAP4(object):
|
||||
'', stop, line_part + data[start:stop]
|
||||
if __debug__: self._log(4, '< %s' % line)
|
||||
self.inq.put(line)
|
||||
+ if self.TerminateReader:
|
||||
+ terminate = True
|
||||
|
||||
if state & ~(select.POLLIN):
|
||||
raise IOError(poll_error(state))
|
||||
@@ -1682,20 +1759,20 @@ class IMAP4(object):
|
||||
line_part = ''
|
||||
|
||||
rxzero = 0
|
||||
- read_poll_timeout = self.read_poll_timeout
|
||||
+ terminate = False
|
||||
|
||||
- while not self.Terminate:
|
||||
+ while not (terminate or self.Terminate):
|
||||
if self.state == LOGOUT:
|
||||
timeout = 1
|
||||
else:
|
||||
- timeout = read_poll_timeout
|
||||
+ timeout = self.read_poll_timeout
|
||||
try:
|
||||
r,w,e = select.select([self.read_fd], [], [], timeout)
|
||||
if __debug__: self._log(5, 'select => %s, %s, %s' % (r,w,e))
|
||||
if not r: # Timeout
|
||||
continue
|
||||
|
||||
- data = self.read(32768) # Drain ssl buffer if present
|
||||
+ data = self.read(self.read_size) # Drain ssl buffer if present
|
||||
start = 0
|
||||
dlen = len(data)
|
||||
if __debug__: self._log(5, 'rcvd %s' % dlen)
|
||||
@@ -1716,6 +1793,8 @@ class IMAP4(object):
|
||||
'', stop, line_part + data[start:stop]
|
||||
if __debug__: self._log(4, '< %s' % line)
|
||||
self.inq.put(line)
|
||||
+ if self.TerminateReader:
|
||||
+ terminate = True
|
||||
except:
|
||||
reason = 'socket error: %s - %s' % sys.exc_info()[:2]
|
||||
if __debug__:
|
||||
@@ -1766,9 +1845,10 @@ class IMAP4(object):
|
||||
|
||||
if __debug__:
|
||||
|
||||
- def _init_debug(self, debug=None, debug_file=None):
|
||||
- self.debug = debug is not None and debug or Debug is not None and Debug or 0
|
||||
- self.debug_file = debug_file is not None and debug_file or sys.stderr
|
||||
+ def _init_debug(self, debug=None, debug_file=None, debug_buf_lvl=None):
|
||||
+ self.debug = self._choose_nonull_or_dflt(0, debug, Debug)
|
||||
+ self.debug_file = self._choose_nonull_or_dflt(sys.stderr, debug_file)
|
||||
+ self.debug_buf_lvl = self._choose_nonull_or_dflt(DFLT_DEBUG_BUF_LVL, debug_buf_lvl)
|
||||
|
||||
self.debug_lock = threading.Lock()
|
||||
self._cmd_log_len = 20
|
||||
@@ -1776,7 +1856,7 @@ class IMAP4(object):
|
||||
self._cmd_log = {} # Last `_cmd_log_len' interactions
|
||||
if self.debug:
|
||||
self._mesg('imaplib2 version %s' % __version__)
|
||||
- self._mesg('imaplib2 debug level %s' % self.debug)
|
||||
+ self._mesg('imaplib2 debug level %s, buffer level %s' % (self.debug, self.debug_buf_lvl))
|
||||
|
||||
|
||||
def _dump_ur(self, lvl):
|
||||
@@ -1803,11 +1883,12 @@ class IMAP4(object):
|
||||
|
||||
tn = threading.currentThread().getName()
|
||||
|
||||
- if lvl == 1 or self.debug >= 4:
|
||||
+ if lvl <= 1 or self.debug > self.debug_buf_lvl:
|
||||
self.debug_lock.acquire()
|
||||
self._mesg(line, tn)
|
||||
self.debug_lock.release()
|
||||
- return
|
||||
+ if lvl != 1:
|
||||
+ return
|
||||
|
||||
# Keep log of last `_cmd_log_len' interactions for debugging.
|
||||
self.debug_lock.acquire()
|
||||
@@ -1824,8 +1905,11 @@ class IMAP4(object):
|
||||
if tn is None:
|
||||
tn = threading.currentThread().getName()
|
||||
tm = time.strftime('%M:%S', time.localtime(secs))
|
||||
- self.debug_file.write(' %s.%02d %s %s\n' % (tm, (secs*100)%100, tn, s))
|
||||
- self.debug_file.flush()
|
||||
+ try:
|
||||
+ self.debug_file.write(' %s.%02d %s %s\n' % (tm, (secs*100)%100, tn, s))
|
||||
+ self.debug_file.flush()
|
||||
+ finally:
|
||||
+ pass
|
||||
|
||||
|
||||
def _print_log(self):
|
||||
@@ -1865,10 +1949,10 @@ class IMAP4_SSL(IMAP4):
|
||||
"""
|
||||
|
||||
|
||||
- def __init__(self, host=None, port=None, keyfile=None, certfile=None, debug=None, debug_file=None, identifier=None, timeout=None):
|
||||
+ def __init__(self, host=None, port=None, keyfile=None, certfile=None, debug=None, debug_file=None, identifier=None, timeout=None, debug_buf_lvl=None):
|
||||
self.keyfile = keyfile
|
||||
self.certfile = certfile
|
||||
- IMAP4.__init__(self, host, port, debug, debug_file, identifier, timeout)
|
||||
+ IMAP4.__init__(self, host, port, debug, debug_file, identifier, timeout, debug_buf_lvl)
|
||||
|
||||
|
||||
def open(self, host=None, port=None):
|
||||
@@ -1878,15 +1962,15 @@ class IMAP4_SSL(IMAP4):
|
||||
This connection will be used by the routines:
|
||||
read, send, shutdown, socket, ssl."""
|
||||
|
||||
- self.host = host is not None and host or ''
|
||||
- self.port = port is not None and port or IMAP4_SSL_PORT
|
||||
+ self.host = self._choose_nonull_or_dflt('', host)
|
||||
+ self.port = self._choose_nonull_or_dflt(IMAP4_SSL_PORT, port)
|
||||
self.sock = self.open_socket()
|
||||
|
||||
try:
|
||||
- import ssl
|
||||
- self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile)
|
||||
+ 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.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile)
|
||||
|
||||
self.read_fd = self.sock.fileno()
|
||||
|
||||
@@ -1949,14 +2033,14 @@ class IMAP4_stream(IMAP4):
|
||||
"""
|
||||
|
||||
|
||||
- def __init__(self, command, debug=None, debug_file=None, identifier=None, timeout=None):
|
||||
+ def __init__(self, command, debug=None, debug_file=None, identifier=None, timeout=None, debug_buf_lvl=None):
|
||||
self.command = command
|
||||
self.host = command
|
||||
self.port = None
|
||||
self.sock = None
|
||||
self.writefile, self.readfile = None, None
|
||||
self.read_fd = None
|
||||
- IMAP4.__init__(self, None, None, debug, debug_file, identifier, timeout)
|
||||
+ IMAP4.__init__(self, None, None, debug, debug_file, identifier, timeout, debug_buf_lvl)
|
||||
|
||||
|
||||
def open(self, host=None, port=None):
|
||||
@@ -2055,12 +2139,14 @@ class _IdleCont(object):
|
||||
|
||||
def __init__(self, parent, timeout):
|
||||
self.parent = parent
|
||||
- self.timeout = timeout is not None and timeout or IDLE_TIMEOUT
|
||||
+ self.timeout = parent._choose_nonull_or_dflt(IDLE_TIMEOUT, timeout)
|
||||
self.parent.idle_timeout = self.timeout + time.time()
|
||||
|
||||
def process(self, data, rqb):
|
||||
+ self.parent.idle_lock.acquire()
|
||||
self.parent.idle_rqb = rqb
|
||||
self.parent.idle_timeout = self.timeout + time.time()
|
||||
+ self.parent.idle_lock.release()
|
||||
if __debug__: self.parent._log(2, 'server IDLE started, timeout in %.2f secs' % self.timeout)
|
||||
return None
|
||||
|
||||
@@ -2175,10 +2261,11 @@ if __name__ == '__main__':
|
||||
except getopt.error, val:
|
||||
optlist, args = (), ()
|
||||
|
||||
- debug, port, stream_command, keyfile, certfile = (None,)*5
|
||||
+ debug, debug_buf_lvl, port, stream_command, keyfile, certfile = (None,)*6
|
||||
for opt,val in optlist:
|
||||
if opt == '-d':
|
||||
debug = int(val)
|
||||
+ debug_buf_lvl = debug - 1
|
||||
elif opt == '-l':
|
||||
try:
|
||||
keyfile,certfile = val.split(':')
|
||||
@@ -2235,31 +2322,33 @@ if __name__ == '__main__':
|
||||
cmd, args = cb_arg
|
||||
if error is not None:
|
||||
AsyncError = error
|
||||
- M._mesg('[cb] ERROR %s %.100s => %s' % (cmd, args, error))
|
||||
+ M._log(0, '[cb] ERROR %s %.100s => %s' % (cmd, args, error))
|
||||
return
|
||||
typ, dat = response
|
||||
- M._mesg('[cb] %s %.100s => %s %.100s' % (cmd, args, typ, dat))
|
||||
+ M._log(0, '[cb] %s %.100s => %s %.100s' % (cmd, args, typ, dat))
|
||||
if typ == 'NO':
|
||||
AsyncError = (Exception, dat[0])
|
||||
|
||||
def run(cmd, args, cb=True):
|
||||
if AsyncError:
|
||||
+ M._log(1, 'AsyncError')
|
||||
M.logout()
|
||||
typ, val = AsyncError
|
||||
raise typ(val)
|
||||
- M._mesg('%s %.100s' % (cmd, args))
|
||||
+ if not M.debug: M._log(0, '%s %.100s' % (cmd, args))
|
||||
try:
|
||||
if cb:
|
||||
typ, dat = getattr(M, cmd)(callback=responder, cb_arg=(cmd, args), *args)
|
||||
- if M.debug:
|
||||
- M._mesg('%s %.100s => %s %.100s' % (cmd, args, typ, dat))
|
||||
+ M._log(1, '%s %.100s => %s %.100s' % (cmd, args, typ, dat))
|
||||
else:
|
||||
typ, dat = getattr(M, cmd)(*args)
|
||||
- M._mesg('%s %.100s => %s %.100s' % (cmd, args, typ, dat))
|
||||
+ M._log(1, '%s %.100s => %s %.100s' % (cmd, args, typ, dat))
|
||||
except:
|
||||
+ M._log(1, '%s - %s' % sys.exc_info()[:2])
|
||||
M.logout()
|
||||
raise
|
||||
if typ == 'NO':
|
||||
+ M._log(1, 'NO')
|
||||
M.logout()
|
||||
raise Exception(dat[0])
|
||||
return dat
|
||||
@@ -2270,15 +2359,15 @@ if __name__ == '__main__':
|
||||
if keyfile is not None:
|
||||
if not keyfile: keyfile = None
|
||||
if not certfile: certfile = None
|
||||
- M = IMAP4_SSL(host=host, port=port, keyfile=keyfile, certfile=certfile, debug=debug, identifier='', timeout=10)
|
||||
+ M = IMAP4_SSL(host=host, port=port, keyfile=keyfile, certfile=certfile, debug=debug, identifier='', timeout=10, debug_buf_lvl=debug_buf_lvl)
|
||||
elif stream_command:
|
||||
- M = IMAP4_stream(stream_command, debug=debug, identifier='', timeout=10)
|
||||
+ M = IMAP4_stream(stream_command, debug=debug, identifier='', timeout=10, debug_buf_lvl=debug_buf_lvl)
|
||||
else:
|
||||
- M = IMAP4(host=host, port=port, debug=debug, identifier='', timeout=10)
|
||||
+ M = IMAP4(host=host, port=port, debug=debug, identifier='', timeout=10, debug_buf_lvl=debug_buf_lvl)
|
||||
if M.state != 'AUTH': # Login needed
|
||||
PASSWD = getpass.getpass("IMAP password for %s on %s: " % (USER, host or "localhost"))
|
||||
test_seq1.insert(0, ('login', (USER, PASSWD)))
|
||||
- M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
|
||||
+ M._log(0, 'PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
|
||||
if 'COMPRESS=DEFLATE' in M.capabilities:
|
||||
M.enable_compression()
|
||||
|
22
mail/offlineimap/files/patch-docs-MANUAL.rst
Normal file
22
mail/offlineimap/files/patch-docs-MANUAL.rst
Normal file
|
@ -0,0 +1,22 @@
|
|||
Fixes wrong title level.
|
||||
|
||||
--- docs/MANUAL.rst.orig 2011-08-15 14:21:24.000000000 +0400
|
||||
+++ docs/MANUAL.rst 2011-08-15 14:22:03.000000000 +0400
|
||||
@@ -380,7 +380,7 @@
|
||||
default.
|
||||
|
||||
Certificate checking
|
||||
-^^^^^^^^^^^^^^^^^^^^
|
||||
+--------------------
|
||||
|
||||
Unfortunately, by default we will not verify the certificate of an IMAP
|
||||
TLS/SSL server we connect to, so connecting by SSL is no guarantee
|
||||
@@ -397,7 +397,7 @@
|
||||
certificate and CA certificate.
|
||||
|
||||
StartTLS
|
||||
-^^^^^^^^
|
||||
+--------
|
||||
|
||||
If you have not configured your account to connect via SSL anyway,
|
||||
OfflineImap will still attempt to set up an SSL connection via the
|
|
@ -15,6 +15,9 @@ bin/offlineimap
|
|||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/LocalStatus.py
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/LocalStatus.pyc
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/LocalStatus.pyo
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/LocalStatusSQLite.py
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/LocalStatusSQLite.pyc
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/LocalStatusSQLite.pyo
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/Maildir.py
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/Maildir.pyc
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/folder/Maildir.pyo
|
||||
|
@ -75,6 +78,9 @@ bin/offlineimap
|
|||
%%PYTHON_SITELIBDIR%%/offlineimap/accounts.py
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/accounts.pyc
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/accounts.pyo
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/error.py
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/error.pyc
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/error.pyo
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/imaplib2.py
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/imaplib2.pyc
|
||||
%%PYTHON_SITELIBDIR%%/offlineimap/imaplib2.pyo
|
||||
|
|
Loading…
Reference in a new issue