learn to not download UIDs defined by the user
Allow users to workaround offending emails that offlineimap can't download. Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
f0096391fc
commit
29e06a60f9
@ -1187,6 +1187,17 @@ remoteuser = u"username"
|
||||
#"cvlc --play-and-stop --play-and-exit /path/to/sound/file.mp3 > /dev/null 2>&1")
|
||||
|
||||
|
||||
# This option stands in the [Repository RemoteExample] section.
|
||||
#
|
||||
# If offlineiamp is having troubles to download some UIDS, it's possible to get
|
||||
# them ignored in a list.
|
||||
#
|
||||
# The function must return the list of UIDs to ignore, None otherwise. It is
|
||||
# passed the folder name.
|
||||
#
|
||||
#copy_ignore_eval = lambda foldername: {'INBOX': [2, 3, 4]}.get(foldername)
|
||||
|
||||
|
||||
[Repository GmailExample]
|
||||
|
||||
# A repository using Gmail's IMAP interface.
|
||||
|
@ -45,6 +45,7 @@ class BaseFolder(object):
|
||||
if self.name == 'INBOX':
|
||||
self.newmail_hook = repository.newmail_hook
|
||||
self.have_newmail = False
|
||||
self.copy_ignoreUIDs = None # List of UIDs to ignore.
|
||||
self.repository = repository
|
||||
self.visiblename = repository.nametrans(name)
|
||||
# In case the visiblename becomes '.' or '/' (top-level) we use
|
||||
@ -870,6 +871,13 @@ class BaseFolder(object):
|
||||
if not statusfolder.uidexists(uid)]
|
||||
num_to_copy = len(copylist)
|
||||
|
||||
# Honor 'copy_ignore_eval' configuration option.
|
||||
if self.copy_ignoreUIDs is not None:
|
||||
for uid in self.copy_ignoreUIDs:
|
||||
if uid in copylist:
|
||||
copylist.remove(uid)
|
||||
self.ui.ignorecopyingmessage(uid, self, dstfolder)
|
||||
|
||||
if num_to_copy > 0 and self.repository.account.dryrun:
|
||||
self.ui.info(
|
||||
"[DRYRUN] Copy {0} messages from {1}[{2}] to {3}".format(
|
||||
|
@ -58,6 +58,10 @@ class IMAPFolder(BaseFolder):
|
||||
fh_conf = self.repository.account.getconf('filterheaders', '')
|
||||
self.filterheaders = [h for h in re.split(r'\s*,\s*', fh_conf) if h]
|
||||
|
||||
# self.copy_ignoreUIDs is used by BaseFolder.
|
||||
self.copy_ignoreUIDs = repository.get_copy_ignore_UIDs(
|
||||
self.getvisiblename())
|
||||
|
||||
|
||||
def __selectro(self, imapobj, force=False):
|
||||
"""Select this folder when we do not need write access.
|
||||
|
@ -40,6 +40,8 @@ class IMAPRepository(BaseRepository):
|
||||
self._oauth2_request_url = None
|
||||
self.imapserver = imapserver.IMAPServer(self)
|
||||
self.folders = None
|
||||
self.copy_ignore_eval = None
|
||||
|
||||
# Only set the newmail_hook in an IMAP repository.
|
||||
if self.config.has_option(self.getsection(), 'newmail_hook'):
|
||||
self.newmail_hook = self.localeval.eval(
|
||||
@ -75,6 +77,19 @@ class IMAPRepository(BaseRepository):
|
||||
def dropconnections(self):
|
||||
self.imapserver.close()
|
||||
|
||||
def get_copy_ignore_UIDs(self, foldername):
|
||||
"""Return a list of UIDs to not copy for this foldername."""
|
||||
|
||||
if self.copy_ignore_eval is None:
|
||||
if self.config.has_option(self.getsection(),
|
||||
'copy_ignore_eval'):
|
||||
self.copy_ignore_eval = self.localeval.eval(
|
||||
self.getconf('copy_ignore_eval'))
|
||||
else:
|
||||
self.copy_ignore_eval = lambda x: None
|
||||
|
||||
return self.copy_ignore_eval(foldername)
|
||||
|
||||
def getholdconnectionopen(self):
|
||||
if self.getidlefolders():
|
||||
return 1
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Curses-based interfaces
|
||||
# Copyright (C) 2003-2015 John Goerzen & contributors
|
||||
# Copyright (C) 2003-2016 John Goerzen & contributors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -442,6 +442,10 @@ class Blinkenlights(UIBase, CursesUtil):
|
||||
self.gettf().setcolor('blue')
|
||||
super(Blinkenlights, self).syncingmessages(*args)
|
||||
|
||||
def ignorecopyingmessage(self, *args):
|
||||
self.gettf().setcolor('red')
|
||||
super(Blinkenlights, self).ignorecopyingmessage(*args)
|
||||
|
||||
def copyingmessage(self, *args):
|
||||
self.gettf().setcolor('orange')
|
||||
super(Blinkenlights, self).copyingmessage(*args)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2007-2015 John Goerzen & contributors
|
||||
# Copyright (C) 2007-2016 John Goerzen & contributors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -21,10 +21,11 @@ import sys
|
||||
import time
|
||||
import logging
|
||||
from threading import currentThread
|
||||
from offlineimap.ui.UIBase import UIBase
|
||||
import offlineimap
|
||||
|
||||
protocol = '7.0.0'
|
||||
import offlineimap
|
||||
from offlineimap.ui.UIBase import UIBase
|
||||
|
||||
protocol = '7.1.0'
|
||||
|
||||
class MachineLogFormatter(logging.Formatter):
|
||||
"""urlencodes any outputted line, to avoid multi-line output"""
|
||||
@ -125,6 +126,11 @@ class MachineUI(UIBase):
|
||||
(s.getnicename(sr), sf.getname(), s.getnicename(dr),
|
||||
df.getname()))
|
||||
|
||||
def ignorecopyingmessage(s, uid, srcfolder, destfolder):
|
||||
s._printData(s.logger.info, 'ignorecopyingmessage', "%d\n%s\n%s\n%s[%s]"%
|
||||
(uid, s.getnicename(srcfolder), srcfolder.getname(),
|
||||
s.getnicename(destfolder), destfolder))
|
||||
|
||||
def copyingmessage(s, uid, num, num_to_copy, srcfolder, destfolder):
|
||||
s._printData(s.logger.info, 'copyingmessage', "%d\n%s\n%s\n%s[%s]"%
|
||||
(uid, s.getnicename(srcfolder), srcfolder.getname(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Noninteractive UI
|
||||
# Copyright (C) 2002-2012 John Goerzen & contributors
|
||||
# Copyright (C) 2002-2016 John Goerzen & contributors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -16,11 +16,13 @@
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
import logging
|
||||
from offlineimap.ui.UIBase import UIBase
|
||||
|
||||
import offlineimap
|
||||
from offlineimap.ui.UIBase import UIBase
|
||||
|
||||
class Basic(UIBase):
|
||||
"""'Basic' simply sets log level to INFO"""
|
||||
"""'Basic' simply sets log level to INFO."""
|
||||
|
||||
def __init__(self, config, loglevel = logging.INFO):
|
||||
return super(Basic, self).__init__(config, loglevel)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
# UI base class
|
||||
# Copyright (C) 2002-2016 John Goerzen & contributors
|
||||
# Copyright (C) 2002-2016 John Goerzen & contributors.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -27,8 +27,9 @@ try:
|
||||
except ImportError: # python3
|
||||
from queue import Queue
|
||||
from collections import deque
|
||||
from offlineimap.error import OfflineImapError
|
||||
|
||||
import offlineimap
|
||||
from offlineimap.error import OfflineImapError
|
||||
|
||||
debugtypes = {'':'Other offlineimap related sync messages',
|
||||
'imap': 'IMAP protocol debugging',
|
||||
@ -385,6 +386,12 @@ class UIBase(object):
|
||||
self.getnicename(sr), srcfolder,
|
||||
self.getnicename(dr), dstfolder))
|
||||
|
||||
def ignorecopyingmessage(self, uid, src, destfolder):
|
||||
"""Output a log line stating which message is ignored."""
|
||||
|
||||
self.logger.info("IGNORED: Copy message UID %s %s:%s -> %s"% (
|
||||
uid, src.repository, src, destfolder.repository))
|
||||
|
||||
def copyingmessage(self, uid, num, num_to_copy, src, destfolder):
|
||||
"""Output a log line stating which message we copy."""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user