Commit Graph

640 Commits

Author SHA1 Message Date
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