The current code for supporting the utf8foldernames does not work with
Python3 due to changes in the 'codecs' module and related functions.
This fix adapts the existing code to work with Python3.
Signed-off-by: Amit Ramon <amit@riseup.net>
In case of an exception in XOAUTH2 code refresh (HTTP Error 400: Bad
Request), following exception occurs:
ERROR: While attempting to sync account 'xxx'
__init__() missing 3 required positional arguments: 'msg', 'hdrs', and 'fp'
Traceback:
File ".../offlineimap3/offlineimap/accounts.py", line 298, in syncrunner
self.__sync()
File ".../offlineimap3/offlineimap/accounts.py", line 374, in __sync
remoterepos.getfolders()
File ".../offlineimap3/offlineimap/repository/IMAP.py", line 648, in getfolders
imapobj = self.imapserver.acquireconnection()
File ".../offlineimap3/offlineimap/imapserver.py", line 591, in acquireconnection
self.__authn_helper(imapobj)
File ".../offlineimap3/offlineimap/imapserver.py", line 448, in __authn_helper
if func(imapobj):
File ".../offlineimap3/offlineimap/imapserver.py", line 382, in __authn_xoauth2
imapobj.authenticate('XOAUTH2', self.__xoauth2handler)
File ".../offlineimap3/venv/lib/python3.7/site-packages/imaplib2.py", line 682, in authenticate
typ, dat = self._simple_command('AUTHENTICATE', mechanism.upper())
File ".../offlineimap3/venv/lib/python3.7/site-packages/imaplib2.py", line 1675, in _simple_command
return self._command_complete(self._command(name, *args), kw)
File ".../offlineimap3/venv/lib/python3.7/site-packages/imaplib2.py", line 1395, in _command
literal = literator(data, rqb)
File ".../offlineimap3/venv/lib/python3.7/site-packages/imaplib2.py", line 2238, in process
ret = self.mech(self.decode(data))
File ".../offlineimap3/offlineimap/imapserver.py", line 257, in __xoauth2handler
raise type(e)(msg, exc_info()[2])
The exception 'e' is of type HTTPError, which does not have the same kind of
constructor as normal Python exceptions.
Instead, print the constructed message and just raise the existing
exception.
With that change, the same condition triggers another problem further on:
ERROR: While attempting to sync account 'xxx'
tuple index out of range
Traceback:
File ".../offlineimap3/offlineimap/accounts.py", line 298, in syncrunner
self.__sync()
File ".../offlineimap3/offlineimap/accounts.py", line 374, in __sync
remoterepos.getfolders()
File ".../offlineimap3/offlineimap/repository/IMAP.py", line 648, in getfolders
imapobj = self.imapserver.acquireconnection()
File ".../offlineimap3/offlineimap/imapserver.py", line 664, in acquireconnection
elif isinstance(e, socket.error) and e.args[0] == errno.ECONNREFUSED:
because e.args is empty.
This patch solves a problem about the comparison of mails used in
foldersort.
When foldersort is used, for example with:
lambda x,y: -cmp(x,y)
The user gets an error:
ERROR: While attempting to sync account 'accountname'
'<' not supported between instances of 'K' and 'K'
Traceback:
File "offlineimap3/offlineimap/accounts.py", line 298, in syncrunner
self.__sync()
File "offlineimap3/offlineimap/accounts.py", line 374, in __sync
remoterepos.getfolders()
File "offlineimap3/offlineimap/repository/IMAP.py", line 725, in getfolders
retval.sort(key=cmp2key(self.foldersort))
The problem is because in Python 3, we must specify all parameters for
total_ordering (see https://docs.python.org/3/library/functools.html in
the functools.total_ordering block):
Given a class defining one or more rich comparison ordering methods,
this class decorator supplies the rest. This simplifies the effort
involved in specifying all of the possible rich comparison operations:
The class must define one of __lt__(), __le__(), __gt__(), or __ge__().
In addition, the class should supply an __eq__() method.
Also, see: https://docs.python.org/3.1/library/stdtypes.html#comparisons
Instances of a class cannot be ordered with respect to other instances
of the same class, or other types of object, unless the class defines
enough of the methods __lt__(), __le__(), __gt__(), and __ge__()
(in general, __lt__() and __eq__() are sufficient, if you want the
conventional meanings of the comparison operators).
This patch implements all methods.
Closes#33
Running offlineimap with tunneled connections fails.
The connection to the server is right, the server sends the
PREAUTH message, offlineimap reads it and provides a reply, something
like 'UID1 CAPABILITY'. This message is added to the output queue in
imaplib2.py, function _command():
if literal is None:
self.ouq.put(rqb)
return rqb
Then, the function _writer() in imaplib2 calls the self.send() function:
try:
self.send(rqb.data)
if __debug__: self._log(4, '> %r' % rqb.data)
self object is an IMAP4_Tunnel class, and the function send() writes the
message, but the message is not sent to the server.
We need flush the buffer.
Closes#30
When I ported offlineimap from Python 2 to Python 3 I removed the Debug for
IMAP (imaplib2).
The reason was offlineimap was setting the Debug directly in imaplib2,
not using the proper way (using the IMAP4 argument). Because we are
removing the virtual_imaplib2, I removed this option.
I removed this line in offlineimap/init.py:303:
---8<---
300 dtype = dtype.strip()
301 self.ui.add_debug(dtype)
302 if dtype.lower() == u'imap':
-303 imaplib.Debug = 5
304
305 if options.runonce:
306 # Must kill the possible default option.
---8<---
With this patch, the debug level 5 is restored in imaplib if the user
set the -d ALL or -d imap in offlineimap.
This patch converts the search results from bytes to strings
I add a bit comment about it here:
In Py2, with IMAP, imaplib2 returned a list of one element string.
['1, 2, 3, ...'] -> in Py3 is [b'1 2 3,...']
In Py2, with Davmail, imaplib2 returned a list of strings.
['1', '2', '3', ...] -> in Py3 should be [b'1', b'2', b'3',...]
In my tests with Py3, I get a list with one element: [b'1 2 3 ...']
Then I convert the values to string and I get ['1 2 3 ...']
With Davmail, it should be [b'1', b'2', b'3',...]
When I convert the values to string, I get ['1', '2', '3',...]
Server capabilities are returned as list of bytes. We need convert them
to list of strings.
This patch do it. Probably you must recreate your cache after this patch.
Reading the password using remotepasseval returns a bytes objects
instead an utf-8 string.
This patch includes support strings and bytes objects.
Closes#21
Signed-off-by: Rodolfo García Peñas (kix) <kix@kix.es>
Remove the warnings:
repository/__init__.py:66:12: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
repository/__init__.py:74:12: W0707: Consider explicitly re-raising using the 'from' keyword (raise-missing-from)
Variable bk is renamed to bkend to avoid this pylint warning:
repository/LocalStatus.py:88:12: C0103: Variable name "bk" doesn't conform to snake_case naming style (invalid-name)
The function sync_folder_structure is only used in the accounts.py file:
kix@inle:~/src/offlineimap3/offlineimap$ rgrep sync_folder_structure *
accounts.py: remoterepos.sync_folder_structure(localrepos, statusrepos)
repository/Base.py: def sync_folder_structure(self, local_repo, status_repo):
kix@inle:~/src/offlineimap3/offlineimap$
The returned value is not used. We have this warning:
R1710: Either all return statements in a function should return an expression, or none of them should. (inconsistent-return-statements)
Because is not returning anything here, but is returning None at the function end.
We can include this None here safely.
First, in Python 3 we don't need call the super().__init__ explicitly, because Python does it. So, we can remove the line:
super().__init__(reposname, account)
If we leafe the method __init__ empty, the parent __init__ method is not called, we need remove the __init__ and then Python uses the parent __init__ method.