Commit Graph

719 Commits

Author SHA1 Message Date
Sebastian Spaeth
36eb37b47d IMAP: reduce quickchanged() checks
For each folder we were making a second IMAP request asking for the
latest UID and compared that with the highest UID in our
statusfolder. This catched the case that 1 mail has been deleted by
someone else and another one has arrived since we checked, so that the
total number of mails appears to not have changed.

We don't capture anymore this case in the quickchanged() case.

It improves my performance from 8 to about 7.5 seconds per check (with lots of
variation) and we would benefit even more in the IMAP<->IMAP case as we do one
additional IMAP lookup per folder on each side then.

Do cleanups on whitespaces while in this file.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-04-25 12:58:47 +02:00
Nicolas Sebrecht
3b09695236 v6.3.3
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-04-21 18:34:24 +02:00
Nicolas Sebrecht
bf1c9e3233 Merge branch 'ss/maildir-quickchanged-cleanup' into next 2011-04-15 19:52:35 +02:00
Ethan Glasser-Camp
9e734006f6 Fix IMAP4_Tunnel to work with imaplib2
* IMAP4_Tunnel constructor should support base-class arguments, in
  order to support the timeout argument.

* IMAP4_Tunnel needs to store the member IMAP4.host, which is normally
  done in IMAP4.open().

* Update IMAP4_Tunnel.read() and IMAP4_Tunnel.send().  We turn on
  nonblocking mode for these sockets, so we can return immediately
  with whatever data is available.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-04-13 18:41:53 +02:00
Sebastian Spaeth
fdf22400b1 imaplib2: Bump from 2.20 to 2.22
This contains a fixed Time2InternalDate function and a more robust
socket connection, trying twice and raising an error only when that
fails (I believe). The actual code changes are rather minor.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Reviewed-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-04-11 19:10:45 +02:00
Sebastian Spaeth
e37441cd19 folder/Maildir: Make use of helper functions
quickchanged() was iterating a lot, make use of some of the helper
functions that had been introduced recently and document the function a
bit better. No functional change.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-04-11 18:57:25 +02:00
Sebastian Spaeth
d762175af4 Make -f option with with folder names with spaces.
Previously ALL spaces had been stripped off. Now, only strip spaces
around the comma, so -f "INBOX, Deleted Mails" will work. You will still
need to quote or escape spaces so the shell hand the list as one command
line argument to offlineimap.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-04-11 18:29:44 +02:00
Sebastian Spaeth
58220fd8e7 Replace calls to getmessagelist() to alternatives
getmessagelist() is slow for the mapped UID case, so replace some of its
occurences with calls that are optimized for this case, ie
getmessagecount() and uidexists().

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Reviewed-and-tested-by: Vincent Beffara <vbeffara@ens-lyon.fr>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-28 17:53:14 +02:00
Sebastian Spaeth
ca012d3a81 Implement more efficient functions for the MappedUID case
We are calling getmessagelist() internally a lot, e.g. just to check if
a UID exists (from uidexist()). This is a very expensive operation in
the UIDMapped case, as we reconstruct the whole messagelist dict every
single time, involving lots of copying etc.

So we provide more efficient implementations for the uidexists()
getmessageuidlist() and getmessagecount() functions that are fast in the
UIDMapped case. This should solve the performance regression that was
recently observed in the Mapped UID case.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Reviewed-and-tested-by: Vincent Beffara <vbeffara@ens-lyon.fr>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-28 17:52:22 +02:00
Nicolas Sebrecht
0f85e592a3 Merge branch 'df/fix-debug-msg' into next 2011-03-28 16:50:18 +02:00
David Favro
954655b7ec Fixed bug: wrong number of arguments to debug() [IMAP.py].
Signed-off-by: David Favro <offlineimap@meta-dynamic.com>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-28 16:49:21 +02:00
Nicolas Sebrecht
71d0828cd6 Merge branch 'master' into next 2011-03-25 18:42:46 +01:00
Sebastian Spaeth
09515f8f90 Increase compatability with Gmail
When uploading a new message to Gmail we need to find out the UID it
assigned it, but Gmail does not advertize the UIDPLUS extension (in all
cases) and it fails to find the email that we just uploaded when
searching for it. This prevented us effectively from uploading to
gmail.

See analysis in
http://lists.alioth.debian.org/pipermail/offlineimap-project/2011-March/001449.html
for details on what is going wrong.

This patch increases compatability with Gmail by checking for APPENDUID
responses to an APPEND action even if the server did not claim to
support it. This restores the capability to upload messages to the
*broken* Gmail IMAP implementation.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-03-25 18:42:16 +01:00
Ethan Glasser-Camp
105da1b0c3 Always logout() on imaplib2 objects, even during exceptions
Without this, trying to Ctrl-C out of offlineimap will go into a hang.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Reviewed-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-25 18:26:22 +01:00
Nicolas Sebrecht
756eb72494 Merge branch 'master' into next 2011-03-24 19:08:30 +01:00
Nicolas Sebrecht
51b89e6c43 Merge branch 'maint'
Conflicts:
	Changelog.draft.rst
	Makefile
2011-03-24 19:07:34 +01:00
Sebastian Spaeth
65faec834f accounts.py: Print the stacktrace via traceback module
All other instances were converted to format crash output including a
stacktrace, but this one seems to have been left out. Make Exceptions
print their stacktrace here too.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-24 19:03:16 +01:00
Vincent Beffara
bb48b6deaf Get rid of the UsefulIMAP4 classes
The three classes with names starting with UsefulIMAP4 were used for two
purposes, to include the UsefulIMAPMixIn class and to implement various
system-specific kludges. None of these kludges remain, so it is cleaner
to include UsefulIMAPMixIn directly in imaplibutil and forget about them
for good.

Signed-off-by: Vincent Beffara <vbeffara@ens-lyon.fr>
Reviewed-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-23 20:00:35 +01:00
Vincent Beffara
9f03f41b70 Move UsefulIMAPMixIn to imaplibutil.py
Now that we do not need any system-specific hack, the three UsefulIMAP4
classes have become empty and should be removed. This implies importing
UsefulIMAPMixIn directly from the classes defined in imaplibutil.

Prepare this change by moving the code into imaplibutil.py. Functionally
this is a no-op.

Signed-off-by: Vincent Beffara <vbeffara@ens-lyon.fr>
Reviewed-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-23 20:00:30 +01:00
Vincent Beffara
9a277cfd02 Remove a darwin-specific workaround for read()
Because of a buggy realloc() implementation in earlier versions of
Python on Mac OS X, we had to cut reads into manageable chunks by hand;
this is no more needed with Python 2.6, and besides it causes problems
with imaplib2, which we now use. Revert the special case to use the
system's read() instead, which is now safe.

Signed-off-by: Vincent Beffara <vbeffara@ens-lyon.fr>
Reviewed-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-23 20:00:23 +01:00
Nicolas Sebrecht
37d0fe8b01 v6.3.2.1
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-16 20:46:18 +01:00
Nicolas Sebrecht
3eba44f636 Merge branch 'ss/uidmaps' into next 2011-03-16 18:05:35 +01:00
Sebastian Spaeth
fd28c5a2d3 folder/IMAP: savemessage() should just save flags if uid already exists
As the LocalStatus and UIDMap backend already did: If the uid already
exists for savemessage(), only modify the flags and don't append a new
message.

We don't invoke savemessage() on messages that already exist in our sync
logic, so this has no change on our current behavior. But it makes
backends befave more consistent with each other.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-16 18:05:16 +01:00
Sebastian Spaeth
dc3ad723c9 Give some love to UIDMaps
- Some documentation improvements, this is a severely underdocumented
  class. This still needs some further improvements though.

- Don't use apply(Baseclass) (which is going away in Python 3), use
  IMAPFolder.__init__(self, *args, **kwargs).

- Don't call ValueError, string. It is ValueError(string)

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-16 18:05:16 +01:00
Nicolas Sebrecht
3b45782cc4 Merge branch 'master' into next 2011-03-15 19:28:02 +01:00
Nicolas Sebrecht
180e86007a Merge branch 'maint' 2011-03-15 18:46:26 +01:00
Sebastian Spaeth
1c71e37f8f Sanity checks for SSL cacertfile configuration
We were not able to handle ~/... type of path configurations and we
crashed with mysterious SSL errors when no file was found at the
configured location. Expand '~' and bomb out with usable error messages
in case such a file does not exist. This will still not protect against
corrupt cacert files but it goes a long way towards user friendliness.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-15 18:45:31 +01:00
Nicolas Sebrecht
44eefae043 cleanup import statements and conform to PEP-8
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 21:35:33 +01:00
Ethan Glasser-Camp
5ea95002f5 Create new connections with a timeout
imaplib2 does not use socket, so does not know about the
defaulttimeout we set based on the config. Instead, we explicitly pass
the default timeout.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:56 +01:00
Ethan Glasser-Camp
a139d9deed Throw away broken connections
Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:56 +01:00
Ethan Glasser-Camp
197030da1a Remove obsolete read(), readline(), _read_upto() methods
For read(), the imaplib2 version seems to work perfectly well. The
others aren't used any more, either by imaplib2, nor by us, so we may
as well get rid of them.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:56 +01:00
Ethan Glasser-Camp
1bf4bee5e6 Update to match semantics of new imaplib2
The biggest change here is that imapobj.untagged_responses is no
longer a dictionary, but a list. To access it, I use the semi-private
_get_untagged_response method.

* offlineimap/folder/IMAP.py (IMAPFolder.quickchanged,
  IMAPFolder.cachemessagelist): imaplib2 now explicitly removes its
  EXISTS response on select(), so instead we use the return values from
  select() to get the number of messages.

* offlineimap/imapserver.py (UsefulIMAPMixIn.select): imaplib2 now
  stores untagged_responses for different mailboxes, which confuses us
  because it seems like our mailboxes are "still" in read-only mode when
  we just re-opened them.  Additionally, we have to return the value
  from imaplib2's select() so that the above thing works.

* offlineimap/imapserver.py (UsefulIMAPMixIn._mesg): imaplib2 now
  calls _mesg with the name of a thread, so we display this
  information in debug output. This requires a corresponding change to
  imaplibutil.new_mesg.

* offlineimap/imaplibutil.py: We override IMAP4_SSL.open, whose
  default arguments have changed, so update the default arguments. We
  also subclass imaplib.IMAP4 in a few different places, which now
  relies on having a read_fd file descriptor to poll on.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:56 +01:00
Ethan Glasser-Camp
f9413226b8 Import imaplib2 instead of imaplib
imaplib2 has slightly different semantics than standard imaplib, so
this patch will break the build, but I thought it was helpful to have it as
a separate commit.

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:56 +01:00
Ethan Glasser-Camp
0a76f0a23d Import newest version of imaplib2
This change does not do anything yet with imaplib2, merely makes it
available for future commits.

This file is identical to the one at
http://sydney.edu.au/engineering/it/~piers/python/imaplib2 .

imaplib2, written by the same guy who wrote imaplib, is very different
from imaplib itself. Calling it a modified version from the standard
distribution is misleading. It's more like a complete rewrite. As
such, it's not really possible to summarize what was changed.

The largest thing is that imaplib2 is "threaded". Instead of doing
blocking writes/reads on the socket during/after every command,
imaplib2 forks off threads to read and write to the socket based on
input and output buffers. This opens the door to asynchronous
commands (every command is potentially asynchronous, according to the
docs), and in particular IDLE, which is by definition an asynchronous
command.

The author writes: "imaplib2 can be substituted for imaplib in
existing clients with no changes in the code", but that's pretty
misleading. It might be true for certain simple users of imaplib, but
for us it's completely false. Among other things, how untagged
responses are stored in-memory is different -- instead of a hash
table, it's a list. I'm guessing this is to preserve order of
responses.

I think there are other miscellaneous improvements, like I think
imaplib2 is IPv6 safe out-of-the-box, but I haven't conducted an
extremely thorough examination of the differences :)

Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:56 +01:00
Ethan Glasser-Camp
e2354fd37c Remove some unneeded imports
Signed-off-by: Ethan Glasser-Camp <ethan@betacantrips.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-14 19:51:52 +01:00
Sebastian Spaeth
2946a1ea5d Convert rfc822 module to email module
The rfc822 module has been deprecated since python 2.3, and conversion to
the email module is straightforward, so let us do that. rfc822 is
completely gone in python3.

This also fixes a bug that led to offlineimap abortion (but that code path
is apparently usually not exercised so I did not notice:
rfc822|email.utils.parsedate return a tuple which has no named attributes,
but we were using them later in that function. So pass the tuple into a
struct_time() to get named attributes.

While reading the docs, I noticed that email.parsedate returns invalid
daylight savings information (is_dst attribute), and we are using it
anyway. Oh well, the imap server might think the mails are off by an hour
at worst.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-13 20:30:35 +01:00
Nicolas Sebrecht
30d95ad0ac Merge branch 'ns/uibase-fix-destlist' into next 2011-03-12 13:48:52 +01:00
Nicolas Sebrecht
6887bd995d Merge branch 'ss/remove-stringio-in-threadutil' into next 2011-03-11 20:34:56 +01:00
Sebastian Spaeth
10024731e6 threadutil: Don't require the StringIO module
The only reason we used it here was to do a
traceback.print_exc(StringIO()) to get a string of our traceback. But we
can simply use traceback.format_exc() which exists since python 2.4.

One less module (and it is in the way to python 3 compatability too)

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-11 20:34:33 +01:00
Nicolas Sebrecht
90949a4bfc UIBase: fix regression while deletingflags
In commit 7a2a0225 [Don't pass list to ui.adding/deletingflags] we changed the
list logic for a per folder logic but forgot to remove one instance of
"destlist" which isn't valid anymore.

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-11 20:20:12 +01:00
Sebastian Spaeth
6c6fdfc769 folder: Implement helper functions uidexists() and getmessageuidlist()
More convenient way to test if a certain uid exists and getting a list
of all uids. Also, the SQL backend will have efficient overrides for
these methods.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-11 18:59:20 +01:00
Sebastian Spaeth
4d352a528a folder: Implement helper function getmessagecount()
Rather than always having to call len(getmessagelist.keys()) as was done
before. No functional change, just nicer looking code. Also the SQLite
backend or other backends could implement more efficient implementations.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-10 20:30:19 +01:00
Nicolas Sebrecht
5048d16913 Merge branch 'ss/declutter-tty-output' into next
Conflicts:
	Changelog.draft.rst
2011-03-10 19:26:26 +01:00
Sebastian Spaeth
efcce01d64 Declutter TTY output
Previously we would output:

Folder sync sspaeth.de[INBOX.INBOX201004]:
 Syncing INBOX.INBOX201004: IMAP -> Maildir
Folder sync sspaeth.de[INBOX.INBOX201006]:
 Syncing INBOX.INBOX201006: IMAP -> Maildir
Folder sync sspaeth.de[INBOX.INBOX201009]:
 Syncing INBOX.INBOX201009: IMAP -> Maildir

which is very repetitive and cluttered. By naming the folder sync
threads just according to the account and not the folder, the output
looks much nicer:

Folder sync [sspaeth.de]:
 Syncing INBOX.INBOX201004: IMAP -> Maildir
 Syncing INBOX.INBOX201006: IMAP -> Maildir
 Syncing INBOX.INBOX201009: IMAP -> Maildir

If syncing multiple accounts in parallel, we will still get headers
indicating the account:

Folder sync [sspaeth.de]:
 Syncing INBOX: IMAP -> Maildir
 Syncing INBOX.INBOX201006: IMAP -> Maildir
Folder sync [gmail]:
 Syncing INBOX: IMAP -> Maildir

This is a small fix that makes the output much nicer in my opinion.

Also don't output the thread name if we are in the MainThread, e.g. when
we output the initial offlineimap banner.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-10 19:04:57 +01:00
Nicolas Sebrecht
7b8d7501d1 Merge branch 'master' into next
Conflicts:
	Changelog.draft.rst
	offlineimap/imapserver.py
2011-03-07 21:55:43 +01:00
Haojun Bao
b94bf79258 fix hang because of infinite loop reading EOF
Read() should return empty string when EOF happen, instead of looping
forever. This is the right semantics of read(), and a wrapped version
should not change it.

If you read the read(2) system call manpage, it tells you that when EOF
is seen, return value is 0; it does not say

	``loop forever when EOF happen''.

After the EOF detection is patched you can see the
following exception:

  WARNING: ERROR attempting to copy message 344 for account Gmail:Traceback (most recent call last):
    File "/usr/lib/pymodules/python2.6/offlineimap/folder/Base.py", line 282, in copymessageto
      message = self.getmessage(uid)
    File "/usr/lib/pymodules/python2.6/offlineimap/folder/IMAP.py", line 216, in getmessage
      initialresult = imapobj.uid('fetch', '%d' % uid, '(BODY.PEEK[])')
    File "/usr/lib/python2.6/imaplib.py", line 753, in uid
      typ, dat = self._simple_command(name, command, *args)
    File "/usr/lib/python2.6/imaplib.py", line 1060, in _simple_command
      return self._command_complete(name, self._command(name, *args))
    File "/usr/lib/python2.6/imaplib.py", line 890, in _command_complete
      raise self.abort('command: %s => %s' % (name, val))
  abort: command: UID => socket error: EOF

Signed-off-by: Bao Haojun <baohaojun@gmail.com>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-07 21:54:28 +01:00
Sebastian Spaeth
7a2a02254e Don't pass list to ui.adding/deletingflags
We only have one "dstfolder" at a time when deleting/adding flags, so no
need to pass in a list of those to the ui functions that output the log
info.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-07 21:11:10 +01:00
Sebastian Spaeth
387fbf3aaa ui: clean up importment statements
They were not PEP-8 formatted, and some imports were simply
unnecessary. Removed those.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-07 21:11:10 +01:00
Sebastian Spaeth
ab1df868c2 String representation of a Folder is its name
This enables us to just use the folder instance in the ui output and get
a name rather than having to call getname() all the time.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-07 21:11:10 +01:00
Sebastian Spaeth
3eee821382 Simplify the syncing strategy a bit
The previous syncing strategy was doing more than we needed to and was a
bit underdocumented. This is an attempt to clean it up.

1) Do away with the previous different code paths depending on
whether there is a LocalStatus file or not (the isnewfolder() test). We
always use the same strategy now, which makes the strategy easier to
understand. This strategy is simply:

a) Sync remote to local folder first
b) Sync local to remote

Where each sync implies a 4 pass strategy which does basically the same
as before (explained below).

2) Don't delete messages on LOCAL which don't exist on REMOTE right at
the beginning anymore. This prevented us e.g. from keeping local
messages rather than redownloading everything once LocalStatus got
corrupted or deleted. This surprised many who put in an existing local
maildir and expected it to be synced to the remote place. Instead, the
local maildir was deleted. This is a data loss that actually occured to
people!

3) No need to separately sync the statusfolder, we update that one
simultanously with the destfolders...

3) Simplified the sync function API by only taking one destdir rather
than a list of destdirs, we never used more anyway. This makes the code
easier to read.

4) Added plenty of code comments while I was going through to make sure
the strategy is easy to understand.
-----------------------------------------

 Pass1: Transfer new local messages
        Upload msg with negative/no UIDs to dstfolder. dstfolder should
        assign that message a new UID. Update statusfolder.

 Pass2: Copy existing messages
        Copy messages in self, but not statusfolder to dstfolder if not
        already in dstfolder. Update statusfolder.

 Pass3: Remove deleted messages
        Get all UIDS in statusfolder but not self. These are messages
        that we have locally deleted. Delete those from dstfolder and
        statusfolder.

 Pass4: Synchronize flag changes
        Compare flags in self with those in statusfolder. If msg has a
        valid UID and exists on dstfolder (has not e.g.  been deleted
        there), sync the flag change to dstfolder and statusfolder.

The user visible implications of this change should be unnoticable
except in one situation:
 Blowing away LocalStatus will not require you to redownload ALL of
 your mails if you still have the local Maildir. It will simply recreate
 LocalStatus.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-07 21:11:10 +01:00
Nicolas Sebrecht
976c071dd7 Merge branch 'ss/deprecate-current-ui-names' into next 2011-03-06 18:33:29 +01:00
Sebastian Spaeth
fc03475b9e Remove thread Lock() when saving UIDvalidity
Removing this lock makes the function not threadsafe, but then it is
only ever called from one thread, the main account syncer. Also, it
doesn't make it worse than most of the other functions in that class
which are also not threadsafe.

Removing this makes the code simpler, and removes the need to import the
threading module.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-06 18:33:11 +01:00
Nicolas Sebrecht
607eba178a Merge branch 'ss/maxconnections-to-2' into next 2011-03-06 18:31:06 +01:00
Sebastian Spaeth
4e28c7c93f Allow to use nicer UI names
The previous ui names were pretty unwieldy. Is it TTYUI.TTY or
TTY.TTYUI? Do I have to use capitals and where?

Simplify the names by making them case insensitive and by dropping
everything before the dot.

So "Curses.Blinkenlights" can now be invoked as "blinkenlights" or
"BLINKENLIGHTS". The old names will still work just fine so the
transition should be smooth. We issue a warning that the long names are
deprecated.

Document in offlineimap.conf that we don't accept lists of fallback UIs,
but only one UI option (this was already the case before this commit but
still wrongly documented).

The list of accepted ui names is:
  ttyui (default), basic, quiet, machineui, blinkenlights

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-06 15:33:29 +01:00
Sebastian Spaeth
c44e94d64a Set maxconnections default to 2
Multithreading speeds up account syncing a lot and the offlineimap
defaults are very conservative. Let's make it use 2 IMAP connections by
default to gain some of the benefits that offlineimap offers.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-06 15:27:38 +01:00
Sebastian Spaeth
3b8e1f91cd Implement APPENDUID support
Rather than inserting our own home-grown header, everytime we save a
message to an IMAP server, we check if we suport the UIDPLUS extension
which provides us with an APPENDUID reply. Use that to find the new UID
if possible, but keep the old way if we don't have that extension.

If a folder is read-only, return the uid that we have passed in per API
description in folder.Base.py

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-05 18:02:10 +01:00
Sebastian Spaeth
96db608e4d Remove convoluted assert statements
The working horse of the savemessage() function, imaplib.append() was
hidden away in an assert statement. Pull the real functions out of the
asserts and simply assert on the return values. This looks less
convoluted and makes this easier to understand in my opinion.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-05 18:02:10 +01:00
Sebastian Spaeth
d22c762385 Factor out the date guessing/retrieving
savemessage was too long and complex. Factor out the date guessing part
of the function and put it into a function of its own. The logic of the
date guessing is the same, however, we do not use the
imaplib.Time2InternalDate() function as it is buggy
(http://bugs.python.org/issue11024) and returns localized patches. So we
create INTERNALDATE ourselves and pass it to append() as a string.

This commit fixes a bug that international users used to pass an invalid
date to the IMAP server, which the server will either ignore or complain
about.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-05 18:02:10 +01:00
Sebastian Spaeth
419f27418e Simplify & document savemessage_getnewheader
savemessage_getnewheader was an undocmented, cryptic and overengineered
function. It generates a new unique value that can be used as a mail
header to be inserted. For this it used LOTS of randomness sources: hash
of the mail content, hash of the folder name, hash of the repository
name, the current time, a random() value, and the offlineimap version string.
All we need is something random. So reduce this to hash of content
appended by a random integer. Sufficient and somewhat faster to calculate.

Rename the function to actually describe accurately what it does or
would you have guessed that savemessage_getnewheader() did nothing more
than returning ('X-OfflineIMAP', <randomstring> )? Rename to
generate_randomheader() to make it clearer what this is all about.

Also document the function, describing what it does, and what it returns.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-05 18:02:09 +01:00
Nicolas Sebrecht
a271f90271 Merge branch 'ss/remove-uneeded-darwin-workaround' into next 2011-03-05 16:37:35 +01:00
Sebastian Spaeth
ab3900e479 Remove unneeded workaround for Darwin
There is a clumsy workaround for Darwin that chunks reads into 8kb
blocks to avoid huge memory allocations. First, this fix should not only
be required but on FreeBSD2.6 too (see
http://bugs.python.org/issue3531). Second, decent python versions (I
checked 2.6) already chunk in the SSL case anyway, so there is no need to do
that again. Remove that level of indirection.

http://evanjones.ca/python-memory.html claims that this problem has been
fixed since python 2.5, so we might consider removing the workaround
completely even for the non-SSL case.

Increase the chunk size on Mac from 8kb to 64kb. Even Macs should be
able to take that amount of memory usage nowadays.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-05 16:37:00 +01:00
Nicolas Sebrecht
4e0aaa07c0 Merge branch 'master' into next 2011-03-03 19:09:30 +01:00
Sebastian Spaeth
2ab51e6855 Make profiling mode really enforce singlethreading
A typo was preventing profiling mode to really enable singlethreading
mode. Fixing the unfortunate typo of mine makes it work.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-03 19:08:49 +01:00
Nicolas Sebrecht
c9ac254c8c Merge branch 'ss/debug-folderfilter' into next 2011-03-03 19:07:35 +01:00
Sebastian Spaeth
93f7d0bd1f Enable debug output to see what folderfilter actually filters out
It is currently very hard to find out what folderfilter actually does
and makes it hard to debug for a user. With this patch if the user has
enabled "-d imap" (even better would perhaps be a different debug type
for this kind of thing?), we see a message
"Filtering out folder 'foo' due to folderfilter"
in the logs.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-03 19:05:57 +01:00
Sebastian Spaeth
cc64a0952c Make self.ui available in all Repository() derivatives
This enables us to make use of self.ui in all repositories without
having to import and use getglobalui() in all types of repositories and
all places.

Note that this patch only makes this available, it does not yet make use
of it.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-03 19:05:57 +01:00
Nicolas Sebrecht
d7210f3ccd Merge branch 'ss/better-msg-error-reference' into next 2011-03-03 18:30:07 +01:00
Sebastian Spaeth
0811beb03d Provide better error message for invalid 'reference' setting
When e.g. specifying an invalid 'reference' value for an IMAP server to
a root folder that does not exist, we would previously have crashed with
a nonsensical and non-intuitive error message (trying to address an
element of a NoneType).

This will also raise an Exception (which should be ok, given that this
is really a misconfiguration on the user side), but it will explain to
the user WHY it exited.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-03 18:29:46 +01:00
Nicolas Sebrecht
ea4bdbe63a Merge branch 'ss/remove-over-verbose-debug' into next 2011-03-03 18:23:56 +01:00
Sebastian Spaeth
472476db6f Remove over-verbose debug options
The debug output for dequote, optionsplit is very verbose, outputing
what the functions are called with and what they return. Those functions
are now very old mature and rather simple, so it suffices to output
their return value rather than cluttering out log with too much
uninteresting garbarge.

This makes log files much more readable.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-03 18:23:32 +01:00
Nicolas Sebrecht
8197077c00 Merge branch 'ss/abstract-repository-class' into next
Conflicts:
	Changelog.draft.rst
2011-03-03 18:22:19 +01:00
Sebastian Spaeth
d5e7620ce9 Create an abstract Repository class
A Repository() returns the correctly instanciated dervivate of a
BaseRepository, depending on the parameters passed to it. The returned
instance is eg an ImapRepository(). This makes the code look nicer,
and we have less functions lying around outside of classes (no more
global LoadRepository() function).

This will also enable us to conveniently hand back a
LocalStatusRepository based on SQLITE rather than plain text, if the
user configures this to be the experimental and optional backend
(once it exists).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-03 18:19:42 +01:00
Nicolas Sebrecht
de3942fd53 Merge branch 'master' into next
Conflicts:
	Changelog.draft.rst
2011-03-01 19:01:28 +01:00
Gábor Melis
966841c8d6 Allow SSL connections to send keep-alive messages
This seems to prevent mysterious hangs with SSL imap servers (especially
gmail?) and does not harm in any case. So let us enable keep-alive
messages for ssl connections.
Our thread pool should be made more robust against closed SSL
connections (which do not always seem to raise Exceptions), and not
deadlock while waiting for resources or data that will never arrive.

Reviewed-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Gábor Melis <mega@retes.hu>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-01 18:55:29 +01:00
Sebastian Spaeth
d05162675c repository/Base.py: Fix regression (UIBase is no more)
Commit e506442996 changed getglobalui() back to UIBase.getglobalui()
although the import had changed earlier, causing a regression.

Fix this by using the correct and current way of calling the ui.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-03-01 18:36:57 +01:00
Thomas Jost
838a67bc40 Support subjectAltName in SSL certificates
Signed-off-by: Thomas Jost <schnouki@schnouki.net>
Reviewed-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-23 18:27:44 +01:00
Nicolas Sebrecht
37e5367966 Merge branch 'ss/simplifly-account-classes' into next
Conflicts:
	offlineimap/accounts.py
2011-02-21 13:23:47 +01:00
Nicolas Sebrecht
eb46d6a2b0 Merge branch 'ss/remove-empty-mailboxes-list' into next 2011-02-21 13:21:46 +01:00
Sebastian Spaeth
6398bf7795 Don't require the string module
There is no need for using the string module if all we want is to split
a string at the white space. All pythons since at least 2.4 can do that.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-21 13:20:21 +01:00
Nicolas Sebrecht
374dea8063 v6.3.2
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-21 12:26:48 +01:00
Nicolas Sebrecht
35b0b5bf84 Merge branch 'ns/keep-2.5-compatibility' into next
Conflicts:
	Changelog.draft.rst
2011-02-21 11:47:42 +01:00
Nicolas Sebrecht
72d05bac09 restore compatibilty with python 2.5 for ui TTY
threading.currentThread() used an accessor to get its name.

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-18 20:00:19 +01:00
Sebastian Spaeth1
074cd11418 Use self.ui rather than UIBase.getglobalui()
We have vonverted all places in folder/* to have self.ui available,
rather than having to use UIBase.getglobalui() all the
time. Unfortunately, we did not convert the users in folder/Base.py.
This patch does it belatedly. This fixes
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=613483

Signed-off-by: Sebastian Spaeth1 <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-17 19:03:29 +01:00
Sebastian Spaeth
45e0b233a5 signal handler should only be called with 2 args
I accidentally added "self" as first parameter to the signal handler
method. Of course it is not called with a class instance, the signal
handler always only receives 2 parameters: the signal number and the
stack frame. So just removing the self fixes things.

Proposed-by: Christian Holme <cholme@gmx.com>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-15 19:19:28 +01:00
Sebastian
997dc1f510 Remove unneeded imports of UIBase
Code was broken, as these backends import UIBase (which had been moved).
However, they don't use it, so we can just delete the import.
Sorry, I failed to find those earlier somehow.

Signed-off-by: Sebastian <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-02-09 19:29:01 +01:00
Sebastian Spaeth
465af6c481 accounts.py: Merge AccountSynchronizationMixin with SyncableAccount class
AccountSynchronizationMixin was never used on its own and it is a very
confusing class until you understand what it is used for. (It
complemented the Account() class with a few methods to make Account()
syncable.

But we use the SyncableAccount class anyway, so merge the former Mixin'
methods directly in there.

This does away with a class that is not directly used, and was a case of
over-object-orientation which confuses more than it helps.

Touched up code documentation while going through the file.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-31 18:52:30 +01:00
Sebastian Spaeth
6a751616f6 Remove unused variable mailboxes
"mailboxes" is defined global and set to an empty list, but never used
from anywhere within offlineimap. So let us just delete it.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-31 18:47:49 +01:00
Nicolas Sebrecht
5660bacc5b Merge branch 'ns/init-remove-uneeded-import' into next
Conflicts:
	Changelog.draft.rst
2011-01-28 19:53:23 +01:00
Nicolas Sebrecht
c8726fe472 init.py: remove uneeded import of Localeval
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-28 19:50:28 +01:00
Nicolas Sebrecht
84b7c686ec Merge branch 'master' into next
Conflicts:
	Changelog.draft.rst
2011-01-28 19:48:35 +01:00
Nicolas Sebrecht
9260b3f5a1 Merge branch 'ezy/better-trace-information' into next 2011-01-28 19:36:13 +01:00
Edward Z. Yang
e506442996 Better trace information when an exception is caught.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-28 19:35:21 +01:00
Nicolas Sebrecht
9afb432053 folder/IMAP.py: accord __version__ with import
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-27 19:45:14 +01:00
Nicolas Sebrecht
c84d6ea9c6 Merge branch 'ss/print-only-version-number-for-this-option' into next 2011-01-27 19:40:45 +01:00
Sebastian Spaeth
776b5173db have --version ONLY print the version number
Make --version much less verbose and only print out the version number
to facilitate easy parsing by scripts. We don't really need the verbose
copyright output, it is show with --help anyway.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-27 19:40:27 +01:00
Sebastian Spaeth
83a85bb3fb Remove MultiLock implementation
Currently the Curses code is broken. Importing offlineimap.ui.Curses
will not succeed due to cyclic imports (threadutils imports ui, but ui
wants threadutils.MultiLock). So Curses cannot be chosen.

Incidentally, the only part in the code that uses "MultiLock" is the
Curses UI, to prevent concurrent access from several threads to the
ui-internal thread list and to IO resources such as the
screen. Fortunately for these purposes we don't need a MultiLock, so we
can do away with that implementation completely. A simple RLock that
allows us to have a thread "own" a lock and makes other threads wanting
access to the resource wait until the owning thread is finished.

The MultiLock implementation looked a bit weird, so simplifying code
here is a good thing, it might well be that we fix some "hangs" that
have been reported (and that would only ever occur with the Curses UI).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-25 19:19:14 +01:00
Thomas Schwinge
fa60f3f9b7 offlineimap.version is no more.
This fixes some leftover of 0b5b38d298.

Signed-off-by: Thomas Schwinge <thomas@schwinge.name>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-25 18:36:18 +01:00
Sebastian Spaeth
b47cc1d276 import getglobalui as we use it
This branch is currently broken, as we were using getglobalui() but it
was not imported. This fixes the missing import and makes offlineimap
run successfully.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-21 20:10:18 +01:00
Nicolas Sebrecht
a9c63078a2 Merge branch 'master' into next 2011-01-20 20:12:02 +01:00
Knut Anders Hatlen
9ad1810e43 understand multiple EXISTS replies from servers like Zimbra
Lars Thalmann <web@larsthalmann.com> writes:

> It seems some servers (Zimbra?) respond to imap SELECT requests with
> multiple EXISTS lines:
>
> ? SELECT INBOX
> * 500 EXISTS
> * 0 RECENT
> * 1000 EXISTS
> * 0 RECENT
> * 1500 EXISTS
> * 0 RECENT
> * 1567 EXISTS
> * 0 RECENT

Signed-off-by: Knut Anders Hatlen <kahatlen@gmail.com>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-20 20:06:46 +01:00
Sebastian Spaeth
c5d49cec3e Improve CustomConfig documentation
Improve documentation about what CustomConfigHelperMixin does,
it was not very clear without a close look to the code before.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-01-20 19:46:01 +01:00
Nicolas Sebrecht
87d5ea3057 Merge branch 'master' into next 2011-01-18 18:40:29 +01:00
Sebastian Spaeth
9b85ffef89 Only verify hostname if we actually use CA certs
The current code path checked the CA cert host name, even if we did not
specify a CA cert file to use. Make the host name check dependent on a
CA cert file.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-18 18:39:38 +01:00
Sebastian Spaeth
f7e9d9525d Imply single-threaded mode with -d(ebug) command line option
All invocations of -d will imply the single-threaded mode unless one of
the debug options is "thread" (in which case it would be senseless to
force single-threaded mode).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-14 19:25:29 +01:00
Sebastian Spaeth
b81b7d6001 Implement true single-threading
Previously, we would spawn child threads for account synchronization
even if we had single-threading enabled. This prevented us from catching
the true location of exceptions, for example. Now, in single-threaded
mode, we perform the account synchronization truely in the main thread
which will ease our debugging.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-14 19:25:11 +01:00
Sebastian Spaeth
760698253b LocalStatus: Don't ignore Exceptions on os.fsync
Earlier we would ignore *ALL* Exceptions that could occur during the
fsyncing of our LocalStatus database. Ignoring all Exceptions is not the
right thing here though. A recent commit improved the situation by
raising at least KeyboardInterrupt Exceptions, but that is still not
optimal.

os.fsync() is available on Unix, and Windows starting in python
2.2.3. so it should always work. If it doesn't, something is wrong.

It has been suggested to only catch EnvironmentError (ie SystemError and
OSError) here, but even those should be thrown. Something *is* wrong if
this fails and we should not ignore it.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-14 19:25:11 +01:00
Sebastian Spaeth
1a1e68d8be Catch KeyboardInterrupt exceptions explicitely
Previously we did not catch KeyboardInterrupts explicitly as all of the
code was executed in forked child threads which would never receive
Ctrl-c exceptions. With the upcoming single threaded modus, this code
can be run in the main thread however, so we need to take care of
KeyboardInterrupts explicitly.

This was done wherever we would catch *ALL* exceptions universally and
print out an error message.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-14 19:25:11 +01:00
Sebastian Spaeth
383ae9e647 Catch SystemExit and KeyboardInterrupt exceptions
Previously we did not catch KeyboardInterrupts explicitly as all of the
code was executed in forked child threads which would never receive
Ctrl-c exceptions. With the upcoming single threaded modus, this code
can be run in the main thread however, so we need to take care of
KeyboardInterrupts explicitly. As this is pretty highlevel code, we also
protect against receiving a SystemExit exception which is raised e.g. in
the ui.terminate() code by calling sys.exit().

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-14 19:25:11 +01:00
Sebastian Spaeth
fe9e5221b2 init.py: clean up 'import's
Make imports conform to PEP8 (one import per line), remove redundant or
unneeded imports.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-10 20:13:34 +01:00
Nicolas Sebrecht
3446aa9368 Merge branch 'ss/folder/base_clean-threadutil-import' into next
Conflicts:
	offlineimap/folder/Base.py
2011-01-10 18:58:05 +01:00
Sebastian Spaeth
a6b2b8014f folder/Base.py: No need to import InstanceLimitedThread explicitely
We already import threadutil, so no need to also import
threadutil.InstanceLimitedThread separately.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-10 18:56:39 +01:00
Nicolas Sebrecht
43096ad378 Merge branch 'ss/ui-remove-detector' into next 2011-01-07 19:38:12 +01:00
Sebastian Spaeth
c3540de763 Remove ui.detector class
The ui.detector class was not really needed and leads to the illusion
that we provide GUI plugins. For the sake of code maintainability we
don't :-).

Rather than having GUI names equivalent to the classes they are in
(which leads to weird names like TTY.TTYUI), this patch allows to give
each GUI an arbitrary string name. GUI names remain still unchanged in
this patch, the default UI when none was configured is TTY.TTYUI.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-07 19:37:48 +01:00
Nicolas Sebrecht
ee8a00cce2 Merge branch 'ss/ui' into next
Conflicts:
	offlineimap/folder/IMAP.py

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-05 19:31:08 +01:00
Sebastian Spaeth
de618d84f3 Save ui as self.ui in folder/Base class
Rather than regetting the ui with UIBase.getglobalui() all the time, we get it once in the base class and let all derivative classes just make use of self.ui rather than refetching the ui all the time, this makes for a bit less code and shorter lines.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-05 19:24:00 +01:00
Sebastian Spaeth
67089248da repository/*: replace UIBase.getglobalui() with getglobalui()
The latter is much shorter and looks nicer. UIBase was a very weird
name and with this patch, we don't need to use (or see) it from higher
level code anymore.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-05 19:24:00 +01:00
Sebastian Spaeth
c6d6dc814f Replace UIBase.getglobalui() with getglobalui()
The latter is shorter and looks nicer. UIBase was a very weird class
name for something that is "user visible". We don't need to use (or
see) it from higher level code for most of the code now.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2011-01-05 19:24:00 +01:00
Sebastian Spaeth
0b5b38d298 Define version constants etc in __init__.py
Move central constant definitions into __init__.py.  This does away
with version.py which contained nothing else and __init__.py is where
things like __VERSION__ are usually defined.

This commit also changes code to use offlineimap.__version__ rather
than offlineimap.version.__version__ as was before. Cleaned up some
duplicate or unneeded imports while touching those, formatting import
statements per PEP8 (one import per row).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-22 19:45:01 +01:00
Sebastian
4f57b94e23 Implement SSL certificate checking
Previously, we did not check at all the authenticy and validity of
the SSL server we connected to. This is bad as it allows
man-in-the-middle attacks etc. This patch remedies the situation
somewhat.

If we specify a sslcacertfile= setting in the Repository section,
validate the server cert (on python>=2.6 or abort with python<=2.5).

As before, no certificate check is performed without that option.
In the future, the hostname check should be made optional and also
a mutt-lick "accept this certificate forever" thing should be
implemented.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-16 19:15:33 +01:00
Sebastian
219eb8c47f Don't call open_new functions outside of any class
Move them into the correct classes, overriding the open() function.
This is what we intent to do anyway, so do it in a clean way.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-16 19:15:33 +01:00
Sebastian
800138d8a4 imaplibutil.py: remove unneeded includes
Signed-off-by: Sebastian Spaeth <Sebastian @SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-16 19:15:07 +01:00
Nicolas Sebrecht
1bfa125f49 Merge branch 'ss/use-optionparser' into next
Conflicts:
	offlineimap/init.py

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-15 20:14:59 +01:00
Sebastian Spaeth
85e8aea94f Convert to use OptionParser for command line handling.
Move the command line option handling from the more manual "getopts"
module to the full fledged "OptionParser". It has the advantage of
e.g. automatically creating the Help text that is shown with the
"-h/--help" option rather than having to hardcode the text and
format the line breaking manually.

Also, do away with the version check when invoking OfflineImap so we
do not have to change the version number in three places when bumping
it.

Rename startup() to run() which sounds more in line what other modules
call their run functions (e.g. Thread.run()).

Signed-Off-By: Sebastian Spaeth <Sebastian@SSpaeth.de>

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-15 20:02:27 +01:00
Nicolas Sebrecht
667dd30afe remove uneeded file
On Mon, Dec 13, 2010 at 03:03:20PM -0600, Sebastian Spaeth wrote:
>
> > ...From where is the "Repository" object used?
>
> Please delete the Respository clas (repository.py) for now. I am sorry
> it sneaked it (I blame my horrible jet leg on it). I would like to
> introduce it in a later topic, but not at this time.

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-13 22:07:11 +01:00
Nicolas Sebrecht
40dcab7134 Merge branch 'ss/remove-uneeded-includes' into next 2010-12-13 21:20:22 +01:00
Sebastian Spaeth
c20d655ea3 remove some unneeded includes
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-13 21:20:08 +01:00
Sebastian
b853b58578 Unbreak getting password from UI
Commit 9239a2d326 broke getting the password from the UI. This
unbreaks the change and adds some extended documentation and cleanups in
the functino en-passent.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-13 19:52:21 +01:00
Sebastian Spaeth
62712cbe15 Proper error message on invalid configured repository type
Previoiusly, we would just bomb out with a KeyError("Foo") if a user
configured a repository Type=Foo. Or in case he tried to sync from a
Maildir to a Maildir. Still abort with an Exception now, but with one
that explains what actually had happened.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-13 19:51:41 +01:00
Nicolas Sebrecht
1c106a4ce9 update version number everywhere it's needed
On 12/13/2010 12:25 PM, Nicolas Sebrecht wrote:

> The release number information is hard coded. Here is a quick fix to update it
> to the last release.
>
> We may introduce more elaborated stuff to define the release dynamically.

FYI: not sure if you all saw it or changed it, but there were three
places I always changed for each new release:

offlineimap.py
bin/offlineimap
offlineimap/version.py

in particular, the value in version.py must match the value in the
offlineimap(.py) file that someone uses to start the thing up.

Reported-by: John Goerzen <jgoerzen@complete.org>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-13 19:38:00 +01:00
Nicolas Sebrecht
b8aaf4cf43 imaputil.py: factorize the flag map
Instead of repeating a mapping table twice, once for each direction, it is only
stored once.  This is safer and faster.

As the patch stands, it makes no custom flags available.  The behaviour
is exactly as before.

Patch-written-by: Dan Christensen <jdc@uwo.ca>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
1b32d374b5 Import cProfile module before falling back to profile
the cProfile/profile modules are great for performance debugging. The
pure-python profile module has much more overhead though and the
cProfile module is recommended if it exists. This changes to import to
first try the cProfile module and then fall back to the profile
module. The cProfile/profiles modules are API compatible for all that
its worth...

If that does not exist we continue to complain as before.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
325dd833ba Make a main class OfflineImap that is being called
Rather than calling a function in a module, invoke offlineimap by
calling an OfflineImap object.

This removes code lying outside of objects; I prefer to keep code
within an object and provides us with a nicer Object encapsulation.

It will also ease the testing of Object functionality in unittests
when they are introduced.

Previously we would import and start Offlineimap like this:

from offlineimap import init
init.startup('6.2.0')

now we do:
from offlineimap import OfflineImap

offlineimap = OfflineImap()
offlineimap.startup('6.2.0')

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
35dd236155 Improve TTY ui to not always prepend 'sync account foo'
This is very excessive and a bit annoying. Output that information
only if the next line concerns a different account/thread than the
previous one. This quiets down the UI quite a bit without losing
information.

While modifying this line, use the newer Thread.name and not the as
per python doc's old syntax getName()

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
f68b626cb4 Don't display sleeping every second on the screen
Only every 10 seconds. Also fix up the documentation of that function
while at it. The Curses ui actually implements user abort it
seems. Not sure if we could do the same in the UIBase, but that is for
another time.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
0cdfffa04d Don't always sleep while waiting for exited threads
Rather than poll our exitthread Queue in a non-blocking fashion and
always sleep for 1 second inbetween, simply call it in a blocking
fashion which will return immediately when a thread has exited. This
is somewhat faster as we don't do unnecessary sleeps after a thread
exited.

Do note that we need to specify some timeout value here (the 60 chosen
is pretty arbitary, but what the value exactly is, is not that
important, it could be any positive value) in order to make the
Queue.get() call work with SIGINT (cf
http://bugs.python.org/issue1360).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
1b36c314c6 remove unneeded includes from syncmaster.py
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
7eca3f194f Prettify message formatting
Straightforward reformatting of the Error output to look nicer on the eyes.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Sebastian Spaeth
6e62da435b Fix Machine ui to not error out on ui.warn()
All other uis (especially BaseUI) define as warn(self, msg, minor = 0)
just MachineUI required minor without a default. This leads the
Machine UI to error out with an exception if we pass it
ui.warn("string") which is the common thing in our code base. This
patch is therefore small but critical in fixing this UI.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Johannes Stezenbach
573d7ed52a Change X-OfflineIMAP header format
Change the X-OfflineIMAP header to work around possible Exchange MAPI
table overflow problem described in
http://article.gmane.org/gmane.mail.imap.offlineimap.general/1699
(It is unknown whether this problem still exits in current
Exchange versions, but let's assume the worst.)

The X-OfflineIMAP header is neccessary with some IMAP servers to
reliably determine the UID of a new messages uploaded to the server
by using the "UID SEARCH HEADER name string" command.  Since this
command compares header name and value it is sufficient to have
a unique header value and a non-unique header name.

Note that a message can have more than one X-OfflineIMAP header if
the message was copied between IMAP folders multiple times.

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2010-12-09 19:52:48 +01:00
Janne Blomqvist
d687999a66 Backwards compatibility for python 2.4
Python 2.4 doesn't allow try...except...finally clauses, see PEP
341. Also, yield statements inside try...finally is not allowed. The
commit changes the logic to no longer use those syntactical features.

Signed-off-by: Nicolas Sebrecht <ni.s@laposte.net>
2010-12-09 19:52:48 +01:00
buergi
9239a2d326 Bugfix patch for offlineimap
Hello John,

i fixed some tiny bugs in offlineimap, mainly just for myself. They are
more dirty fixes than real bugfixes since I'm missing the deeper insight
into the code.
Especially the first one for Curses.py is very dirty and breaks the
scaling of the interface when the terminal size changes, but at least
the terminal is in proper state after exiting offlineimap.

In the order of appearance in the patchfile:
1. 'fixes' terminal breakage on quit of curses interface in python 2.6
to 2.6.5 (fixed since 2.6.6 http://bugs.python.org/issue7567)
2. fixes netrc password authentication
3. fixes user name querying from netrc

The patch is made for git revision 6b1cb5e036

Thanks a lot for the great application!

Best regards,
buergi
2010-08-20 08:29:47 -05:00
John Goerzen
9c6581eb39 Now support multiple -k options on the command line.
Patch by Vladimir Marek

fixes #113
2010-04-21 09:17:08 -05:00
Michal Schmidt
caa7d8a128 much faster deleting of messages from LocalStatus
After tens of thousands of messages on the IMAP server were deleted it
takes offlineimap extremely long time (several hours of high CPU usage)
to delete them locally. It spends almost all the time modifying
LocalStatus. It processes the messages one by one, rewriting the
folder's status file in LocalStatus after each message.

It is much more efficient to save the status file only once, after
removing all the messages from the messagelist.

Deleting lots of messages now takes seconds instead of hours.

This should solve Debian bug #518093:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=518093

Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
2010-03-31 21:32:51 -05:00
Mike Dawson
30344587d9 Patch for error handling / separation of accounts etc.
Dear All,
I have made the attached patch to try and make offlineimap a bit more
stable in challenging situations.  It's extremely useful in slow
connection environments - but sometimes if one account had the wrong
password or the connection went down then unfortunately the whole
program would crash.

I have tested this on our connection and tried throwing at it just about
every situation - connection, up down, up, down again, change password,
error whilst copying one message, etc.  I have been running this patch
for the last 5 days or so syncing 6 accounts at the moment...  It seems
to work and stay alive nicely (even if your connection does not)...

Hope that this can go in for the next release... Please let me know if
anyone notices any problems with this...

Regards,

-Mike

-- Attached file included as plaintext by Ecartis --
-- File: submit

From 1d6777cab23637eb830031c7cab0ae9b8589afd6 Mon Sep 17 00:00:00 2001
From: mike <mike@mikelaptop.(none)>
Date: Mon, 24 Aug 2009 19:37:59 +0430
Subject: [PATCH] This patch attempts to introduce a little more error handling - e.g.
 if one account has an error because of a changed password or something
 that should not affect the other accounts.

Specifically:
If one sync run has an issue this is in a try-except clause - if it
has an auto refresh period the thread will sleep and try again - this
could be quite useful in the event of the connection going down for a
little while, changed password etc.

If one folder cannot be created an error message will be displayed through
the UI and the program will continue (e.g. permission denied to create a folder)

If one message does not want to copy for whatever resaon an error message
will be displayed through the UI and at least the other messages will
be copied

If one folder run has an exception then the others will still run
2009-08-28 00:01:10 -05:00
John Goerzen
43ead072a1 Merge branch 'master' of ssh://jpgarch@complete.org/~jpgarch/git/offlineimap 2009-08-24 00:02:13 -05:00
Toke Høiland-Jørgensen
a781016633 Fix ssl socket wrap deprecation warning. 2009-08-24 00:01:54 -05:00
John Goerzen
1148df7685 Merge branch 'maxage'
Conflicts:
	offlineimap/folder/IMAP.py
2009-08-16 09:29:00 -05:00
Mike Dawson
cde94e5047 Patch for maxage and maxsize options
Dear All,
Attached is the patch that I have developed to provide maxage and
maxsize options.  You can thus sync only the last x days of messages and
exclude large messages.  All details in the attached git file.

Regards,

-Mike

-- Attached file included as plaintext by Ecartis --
-- File: submit

From 04fead2b46a79675a5b29de6f2b4088b9c9448e5 Mon Sep 17 00:00:00 2001
From: mike <mike@mikelaptop.(none)>
Date: Sun, 16 Aug 2009 17:00:49 +0430
Subject: [PATCH] Patch to provide maxage and maxsize account options to exclude old/large messages

This is designed to make offlineimap even better for low bandwidth connections.

maxage allows you to specify a number of days and only messages within
that range will be considered by offlineimap for the sync.  This can be
useful if you would like to start using offlineimap with a large
existing account and do not want to import large archives of mail.

maxsize allows you to specify the maximum size of a message to consider so
that you can exclude messages with large attachments etc.

In both cases the cachemessagelist function of the folder was modified to ignore
messages that do not meet the criteria.  If the criteria are not specified
then the existing code will be executed the same as before.  If a message
does not meet the criteria it will be as though this message does not exist
- offlineimap will completely ignore it.  It will not have flags updated,
it will not be deleted, it will not be considered at all.

When operating against an IMAP repository a server side search function
is used.  This of course requires support for server side search.

I have tested this with either option, no options etc. against IMAP, Maildir
and Gmail.  I have run variations of this patch here for the last 3 weeks or
so syncing about 4 accounts normally.
2009-08-16 09:27:49 -05:00
John Goerzen
2433dc9f06 Merge branches 'master' and 'master' of ssh://jpgarch@complete.org/~jpgarch/git/offlineimap 2009-08-12 15:25:26 -05:00
John Goerzen
9e6427a443 update version info 2009-08-12 00:41:19 -05:00