From 96dc914c99a5199fae9326651d891511c66b7561 Mon Sep 17 00:00:00 2001 From: inpos Date: Sun, 29 May 2016 22:29:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=BA=D0=B0=20=D0=BD=D0=B5=D1=8F?= =?UTF-8?q?=D1=81=D0=BD=D0=BE,=20=D0=BA=D0=B0=D0=BA=20=D0=BF=D0=BE=D0=B1?= =?UTF-8?q?=D0=B5=D0=B4=D0=B8=D1=82=D1=8C=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B8?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8=20=D1=8F?= =?UTF-8?q?=D1=89=D0=B8=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mech_imap.py | 20 ++++-- serpent/imap/mailbox.py | 150 ++++++++++++++++++++-------------------- 2 files changed, 89 insertions(+), 81 deletions(-) diff --git a/mech_imap.py b/mech_imap.py index 0add5e6..fb245de 100644 --- a/mech_imap.py +++ b/mech_imap.py @@ -114,6 +114,8 @@ class IMAPUserAccount(object): 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].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] return True @@ -121,20 +123,20 @@ class IMAPUserAccount(object): if isinstance(name, unicode): name = name.encode('imap4-utf-7') if name in IMAP_MBOX_REG[self.dir].keys(): - IMAP_MBOX_REG[self.dir][name].flags['subscribed'] = True - IMAP_MBOX_REG[self.dir][name]._save_flags() - + IMAP_MBOX_REG[self.dir][name].subscribe() + def unsubscribe(self, name): + if name in conf.imap_auto_mbox: + raise imap4.MailboxException, name if isinstance(name, unicode): name = name.encode('imap4-utf-7') if name in IMAP_MBOX_REG[self.dir].keys(): - IMAP_MBOX_REG[self.dir][name].flags['subscribed'] = False - IMAP_MBOX_REG[self.dir][name]._save_flags() - + IMAP_MBOX_REG[self.dir][name].unsubscribe() + def isSubscribed(self, name): if isinstance(name, unicode): 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): name_l = name.split(IMAP_HDELIM) @@ -159,11 +161,15 @@ class SerpentIMAPRealm(object): class IMAPServerProtocol(imap4.IMAP4Server): def lineReceived(self, line): + if isinstance(line, unicode): + line = line.encode('utf-8') print "CLIENT:", line imap4.IMAP4Server.lineReceived(self, line) def sendLine(self, line): imap4.IMAP4Server.sendLine(self, line) + if isinstance(line, unicode): + line = line.encode('utf-8') print "SERVER:", line def connectionLost(self, reason): diff --git a/serpent/imap/mailbox.py b/serpent/imap/mailbox.py index 7530cb9..ef14309 100644 --- a/serpent/imap/mailbox.py +++ b/serpent/imap/mailbox.py @@ -68,10 +68,10 @@ class IMAPMailbox(ExtendedMaildir): maildir.initializeMaildir(path) self.listeners = [] self.path = path - self.path_msg_info = os.path.join(path, conf.imap_msg_info) - self.path_mbox_info = os.path.join(path, conf.imap_mbox_info) + self.msg_info = SqliteDict(os.path.join(path, conf.imap_msg_info)) + self.mbox_info = SqliteDict(os.path.join(path, conf.imap_mbox_info)) self.lastadded = None - self.__check_flags() + self.__check_flags_() def _start_monitor(self): self.notifier = inotify.INotify() @@ -87,26 +87,35 @@ class IMAPMailbox(ExtendedMaildir): l.newMessages(self.getMessageCount(), self.getRecentCount()) 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 mbox_info.keys(): mbox_info['subscribed'] = False - if 'uidvalidity' not in mbox_info.keys(): mbox_info['uidvalidity'] = random.randint(0, 2**32) - if 'uidnext' not in mbox_info.keys(): mbox_info['uidnext'] = 1 - mbox_info.commit() - l = [l for l in self.__msg_list_()] - for i in l: - fn = i.split('/')[-1] - if fn not in msg_info.keys(): - val1 = {'uid': self.getUIDNext()} - if i.split('/')[-2] == 'new': - val1['flags'] = [] - else: - val1['flags'] = [misc.IMAP_FLAGS['SEEN']] - msg_info[fn] = val1 - msg_info.commit() + if 'subscribed' not in self.mbox_info.keys(): self.mbox_info['subscribed'] = False + if 'uidvalidity' not in self.mbox_info.keys(): self.mbox_info['uidvalidity'] = random.randint(0, 2**32) + if 'uidnext' not in self.mbox_info.keys(): self.mbox_info['uidnext'] = 1 + self.mbox_info.commit(blocking=False) + l = [l for l in self.__msg_list_()] + for i in l: + fn = i.split('/')[-1] + if fn not in msg_info.keys(): + val1 = {'uid': self.getUIDNext()} + if i.split('/')[-2] == 'new': + val1['flags'] = [] + else: + val1['flags'] = [misc.IMAP_FLAGS['SEEN']] + self.msg_info[fn] = val1 + self.msg_info.commit(blocking=False) + + 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): - with SqliteDict(self.path_msg_info) as msg_info: - val1 = [0 for fn in msg_info.keys() if flag in msg_info[fn]['flags']] + val1 = [0 for fn in self.msg_info.keys() if flag in self.msg_info[fn]['flags']] return len(val1) def getHierarchicalDelimiter(self): @@ -116,8 +125,7 @@ class IMAPMailbox(ExtendedMaildir): return misc.IMAP_FLAGS.values() def getMessageCount(self): - with SqliteDict(self.path_msg_info) as msg_info: - val1 = [0 for fn in msg_info.keys() if misc.IMAP_FLAGS['DELETED'] not in msg_info[fn]['flags']] + val1 = [0 for fn in self.msg_info.keys() if misc.IMAP_FLAGS['DELETED'] not in self.msg_info[fn]['flags']] return len(val1) def getRecentCount(self): @@ -130,13 +138,12 @@ class IMAPMailbox(ExtendedMaildir): return True def getUIDValidity(self): - return SqliteDict(self.path_mbox_info)['uidvalidity'] + return self.mbox_info['uidvalidity'] def getUIDNext(self): - with SqliteDict(self.path_mbox_info) as mbox_info: - un = mbox_info['uidnext'] - mbox_info['uidnext'] += 1 - mbox_info.commit() + un = self.mbox_info['uidnext'] + self.mbox_info['uidnext'] += 1 + self.mbox_info.commit(blocking=False) return un def getUID(self, num): @@ -149,9 +156,8 @@ class IMAPMailbox(ExtendedMaildir): path = self.lastadded self.lastadded = None fn = path.split('/')[-1] - with SqliteDict(self.path_msg_info) as msg_info: - msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags} - msg_info.commit() + self.msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags} + self.msg_info.commit(blocking=False) if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur': new_path = os.path.join(self.path, 'cur', fn) os.rename(path, new_path) @@ -178,64 +184,60 @@ class IMAPMailbox(ExtendedMaildir): def fetch(self, messages, uid): return [[seq, MaildirMessage(seq, file(filename, 'rb').read(), - SqliteDict(self.path_msg_info)[filename.split('/')[-1]]['flags'], + self.msg_info[filename.split('/')[-1]]['flags'], rfc822date())] for seq, filename in self.__fetch_(messages, uid).iteritems()] def __fetch_(self, messages, uid): - self.__load_flags_() if uid: messagesToFetch = {} if not messages.last: - messages.last = SqliteDict(self.path_mbox_info)['uidnext'] - with SqliteDict(self.path_msg_info) as msg_info: - fn_uid = dict((fn, msg_info[fn]['uid']) for fn in msg_info.keys()) - for uid in messages: - if uid in fn_uid.values(): - for name, _id in fn_uid.iteritems(): - if uid == _id: - if os.path.exists(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)): - messagesToFetch[uid] = os.path.join(self.path,'cur', name) + messages.last = self.mbox_info['uidnext'] + fn_uid = dict((fn, self.msg_info[fn]['uid']) for fn in self.msg_info.keys()) + for uid in messages: + if uid in fn_uid.values(): + for name, _id in fn_uid.iteritems(): + if uid == _id: + if os.path.exists(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)): + messagesToFetch[uid] = os.path.join(self.path,'cur', name) else: messagesToFetch = self._seqMessageSetToSeqDict(messages) return messagesToFetch def store(self, messages, flags, mode, uid): d = {} - with SqliteDict(self.path_msg_info) as msg_info: - for _id, path in self.__fetch_(messages, uid).iteritems(): - filename = path.split('/')[-1] - if mode < 0: - old_f = msg_info[filename]['flags'] - msg_info[filename]['flags'] = list(set(old_f).difference(set(flags))) - if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'new': - new_path = os.path.join(self.path, 'new', filename) - os.rename(path, new_path) - elif mode == 0: - msg_info[filename]['flags'] = flags - elif mode > 0: - old_f = msg_info[filename]['flags'] - msg_info[filename]['flags'] = list(set(old_f).union(set(flags))) - if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur': - new_path = os.path.join(self.path, 'cur', filename) - os.rename(path, new_path) - d[_id] = msg_info[filename]['flags'] - msg_info.commit() + for _id, path in self.__fetch_(messages, uid).iteritems(): + filename = path.split('/')[-1] + if mode < 0: + old_f = self.msg_info[filename]['flags'] + self.msg_info[filename]['flags'] = list(set(old_f).difference(set(flags))) + if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'new': + new_path = os.path.join(self.path, 'new', filename) + os.rename(path, new_path) + elif mode == 0: + self.msg_info[filename]['flags'] = flags + elif mode > 0: + old_f = self.msg_info[filename]['flags'] + self.msg_info[filename]['flags'] = list(set(old_f).union(set(flags))) + if misc.IMAP_FLAGS['SEEN'] in flags and path.split('/')[-2] != 'cur': + new_path = os.path.join(self.path, 'cur', filename) + os.rename(path, new_path) + d[_id] = self.msg_info[filename]['flags'] + msg_info.commit(blocking=False) return d def expunge(self): uids = [] - with SqliteDict(self.path_msg_info) as msg_info: - for path in self.__msg_list_(): - fn = path.split('/')[-1] - if fn not in msg_info.keys(): - continue - uid = msg_info[fn]['uid'] - if misc.IMAP_FLAGS['DELETED'] in msg_info[fn]['flags']: - os.remove(path) - del msg_info[fn] - uids.append(uid) - msg_info.commit() + for path in self.__msg_list_(): + fn = path.split('/')[-1] + if fn not in self.msg_info.keys(): + continue + uid = self.msg_info[fn]['uid'] + if misc.IMAP_FLAGS['DELETED'] in self.msg_info[fn]['flags']: + os.remove(path) + del self.msg_info[fn] + uids.append(uid) + self.msg_info.commit(blocking=False) return uids def addListener(self, listener):