Commit Graph

328 Commits

Author SHA1 Message Date
Eygene Ryabinkin
863113efa3 Match header names case-insensitively
http://tools.ietf.org/html/rfc5234#section-2.3 says that ABNF strings
are case-insensitive.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-06-30 16:41:17 +04:00
Adam Spiers
807f3da880 addmessageheader(): add debug for header insertion
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-06-24 23:36:48 +04:00
Adam Spiers
37f74d859a addmessageheader: fix case #2 and flesh out docstring
The example illustrations were slightly cryptic;
modify them to be more obvious.

Fix case #2 (message starts with two line breaks)
where additional line break was shown and coded.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-06-24 23:25:45 +04:00
Adam Spiers
afead6c48e Rename addmessageheader()'s crlf parameter to linebreak
The parameter's value is a string representing the linebreak,
and can sometimes contain just '\n', in which case naming it
crlf is slightly misleading.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-06-24 23:12:06 +04:00
Eygene Ryabinkin
968ffc20bd More clearly show results of folder name translation
For cases like
  http://article.gmane.org/gmane.mail.imap.offlineimap.general/6468
it is beneficial to see that folder name was translated and the result
of this translation on a single line: having log like
{{{
Folder Boring/Wreck [acc: tmarble@info9.net]:
 Syncing Boring/Breck: Gmail -> Maildir
}}}
with translated name on the "Folder" line and original one on the
"Syncing" line isn't very intuitive.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-06-24 18:48:58 +04:00
Eygene Ryabinkin
e8db1217d4 Fix improper header separator for X-OfflineIMAP header
For servers without UIDPLUS we are inserting additional header
just after transformation '\n' -> CRLF was done.  addmessageheaders()
was written to work with just '\n' as the separator, so X-OfflineIMAP
header wasn't preceeded by the CRLF, but just by '\n'.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-06-01 22:12:26 +04:00
Abdo Roig-Maranges
1690e5f74e Copymessageto should not be private since we override it
private methods prevent them from being overriden on derived classes. In
GmailFolder we need to override copymessageto, so it can't be private.

Before this commit, copymessageto was made private in Base but not in
GmailFolder. The end result was that labels were not set when copying
the message content, and always needed to be set on the label copying
pass.

Pointyhat-to: Eygene Ryabinkin
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-11 22:44:57 +04:00
Abdo Roig-Maranges
8c43e52173 Fix multiple typos in var, function and exception names
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-07 18:29:47 +04:00
Abdo Roig-Maranges
8dd6f7893c Add import for OfflineImapError
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-07 18:29:47 +04:00
Abdo Roig-Maranges
8b4f86be67 Class LocalStatusFolder: remove duplicate cachemessagelist()
Remained from GMail label sync merge.

Pointyhat-to: Eygene Ryabinkin
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-07 18:29:47 +04:00
Abdo Roig-Maranges
1300f2289b deletemessageheaders(): use passed list of headers to remove
... and not self.filterheaders.  With the current code this change
is no-op (since self.filterheaders is always passed as header_list),
but it is a bug in general.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-07 18:29:47 +04:00
Abdo Roig-Maranges
1b954c3b4c Add ability to migrate status data across backends
If when we request a LocalStatus folder, the folder has to be created,
we look whether the other backend has data, and if it does we migrate
it to the new backend.

The old backend data is left untouched, so that if you change back say
from sqlite to plaintext, the older data is still there.  That should
not lead to data loss, only a slower sync while the status folder gets
updated.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-06 23:37:11 +04:00
Abdo Roig-Maranges
214137eb7b Improvements to the SQlite-based local status folder
* Do not inherit LocalStatusSQLiteFolder class from the plaintext
    one.

  * Use some functions already in BaseFolder in both, plaintext and
    sqlite classes.

  * Add a saveall method. The idea is that saveall dumps the entire
    messagelist to disk, while save only commits the uncommited
    changes. Right now, save is noop for sqlite, and equivalent to
    saveall for plaintext, but it enables to be more clever on when we
    commit to disk in the future.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-06 23:37:11 +04:00
Abdo Roig-Maranges
09556d645e Adapt plain status folder to gmail labels stuff
* Implements Status Folder format v2, with a mechanism to upgrade an
    old statusfolder.

  * Do not warn about Gmail and GmailMaildir needing sqlite backend
    anymore.

  * Clean repository.LocalStatus reusing some code from
    folder.LocalStatus.

  * Change field separator in the plaintext file from ':' to '|'. Now
    the local status stores gmail labels. If they contain field
    separator character (formerly ':'), they get messed up. The new
    character '|' is less likely to appear in a label.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-06 23:37:11 +04:00
Abdó Roig-Maranges
789e047734 Extend handling of GMail labels header
Format headers X-Label and Keywords as a space separated list and all
other ones as comma-separated entities.  This makes OfflineIMAP label
handling to be compatible with some user agents that recognise these
headers.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-06 23:37:03 +04:00
Abdó Roig-Maranges
0e4afa9132 Make GmailFolder sync GMail labels
When synclabels config flag is set to "yes" for the GMail repo,
offlineimap fetches the message labels along with the messages, and
embeds them into the body under the header X-Keywords (or whatever
'labelsheader' was set to), as a comma separated list.

It also adds an extra pass to savemessageto, that performs label
synchronization on existing messages from GMail to local, the same way
it is done with flags.

We also introduce GmailMaildir repository that adds functionality to
change message labels.  It keeps track of messages modification time,
so one can quickly detect when the labels may have changed.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-06 23:36:06 +04:00
Abdó Roig-Maranges
9319ae212b Restructured folder/IMAP code
In preparation for GMail label sync, we had split our some functionality
that will be needed further into their own functions.  This also permitted
the code to look more compact and concise.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-06 23:03:21 +04:00
Abdó Roig-Maranges
5391476dfb Add ability to trim some local mail headers
When filterheaders is set to a comma-separated list of headers,
OfflineIMAP removes those headers from messages before uploading them
to the server.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-03 14:45:28 +04:00
Eygene Ryabinkin
844ca6b08c Don't embed CRLF multiple times when saving a message
Since we just do multiple passes for saving the message without
actually modifying its content (apart from header insertion that
is CRLF-clean), we can change line ends to the proper CRLF just
once.

And we can also get message's date only once too.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-03 14:43:11 +04:00
Abdó Roig-Maranges
0c4fe6bada Bugfix: make change_message_uid to update messagelist's filename
This broke code that relied on the filename being up to date in memory
after messages are copied.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-02 19:28:28 +04:00
Abdó Roig-Maranges
697ca8a229 Changed NotImplementedException to NotImplementedError
It seems NotImplementedException does not exist. It must be a relic
from old Python...

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-05-02 19:23:01 +04:00
Eygene Ryabinkin
6cbd2498ae Refactoring: make functions to be private if we can
Make external API of class/module to be smaller, explicitely mark
all internal functions.  Also annotate methods that are implemented
as the part of the parent class interface.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-04-30 19:35:56 +04:00
Stefan Huber
af2d6dc5e1 Fix: Undefined variable 'this' should be 'self'
Pointyhat-to: Eygene Ryabinkin
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-03-06 10:48:34 +04:00
Eygene Ryabinkin
829c9cf4be Introduce dynamic filtering for repository folders
Allow people who want folder filtering to depend on the external
conditions or to make it dynamic for other reasons, to do what
they want.

New repository configuration knob 'dynamic_folderfilter' was
introduced; it defaults to 'False' that matches historical behaviour.

GitHub: #73
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-03-02 16:37:41 +04:00
Eygene Ryabinkin
b01274ce38 Fix double release of IMAP connection object
This commit fixes the case when we're invoking releaseconnection()
for a given imapobj twice.

This bug manifests itself as
{{{
ValueError: list.remove(x): x not in list

  File "[...]/offlineimap/folder/IMAP.py", line 615, in savemessage
    self.imapserver.releaseconnection(imapobj)
  File "[...]/offlineimap/imapserver.py", line 130, in releaseconnection
    self.assignedconnections.remove(connection)
}}}

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2014-02-26 17:51:48 +04:00
Eygene Ryabinkin
1ef506655c Catch two instances of untested regexp matches
They could possibly lead to the problems mentioned in
  https://github.com/OfflineIMAP/offlineimap/issues/6
though there are no sound evidences for this.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-08-30 21:50:08 +04:00
Eygene Ryabinkin
69765a3ef0 Properly call error() function from ui.UIBase
Second argument is exception traceback, not the message; without this
tracebacks like mentioned in
  http://permalink.gmane.org/gmane.mail.imap.offlineimap.general/5712
were happening when this exception handling block was hit.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-08-30 21:49:09 +04:00
X-Ryl669
3bc66c0858 Add support for alternative message date synchronisation
Global or per-repository option utime_from_message tells OfflineIMAP
to set file modification time of messages pushed from one repository
to another basing on the message's "Date" header.

This is useful if you are doing some processing/finding on your
Maildir (for example, finding messages older than 3 months),
without parsing each file/message content.

From: Cyril RUSSO <boite.pour.spam@gmail.com>
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-08-09 10:48:00 +04:00
Adam Spiers
d39a1f864f make savemessage() handle NO response to APPEND correctly
IMAP servers can return `NO` responses to the `APPEND` command,
e.g. here's an example response from Groupwise's IMAP server:

    NO APPEND The 1500 MB storage limit has been exceeded.

In this case, savemessage() should abort the repository sync rather
than returning UID 0 which would cause the local copy of the message
being saved to get irreversibly deleted.

Signed-off-by: Adam Spiers <offlineimap@adamspiers.org>
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-08-02 16:41:54 +04:00
Eygene Ryabinkin
41cb0f577f Prune trailing whitespaces from code and documentation
They are redundant in all pruned cases and sometimes even create some
problems, e.g., when one tries to jump through paragraphs in vi.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-07-21 23:00:23 +04:00
Dmitrijs Ledkovs
e8c40a9285 Merge branch 'master' into next 2013-07-10 02:49:52 +01:00
Adam Spiers
aa5202396c fix typos 2013-03-27 12:42:32 +00:00
Eygene Ryabinkin
611f6e89c0 IMAP class: don't suggest multithreading in single-threaded mode
Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-02-11 23:34:28 +04:00
Eygene Ryabinkin
f4140cbbed Create global instance of command-line options
This eases testing of option values inside the code.  This instance
is implemented as the read-only copy of the obtained 'options' object,
so callers won't be able to modify its contents.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
2013-02-11 23:34:18 +04:00
X-Ryl669
5c842c01bd Fix deadlock for IMAP folder synced in singlethreaded mode
The problem lies in the fact that offlineimap.folder.Base's method
syncmessagesto_copy() uses threaded code everytime it is suggested by
the derived class's suggeststhreads() (currently, only IMAP does this
suggestion), but offlineimap/init.py will not spawn the
exitnotifymonitorloop() from offlineimap.threadutil.

The root cause is that ExitNotifyThread-derived threads need
offlineimap.threadutil's exitnotifymonitorloop() to be running the
cleaner for the exitthreads Queue(), because it fills the queue via
the run() method from this class: it wants to put() itself to the
Queue on exit, so when no exitnotifymonitorloop() is running, the
queue will fill up.  And if this thread is an instance of
InstanceLimitedThread that hits the limit on the number of threads,
then it will hold the instancelimitedsems[] semaphore will prevent
other InstanceLimitedThread()s of the same name to pass its start()
method.

The fix is to avoid using threaded code if we're running
single-threaded.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
Obtained-from: X-Ryl669 <boite.pour.spam@gmail.com>
2013-02-05 07:53:25 +04:00
Tobias Thierer
caef9a72fc Fix IMAP folder throwing away time zone when parsing email Date headers
Fix imapfolder.getmessageinternaldate misparsing the Date:
header from emails due to a bug or surprising behaviour by
email.utils.parsedate. This is because email.utils.parsedate's
return value contains the unadjusted hour value from the string
parsed but does not include information about the time zone in
which it is specified. For example (Python 2.7.3):

$ python -c "import email.utils;
  print email.utils.parsedate('Mon, 20 Nov 1995 19:12:08 -0500')"
 (1995, 11, 20, 19, 12, 8, 0, 1, -1)

(the -1 is the isdst field); the -0500 time zone is completely
ignored, so e.g. the same input with time "19:12:08 +0300" has
the same result. When passed to time.struct_time as allowed per
the parsedate documentation, this time is interpreted in GMT and
thus deviates from the correct value by the timezone offset
(in this example, -5 hours).

I consider this a bug in email.utils.parsedate: In my opinion,
since the return value of the parsetime doesn't include a timezone,
it should be expressed in terms of UTC rather than in terms of the
time zone from the Date header; the existence of
email.utils.parsedate_tz, to which I've switched, indicates that
maybe the authors were aware of this problem.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-10-03 11:16:13 +02:00
Dave Abrahams
e94642bb4d Determine folder syncing on Folder initialization
Rather than later when retrieving them by IMAP, we determine the
"sync_this" value of a folder on Folder() initialization.

This also fixes a bug where folder structure was not propagated when
a folder was filtered out but included in the folderincludes list.

Patch by Dave, split and modified slightly by Sebastian

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-09-01 02:30:46 +02:00
Sebastian Spaeth
3cb2ddccb8 Use "with lock" pattern
While looking at the code to investigate if an why we sometimes don't
seem to honor the write lock, I made it use the more modern "with lock:"
pattern.

Still have not found out how we could ever be using 2 instances of the
LocalStatusFolder for the same folder.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-08-31 22:34:53 +02:00
Dmitrijs Ledkovs
d45872e59c Add missing OfflineImapError import in folder/UIDMaps.py
Bug-Debian: http://bugs.debian.org/671279
Reported-by: Ansgar Burchardt <ansgar@debian.org>
Signed-off-by: Dmitrijs Ledkovs <xnox@debian.org>
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
2012-07-30 20:10:11 +02:00
Sebastian Spaeth
36156fa985 Remove the APPENDUID hack, previously introduced
As Gmail was only announcing the presence of the UIDPLUS extension
after we logged in, and we were then only getting server
capabilities before, a hack was introduced that checked the
existence of an APPENDUID reply, even if the server did not claim
to support it.

However, John Wiegley reports problems, where the APPENDUID would
be None, and we attempt to go this path (it seems that imaplib2
returns [None] if there is no such reply, so our test here for "!="
might fail. Given that this is an undocumented imaplib2 function
anyway, and we do fetch gmail capabilities after authentication,
this hack should no longer be necessary.

We had problems there earlier, where imapobj.response() would
return [None] although we had received a APPENDUID response from
the server, this might need more debugging and testing.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-06-06 10:13:42 +02:00
David Logie
a614f9a735 Fix str.format() calls for Python 2.6.
Python 2.6 requires a slightly different string formatting that >2.7.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-06-02 18:25:51 +02:00
Sebastian Spaeth
61e754c65e Do not try to release IMAP connection twice
Reported by sharat87 in https://github.com/spaetz/offlineimap/pull/38,
he would often get an unhandled Exception when trying to
releaseconnection() a connection that was not in the pool of
connections.

The reason this could happen is that when folder.IMAP.quickchanged()
raises an Exception in select(), we would release the connection in the
"except" handling, and than release the same connection in the "finally"
clause, which led to the error. The right thing is to only release the
connection once, of course.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-04-21 13:32:14 +02:00
Sebastian Spaeth
925538f02d docs: Fix docstrings to proper .rst syntax
Prevents compile errors when creating the user documentation.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-24 11:20:22 +01:00
Sebastian Spaeth
0e6b4ae798 Revert "Clean up and improve APPENDUID handling"
This reverts commit 4d47f7bf3c.

This is one of two candidates for introducing the instabilities that
John Wiegley observed. We need to reintroduce with careful testing only.

The original patch has been mostly reverted.
2012-02-24 08:35:59 +01:00
Sebastian Spaeth
bc73c11239 Revert "Don't CHECK imapserver after each APPEND"
This reverts commit 47390e03d6.

It is one of two potential candidates for the APPENDUID
regression that John Wiegley reported. We need to examine this
carefully before reintroducing this patch.

Resolved Changelog.draft.rst conflict.
2012-02-24 08:31:31 +01:00
Sebastian Spaeth
256a26a649 dry-run mode: Protect us from actually deleting a message in dry-run mode
Document which functions honor dry-run mode and which don't.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-17 13:17:05 +01:00
Sebastian Spaeth
5ef69e95c0 Prevent modifications on a folder level to occur in dry-run
Prevent savemessage(), and savemessageflags() to occur in dryrun mode in
all backends. Still need to protect against deletemessage().

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-17 13:17:05 +01:00
Sebastian Spaeth
bf44d30b46 UIDMaps: Better error message when not finding a mapping
Bail out with a better Exception and error text. The whole mapped
UID situation needs to be improved though.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-17 08:48:59 +01:00
Sebastian Spaeth
7da50e638d folder/IMAP: better error when savemessage fails
If we cannot identify the new UID after a sendmessage(), log a better error
message, including the server response for better debugging.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-16 16:49:06 +01:00
Sebastian Spaeth
10dd317026 Folder: Implement __eq__ for folders
This allows to compare folders directly with strings. It also allows
constructs such as "if 'moo' in repo.getfolders()".

See the code documentation for the exact behavior (it basically is equal if
it's the same instance *or* a string matching the untranslated folder name.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-16 11:03:33 +01:00
Sebastian Spaeth
5c598d7e74 dict.has_key(a) --> a in dict
has_key() is gone in python3, so use a more modern syntax here.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:43 +01:00
Sebastian Spaeth
8aba2800e6 long(0) -> 0
There is no need to cast 0 to 'long' even if we want to compare it to long
numbers in modern pythons.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:43 +01:00
Sebastian Spaeth
e6e708ec78 Don't use sort() on dict values()
This won't work in python3 anymore, so just use sorted() when needed.
In one case, we could remove the sort() completely as were were sanity checking
one line above, that we only having one UID as response which makes sorting
unneeded.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:43 +01:00
Sebastian Spaeth
b33f2452f0 Use "from . import" for relative imports
Will fail in python3 otherwise.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:43 +01:00
Sebastian Spaeth
81fc20c7ca Remove python<2.6 import workarounds (set & ssl)
'set' is builtin since python2.6, so remove the imports. Also 'ssl' exists
since 2.6 and has everything we need, so no need for conditional import
tests here anymore.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:42 +01:00
Sebastian Spaeth
c5468ae599 raise Exception, "text" --> raise Exception("text")
To have the code work in python3, we need to convert all occurences of

raise Exception, "text" to be proper functions. This style also adheres to PEP8.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:42 +01:00
Sebastian Spaeth
55da31c84b octal notation 0700 -> 0o700
Use octal notation that python3 understands. Works >=python2.6

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:42 +01:00
Sebastian Spaeth
0844d27f9f except Ex, e: --> except Ex as e:
Nudge us towards python3 compatability by converting deprecated python2 syntax.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-06 17:41:42 +01:00
Sebastian Spaeth
51728ed815 Remove Gmail realdelete option
It can lead to potential dataloss (see recent commit log where I added a
scary warning about it to offlineimap.conf).

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-02-04 21:08:44 +01:00
Sebastian Spaeth
47390e03d6 Don't CHECK imapserver after each APPEND
Most servers support the UIDPLUS extension, and we don't have to search
headers after each uploaded message. There is no need to CHECK the imap
server after each message when there is no need to search headers.

I have not measured the performance impact on real world servers, but
this lets us do less unneeded work in the common case.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-20 14:43:12 +01:00
Sebastian Spaeth
4d47f7bf3c Clean up and improve APPENDUID handling
We were not cleaning out possibly existing APPENDUID messages before
APPENDing a new message. In case an old message were still hanging
around, this could *possibly* lead to retrieving and old UID. Things
should have been fine, but we do want to play safe here.

Also, make use of the "official" imaplib2 .response() command rather
than the internal _get_untagged_response() function.

Remove the hack that we would be looking for APPENDUID responses even if
the server claimed not to support the UIDPLUS ext. We now poll server
CAPABILITIES after login, and Gmail does provide us with the UIDPLUS
capability after login.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-20 14:33:16 +01:00
Sebastian Spaeth
165cf5cb4f Use modern "with open() as file"
Saves a LOC and guarantees that the file will be closed

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-19 12:03:03 +01:00
Sebastian Spaeth
de1e03b065 Tweak code documentation
Minor comment changes

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-19 12:03:03 +01:00
Sebastian Spaeth
d3c693be7d Rename folder.saveuidvalidity()
Simply rename to folder.save_uidvalidity()

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-19 12:03:03 +01:00
Sebastian Spaeth
eb616da602 Rename folder.isuidvalidityok()
Use nicer name folder.check_uidvalidity() and improve code documentation

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-19 12:03:03 +01:00
Sebastian Spaeth
297a618441 Rename folder.getsaveduidvalidity(), folder.getuidvalidity()
Modernize names to: folder.get_saveduidvalidity(), folder.get_uidvalidity()

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-19 12:03:03 +01:00
Sebastian Spaeth
9453e1d955 Fix getuidvalidity crash (UIDVALIDITY returning None)
Rename getuidvalidity -> get_uidvalidity and cache the IMAP result.

1) Start modernizing our function names using more underscores
2) IMAPs implementation of get_uidvalidity was removing the UIDVALIDITY result
   from the imaplib2 result stack, so subsequent calls would return "None".
   As various functions can invoke this, this led to some errors that we
   avoid by caching the current UIDVALIDITY value in the Folder instance.

There are more simplifications and improvements to be made.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-19 12:02:13 +01:00
Sebastian Spaeth
6dc74c9da5 Improve delete performance with SQLITE backend
When deleting many (eg 2000) mails using the SQLITE backend, this takes
a long time durig which OfflineImap can not be aborted via
CTRL-C. Thinking it had frozen permanently, I killed it hard, leaving a
corrupted db journal (which leads to awkwards complaints by OLI on
subsequent starts!). That shows that delete performance is critical and
needs improvement.

We were iterating through the list of messages to delete and deleted
them one-by-one execute()'ing a new SQL Query for each message. This
patch improves the situation by allowing us to use executemany(), which
is -despite still being one SQL query per message- much faster. This is
because rather than performing a commit() after each mail, we now do
only one commit() after all mails have been deleted.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-17 04:17:15 +01:00
Sebastian Spaeth
d72bb88729 Improve error message
Add *what* UID was returned in case savemessage did not return a UID>0

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-09 09:57:36 +01:00
Sebastian Spaeth
3284e010ff Revert "use .response() rather _get_untagged_response()"
Recently the internal function use of imaplib2's _get_untagged_response()
was switched to use the public documented .response() function (which
should return the same data). However within a few fays we received reports
that both uses of a) the UIDVALIDITY fetching and b) the APPENDUID fetching
returned [None] as data although the IMAP log definitely shows that data
was returned. Revert to using the undocumented internal imaplib2 function,
that seemed to have worked without problems. This needs to be taken up to
the imaplib2 developer.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-09 09:51:43 +01:00
Sebastian Spaeth
7184ec28cc Sanity check return value of UIDVALIDTY response
We have a reported case where response('UIDVALIDITY') returned [None]
which results in an ugly non-intuitive crash. Sanity check and report
something nicer.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-08 12:26:47 +01:00
Sebastian Spaeth
50de2174bf Allow to pass 'force' arg to selectro() to enforce a new select
Pass through the 'force' argument from selectro() to select() so that it
can also enforce a new SELECT even if we already are on that folder.

Also change the default parameter from '0' to 'False' to make clear that
this is a Bool.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-08 11:29:54 +01:00
Sebastian Spaeth
6e9e256946 Ignore lower-case custom Maildir flags
Do not read in custom maildir flags, or we would try to sync them over
the wire. The next step will be to merge flag writes with existing
custom flags, so we don't lose information.

The long term goal will be to attempt to sync flags to the other side,
of course.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-07 22:00:45 +01:00
Sebastian Spaeth
d549cbdac9 Fix code comment on flag stripping
Fix code comment that we preserve custom dovecot flags. We discard them.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-07 21:34:57 +01:00
Sebastian Spaeth
0b85a34fc7 Maildir: flagmatchre --> re_flagmatch
Overlooked a variable renaming when merging in a branch.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-07 13:10:41 +01:00
Sebastian Spaeth
3a1eab7383 Remove a stray debug output that slipped in the previous commit.
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-07 01:31:24 +01:00
Sebastian Spaeth
ec63b4fe6b replace imaplib internal _get_untagged_response with public functions
We were using the internal imaplib2 _get_untagged_response() functions a
few times. Replace 3 of these calls with 2 calls to the public function
response() rather than fudging with internals that could change anytime.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-07 01:28:20 +01:00
Sebastian Spaeth
17f60f7233 Remove from __future__ import with_statements
These were needed for python <2.6 compatability, but since we depend on
python 2.6 now, these can go.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 23:13:55 +01:00
Sebastian Spaeth
8fc7227189 SEVERE: Fix getting wrong UID back on IMAP upload
This change looks harmless, but it fixes a severe bugfix, potentially
leading to data loss! It fixes the "on n new uploads, it will redownload
n-1, n-2, n-3,... messages during the next syncs" condition, and this is
what happens:

If there are more than one Mails to upload to a server, we do that by
repeatedly invoking folder.IMAP.savemessage(). If the server supports
the UIDPLUS extension we query the resulting UID by doing a:

imapobj._get_untagged_response('APPENDUID', True)

and that is exactly the problem. The "True" part causes the reply to
remain in the "response stack" of the imaplib2 library. When we do
the same call on a subsequent message and the connection is still on the
same folder, we will get the same UID response back (imaplib2 only looks
for the first matching response and returns that). The only time we
clear the response stack, is when the IMAP connection SELECTS a
different folder.

This means that when we upload 10 messages, the IMAP server gives us
always the same UID (that of the first one) back. And trying to write
out 10 different messages with the same UID will confuse OfflineIMAP.

This is the reason why we saw the ongoing UPLOADING/DOWNLOADING behavior
that people reported. And this is the reason why we saw the
inconsistency in the UID mapping in the IMAP<->IMAP case.

I urge everyone to upgrade ASAP. Sorry for that, I don't know why the
problem only became prevalent in the recent few releases as this code
has been there for quite a while.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 21:57:48 +01:00
Sebastian Spaeth
0ea6c6ed47 Forgot to change a variable name in all cases
the newuid var was renamed new_uid but there was one leftover. Fixed.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 21:41:04 +01:00
Sebastian Spaeth
78a37f27ef WIP, revamp how we treat top-level dirs
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 19:08:48 +01:00
Sebastian Spaeth
ff50585007 Folder-Maildir.savemessageflags(): Only parse file name if flags changed
Rather than always parsing the filename, we only need to do so if the flags
have actually changed, otherwise we can keep the filename.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 19:08:48 +01:00
Sebastian Spaeth
de537dc09c Implement change_message_uid
Previously, assigning a new UID to a mapped IMAP or Maildir repository
was done by loading the "local" item, saving it under a new UID and
deleting the old one. This involved lots of disk activity for nothing
more than an effective file rename in Maildirs, and lots of network
usage in the MappedUID cases.

We do this on every upload from a local to a remote item, so that can
potentially be quite expensive. This patch lets backends that support it
(Maildir, MappedUID) efficiently rename the file rather than having to
read the mail content, write it out as a new file and delete the old
file. This speeds up uploads from Maildir and the MappedUID server.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 19:08:48 +01:00
Sebastian Spaeth
09ce56c594 Factor out creating a Maildir message filename
Various functions (such as change_message_uid) will want to construct
maildir filenames, so factor out the code into a helper.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 19:08:48 +01:00
Sebastian Spaeth
6fe808338c Refactor parsing out maildirs filename components
Create a helper function that retrieves the UID, folder MD5, and Flags from
a message filename.

We need these items when we simply want to rename (=new UID) a Maildir
message file later. The new function can give us these components.

Rework, so we cache the calculation of the folder's md5 value once, it
never changes and we call it a lot.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 19:08:45 +01:00
Sebastian Spaeth
d5666ce91d Don't create invalid maildir names with lower case maildir flags
If someone had a custom :2,a flag, adding a new flag would lead to the
invalid maildir filename ...a:2,... due to regex deficiencies not coping
with this. Fix this so we alway produce valid maildir names.

Note that custom flags are still problematic: as the syncing to the
remote IMAP server will fail, the next sync will assume that they have
been removed from the remote IMAP side and they will be removed from the
local Maildir then. We will need to think about how to handle this. At
least, with this patch we won't lose standard flags and won't produce
invalid maildir names.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-06 13:05:08 +01:00
Sebastian Spaeth
64f5e557bc Fix (harmless) regex flaw when determining maildir flags
The regex for catching Maildir message flags was
self.infosep + '.*2,([A-Z]+)' (infosep being ':').

The .* is bogus, as there is nothing between the : and the 2, per
maildir name specification, so remove that unneeded piece.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-05 14:39:09 +01:00
Sebastian Spaeth
0ccf06d5e6 Implement clean CTRL-C termination
Previously, we would simply bail out in an ugly way, potentially leaving
temporary files around etc, or while writing status files. Hand SIGINT
and SIGTERM as an event to the Account class, and make that bail out
cleanly at predefined points. Stopping on ctrl-c can take a few seconds
(it will e.g. finish to transfer the ongoing message), but it will shut
down cleanly.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2012-01-04 19:31:27 +01:00
Sebastian Spaeth
8ec6980c96 Don't fail on empty LocalStatus cache files
As reported in https://github.com/spaetz/offlineimap/pull/2, we would
fail when files are empty because file.read() would throw attribute
errors.

Fix this by removing the superfluous read() check and additionally log
some warning message.

Reported-by: Ralf Schmitt
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-12-01 23:57:54 +01:00
Sebastian Spaeth
f4a32bafd6 Pass ui.registerthread an Account() and not a name as string
This way, we can use all the account functions such as set_abort_event()
from the ui if needed.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-11-03 13:45:44 +01:00
Sebastian Spaeth
d54859a931 Don't setDaemon explicitly, it's done inherently
All ExitNotifyThreads and InstanceLimitThreads are setDaemon(True) in their
constructor, so there is no need to do that again in the code.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-11-02 11:29:23 +01:00
Sebastian Spaeth
656405616d Drop connection if it might be bad on APPEND
1) Differentiate error messages between imaplib.abort and imaplib.error
exceptions in the log.

2) Drop connections in the case of imapobj.error, it also might denote a
   broken connection.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-11-02 10:36:30 +01:00
Sebastian Spaeth
33b4a16dac Fix mbox.select(foldername) readonly parameter comparison
The default parameter value was "None", and we were comparing that
directly to the imaplib2 value of is_readonly which is False or True, so
the comparison always returned "False".

Fix this by setting the default parameter to "False" and not
"None". Also convert all users of that function to use False/True.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-11-02 08:57:01 +01:00
Sebastian Spaeth
b0fd6c6ab8 Do not import threading.*
Only import the lock, that we actually need. Also import the with statement
for use with python 2.5. We'll need it for sure in this file.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-10-05 18:34:32 +02:00
Sebastian Spaeth
9578f29195 Use 'reference' value when creating an IMAP directory
A repositories 'reference value is always prefixed to the full folder
path, so we should do so when creating a new one. The code had existed
but was commented out since 2003, I guess the "reference" option is not
too often used.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-09-30 16:57:07 +02:00
Sebastian Spaeth
eb0b546927 Output progress indication when copying files
Output (2 of 500) when logging message copying. This required moving of
self.ui.copyingmessage into a different function where we actually have
the information about the progress handy.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-09-29 16:51:48 +02:00
Sebastian Spaeth
4bfc1e8227 except imapobj.abort() -> except imapobj.abort
When checking for the IMAP4.abort() exception, we need of course to
perform:

except imapobj.abort:

and not

except imapobj.abort():

Thanks to Johannes Stezenbach <js@sig21.net> for pointing to the glitch.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-09-27 14:08:20 +02:00
Sebastian Spaeth
e145beb394 Fix "command CHECK illegal in state AUTH"
Dave identified a case where our new dropped connection handling did
not work out correctly: we use the retry_left variable to signify
success (0=success if no exception occured).

However, we were decrementing the variable AFTER all the exception
checks, so if there was one due to a dropped connection, it
could well be that we 1) did not raise an exception (because we want to
retry), and 2) then DECREMENTED retry_left, which indicated "all is
well, no need to retry".

The code then continued to check() the append, which failed with the
above message (because we obtained a new connection which had not even
selected the current folder and we were still in mode AUTH). The fix is
of course, to fix our logic: Decrement retry_left first, THEN decide
whether to raise() (retry_left==0) or retry (retry_left>0) which would
then correctly attempt another loop. I am sorry for this newbie type of
logic error. The retry count loop was too hastily slipped in, it seems.

Reported-by: Dave Abrahams <dave@boostpro.com>
Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-09-26 16:13:52 +02:00
Sebastian Spaeth
953c58a9c9 Robustify (&fix) error throwing on APPEND
If APPEND raises abort(), the (typ, dat) variables will not be set, so
we should not be using it for the  OfflineImapError Exception
string. Fixing and prettifying the string formatting a bit at the same
time.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-09-26 15:57:35 +02:00
Sebastian Spaeth
e30ae53b2a Folder: Force top-level folder visiblename to ''
nametrans rules can lead to different visiblename names for the
top-level directory, specifically both '.' and '' (the latter was
recently introduced). However, we need to be able to compare folder
names to see if we need to create a new directory or whether a directory
already exists, so we need to be able to compare a repositories
visiblename (=transposed via nametrans rule) with another folder.

To make the top-level directory comparison happen, we enforce a
top-level name of '', so that comparisons work.

Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
2011-09-23 14:31:49 +02:00