Пока неясно, как победить ошибки при переименовании ящика

asyncio
inpos 2016-05-29 22:29:14 +03:00
parent 5ab9b0c9cf
commit 96dc914c99
2 changed files with 89 additions and 81 deletions

View File

@ -114,6 +114,8 @@ class IMAPUserAccount(object):
move(os.path.join(self.dir, old), os.path.join(self.dir, new)) move(os.path.join(self.dir, old), os.path.join(self.dir, new))
IMAP_MBOX_REG[self.dir][new] = IMAP_MBOX_REG[self.dir][old] IMAP_MBOX_REG[self.dir][new] = IMAP_MBOX_REG[self.dir][old]
IMAP_MBOX_REG[self.dir][new].path = os.path.join(self.dir, new) IMAP_MBOX_REG[self.dir][new].path = os.path.join(self.dir, new)
IMAP_MBOX_REG[self.dir][new].path_msg_info = os.path.join(self.dir, conf.imap_msg_info)
IMAP_MBOX_REG[self.dir][new].path_mbox_info = os.path.join(self.dir, conf.imap_mbox_info)
del IMAP_MBOX_REG[self.dir][old] del IMAP_MBOX_REG[self.dir][old]
return True return True
@ -121,20 +123,20 @@ class IMAPUserAccount(object):
if isinstance(name, unicode): if isinstance(name, unicode):
name = name.encode('imap4-utf-7') name = name.encode('imap4-utf-7')
if name in IMAP_MBOX_REG[self.dir].keys(): if name in IMAP_MBOX_REG[self.dir].keys():
IMAP_MBOX_REG[self.dir][name].flags['subscribed'] = True IMAP_MBOX_REG[self.dir][name].subscribe()
IMAP_MBOX_REG[self.dir][name]._save_flags()
def unsubscribe(self, name): def unsubscribe(self, name):
if name in conf.imap_auto_mbox:
raise imap4.MailboxException, name
if isinstance(name, unicode): if isinstance(name, unicode):
name = name.encode('imap4-utf-7') name = name.encode('imap4-utf-7')
if name in IMAP_MBOX_REG[self.dir].keys(): if name in IMAP_MBOX_REG[self.dir].keys():
IMAP_MBOX_REG[self.dir][name].flags['subscribed'] = False IMAP_MBOX_REG[self.dir][name].unsubscribe()
IMAP_MBOX_REG[self.dir][name]._save_flags()
def isSubscribed(self, name): def isSubscribed(self, name):
if isinstance(name, unicode): if isinstance(name, unicode):
name = name.encode('imap4-utf-7') name = name.encode('imap4-utf-7')
return IMAP_MBOX_REG[self.dir][name].flags['subscribed'] return IMAP_MBOX_REG[self.dir][name].is_subscribed()
def _inferiorNames(self, name): def _inferiorNames(self, name):
name_l = name.split(IMAP_HDELIM) name_l = name.split(IMAP_HDELIM)
@ -159,11 +161,15 @@ class SerpentIMAPRealm(object):
class IMAPServerProtocol(imap4.IMAP4Server): class IMAPServerProtocol(imap4.IMAP4Server):
def lineReceived(self, line): def lineReceived(self, line):
if isinstance(line, unicode):
line = line.encode('utf-8')
print "CLIENT:", line print "CLIENT:", line
imap4.IMAP4Server.lineReceived(self, line) imap4.IMAP4Server.lineReceived(self, line)
def sendLine(self, line): def sendLine(self, line):
imap4.IMAP4Server.sendLine(self, line) imap4.IMAP4Server.sendLine(self, line)
if isinstance(line, unicode):
line = line.encode('utf-8')
print "SERVER:", line print "SERVER:", line
def connectionLost(self, reason): def connectionLost(self, reason):

View File

@ -68,10 +68,10 @@ class IMAPMailbox(ExtendedMaildir):
maildir.initializeMaildir(path) maildir.initializeMaildir(path)
self.listeners = [] self.listeners = []
self.path = path self.path = path
self.path_msg_info = os.path.join(path, conf.imap_msg_info) self.msg_info = SqliteDict(os.path.join(path, conf.imap_msg_info))
self.path_mbox_info = os.path.join(path, conf.imap_mbox_info) self.mbox_info = SqliteDict(os.path.join(path, conf.imap_mbox_info))
self.lastadded = None self.lastadded = None
self.__check_flags() self.__check_flags_()
def _start_monitor(self): def _start_monitor(self):
self.notifier = inotify.INotify() self.notifier = inotify.INotify()
@ -87,26 +87,35 @@ class IMAPMailbox(ExtendedMaildir):
l.newMessages(self.getMessageCount(), self.getRecentCount()) l.newMessages(self.getMessageCount(), self.getRecentCount())
def __check_flags_(self): def __check_flags_(self):
with SqliteDict(self.path_msg_info) as msg_info, SqliteDict(self.path_mbox_info) as mbox_info: if 'subscribed' not in self.mbox_info.keys(): self.mbox_info['subscribed'] = False
if 'subscribed' not in mbox_info.keys(): mbox_info['subscribed'] = False if 'uidvalidity' not in self.mbox_info.keys(): self.mbox_info['uidvalidity'] = random.randint(0, 2**32)
if 'uidvalidity' not in mbox_info.keys(): mbox_info['uidvalidity'] = random.randint(0, 2**32) if 'uidnext' not in self.mbox_info.keys(): self.mbox_info['uidnext'] = 1
if 'uidnext' not in mbox_info.keys(): mbox_info['uidnext'] = 1 self.mbox_info.commit(blocking=False)
mbox_info.commit() l = [l for l in self.__msg_list_()]
l = [l for l in self.__msg_list_()] for i in l:
for i in l: fn = i.split('/')[-1]
fn = i.split('/')[-1] if fn not in msg_info.keys():
if fn not in msg_info.keys(): val1 = {'uid': self.getUIDNext()}
val1 = {'uid': self.getUIDNext()} if i.split('/')[-2] == 'new':
if i.split('/')[-2] == 'new': val1['flags'] = []
val1['flags'] = [] else:
else: val1['flags'] = [misc.IMAP_FLAGS['SEEN']]
val1['flags'] = [misc.IMAP_FLAGS['SEEN']] self.msg_info[fn] = val1
msg_info[fn] = val1 self.msg_info.commit(blocking=False)
msg_info.commit()
def subscribe(self):
self.mbox_info['subscribed'] = True
self.mbox_info.commit(blocking=False)
def unsubscribe(self):
self.mbox_info['subscribed'] = False
self.mbox_info.commit(blocking=False)
def is_subscribed(self):
return self.mbox_info['subscribed']
def __count_flagged_msgs_(self, flag): def __count_flagged_msgs_(self, flag):
with SqliteDict(self.path_msg_info) as msg_info: val1 = [0 for fn in self.msg_info.keys() if flag in self.msg_info[fn]['flags']]
val1 = [0 for fn in msg_info.keys() if flag in msg_info[fn]['flags']]
return len(val1) return len(val1)
def getHierarchicalDelimiter(self): def getHierarchicalDelimiter(self):
@ -116,8 +125,7 @@ class IMAPMailbox(ExtendedMaildir):
return misc.IMAP_FLAGS.values() return misc.IMAP_FLAGS.values()
def getMessageCount(self): def getMessageCount(self):
with SqliteDict(self.path_msg_info) as msg_info: val1 = [0 for fn in self.msg_info.keys() if misc.IMAP_FLAGS['DELETED'] not in self.msg_info[fn]['flags']]
val1 = [0 for fn in msg_info.keys() if misc.IMAP_FLAGS['DELETED'] not in msg_info[fn]['flags']]
return len(val1) return len(val1)
def getRecentCount(self): def getRecentCount(self):
@ -130,13 +138,12 @@ class IMAPMailbox(ExtendedMaildir):
return True return True
def getUIDValidity(self): def getUIDValidity(self):
return SqliteDict(self.path_mbox_info)['uidvalidity'] return self.mbox_info['uidvalidity']
def getUIDNext(self): def getUIDNext(self):
with SqliteDict(self.path_mbox_info) as mbox_info: un = self.mbox_info['uidnext']
un = mbox_info['uidnext'] self.mbox_info['uidnext'] += 1
mbox_info['uidnext'] += 1 self.mbox_info.commit(blocking=False)
mbox_info.commit()
return un return un
def getUID(self, num): def getUID(self, num):
@ -149,9 +156,8 @@ class IMAPMailbox(ExtendedMaildir):
path = self.lastadded path = self.lastadded
self.lastadded = None self.lastadded = None
fn = path.split('/')[-1] fn = path.split('/')[-1]
with SqliteDict(self.path_msg_info) as msg_info: self.msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags}
msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags} self.msg_info.commit(blocking=False)
msg_info.commit()
if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur': if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur':
new_path = os.path.join(self.path, 'cur', fn) new_path = os.path.join(self.path, 'cur', fn)
os.rename(path, new_path) os.rename(path, new_path)
@ -178,64 +184,60 @@ class IMAPMailbox(ExtendedMaildir):
def fetch(self, messages, uid): def fetch(self, messages, uid):
return [[seq, MaildirMessage(seq, return [[seq, MaildirMessage(seq,
file(filename, 'rb').read(), file(filename, 'rb').read(),
SqliteDict(self.path_msg_info)[filename.split('/')[-1]]['flags'], self.msg_info[filename.split('/')[-1]]['flags'],
rfc822date())] rfc822date())]
for seq, filename in self.__fetch_(messages, uid).iteritems()] for seq, filename in self.__fetch_(messages, uid).iteritems()]
def __fetch_(self, messages, uid): def __fetch_(self, messages, uid):
self.__load_flags_()
if uid: if uid:
messagesToFetch = {} messagesToFetch = {}
if not messages.last: if not messages.last:
messages.last = SqliteDict(self.path_mbox_info)['uidnext'] messages.last = self.mbox_info['uidnext']
with SqliteDict(self.path_msg_info) as msg_info: fn_uid = dict((fn, self.msg_info[fn]['uid']) for fn in self.msg_info.keys())
fn_uid = dict((fn, msg_info[fn]['uid']) for fn in msg_info.keys()) for uid in messages:
for uid in messages: if uid in fn_uid.values():
if uid in fn_uid.values(): for name, _id in fn_uid.iteritems():
for name, _id in fn_uid.iteritems(): if uid == _id:
if uid == _id: if os.path.exists(os.path.join(self.path,'new', name)):
if os.path.exists(os.path.join(self.path,'new', name)): messagesToFetch[uid] = os.path.join(self.path,'new', name)
messagesToFetch[uid] = os.path.join(self.path,'new', name) elif os.path.exists(os.path.join(self.path,'cur', name)):
elif os.path.exists(os.path.join(self.path,'cur', name)): messagesToFetch[uid] = os.path.join(self.path,'cur', name)
messagesToFetch[uid] = os.path.join(self.path,'cur', name)
else: else:
messagesToFetch = self._seqMessageSetToSeqDict(messages) messagesToFetch = self._seqMessageSetToSeqDict(messages)
return messagesToFetch return messagesToFetch
def store(self, messages, flags, mode, uid): def store(self, messages, flags, mode, uid):
d = {} d = {}
with SqliteDict(self.path_msg_info) as msg_info: for _id, path in self.__fetch_(messages, uid).iteritems():
for _id, path in self.__fetch_(messages, uid).iteritems(): filename = path.split('/')[-1]
filename = path.split('/')[-1] if mode < 0:
if mode < 0: old_f = self.msg_info[filename]['flags']
old_f = msg_info[filename]['flags'] self.msg_info[filename]['flags'] = list(set(old_f).difference(set(flags)))
msg_info[filename]['flags'] = list(set(old_f).difference(set(flags))) if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'new':
if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'new': new_path = os.path.join(self.path, 'new', filename)
new_path = os.path.join(self.path, 'new', filename) os.rename(path, new_path)
os.rename(path, new_path) elif mode == 0:
elif mode == 0: self.msg_info[filename]['flags'] = flags
msg_info[filename]['flags'] = flags elif mode > 0:
elif mode > 0: old_f = self.msg_info[filename]['flags']
old_f = msg_info[filename]['flags'] self.msg_info[filename]['flags'] = list(set(old_f).union(set(flags)))
msg_info[filename]['flags'] = list(set(old_f).union(set(flags))) if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur':
if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur': new_path = os.path.join(self.path, 'cur', filename)
new_path = os.path.join(self.path, 'cur', filename) os.rename(path, new_path)
os.rename(path, new_path) d[_id] = self.msg_info[filename]['flags']
d[_id] = msg_info[filename]['flags'] msg_info.commit(blocking=False)
msg_info.commit()
return d return d
def expunge(self): def expunge(self):
uids = [] uids = []
with SqliteDict(self.path_msg_info) as msg_info: for path in self.__msg_list_():
for path in self.__msg_list_(): fn = path.split('/')[-1]
fn = path.split('/')[-1] if fn not in self.msg_info.keys():
if fn not in msg_info.keys(): continue
continue uid = self.msg_info[fn]['uid']
uid = msg_info[fn]['uid'] if misc.IMAP_FLAGS['DELETED'] in self.msg_info[fn]['flags']:
if misc.IMAP_FLAGS['DELETED'] in msg_info[fn]['flags']: os.remove(path)
os.remove(path) del self.msg_info[fn]
del msg_info[fn] uids.append(uid)
uids.append(uid) self.msg_info.commit(blocking=False)
msg_info.commit()
return uids return uids
def addListener(self, listener): def addListener(self, listener):