Compare commits
	
		
			3 Commits
		
	
	
		
			master
			...
			sqlitedict
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8f88a79980 | |||
| 0a34f252d4 | |||
| 966ce51781 | 
							
								
								
									
										27
									
								
								mech_imap.py
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								mech_imap.py
									
									
									
									
									
								
							@ -20,19 +20,18 @@ class IMAPUserAccount(object):
 | 
			
		||||
        if not os.path.exists(mdir):
 | 
			
		||||
            os.makedirs(mdir)
 | 
			
		||||
        self.dir = mdir
 | 
			
		||||
        if self.dir in IMAP_MBOX_REG.keys():
 | 
			
		||||
        if self.dir in IMAP_MBOX_REG.iterkeys():
 | 
			
		||||
            IMAP_MBOX_REG[self.dir][IMAP_ACC_CONN_NUM] += 1
 | 
			
		||||
        else:
 | 
			
		||||
            IMAP_MBOX_REG[self.dir] = {}
 | 
			
		||||
            IMAP_MBOX_REG[self.dir][IMAP_ACC_CONN_NUM] = 0
 | 
			
		||||
            IMAP_MBOX_REG[self.dir][IMAP_ACC_CONN_NUM] = 1
 | 
			
		||||
        for m in conf.imap_auto_mbox.keys():
 | 
			
		||||
            name = m
 | 
			
		||||
            if isinstance(m, unicode):
 | 
			
		||||
                m = m.encode('imap4-utf-7')
 | 
			
		||||
            if m not in IMAP_MBOX_REG[self.dir].keys():
 | 
			
		||||
            if m not in IMAP_MBOX_REG[self.dir].iterkeys():
 | 
			
		||||
                IMAP_MBOX_REG[self.dir][m] = self.create(m)
 | 
			
		||||
                IMAP_MBOX_REG[self.dir][m].setSpecial(conf.imap_auto_mbox[name])
 | 
			
		||||
                IMAP_MBOX_REG[self.dir][m]._start_monitor()
 | 
			
		||||
                self.subscribe(m)
 | 
			
		||||
 | 
			
		||||
    def _getMailbox(self, path):
 | 
			
		||||
@ -66,11 +65,11 @@ class IMAPUserAccount(object):
 | 
			
		||||
    def create(self, pathspec):
 | 
			
		||||
        if isinstance(pathspec, unicode):
 | 
			
		||||
            pathspec = pathspec.encode('imap4-utf-7')
 | 
			
		||||
        if pathspec not in IMAP_MBOX_REG[self.dir].keys():
 | 
			
		||||
        if pathspec not in IMAP_MBOX_REG[self.dir].iterkeys():
 | 
			
		||||
            paths = filter(None, pathspec.split(IMAP_HDELIM))
 | 
			
		||||
            for accum in range(1, len(paths)):
 | 
			
		||||
                subpath = IMAP_HDELIM.join(paths[:accum])
 | 
			
		||||
                if subpath not in IMAP_MBOX_REG[self.dir].keys():
 | 
			
		||||
                if subpath not in IMAP_MBOX_REG[self.dir].iterkeys():
 | 
			
		||||
                    try:
 | 
			
		||||
                        IMAP_MBOX_REG[self.dir][subpath] = self._getMailbox(IMAP_HDELIM.join(paths[:accum]))
 | 
			
		||||
                        IMAP_MBOX_REG[self.dir][subpath].subscribe()
 | 
			
		||||
@ -189,16 +188,26 @@ class IMAPServerProtocol(imap4.IMAP4Server):
 | 
			
		||||
    
 | 
			
		||||
    def connectionLost(self, reason):
 | 
			
		||||
        self.setTimeout(None)
 | 
			
		||||
        if self.account and self.account.dir in IMAP_MBOX_REG.keys():
 | 
			
		||||
        self.transport.loseConnection()
 | 
			
		||||
        if self.account and self.account.dir in IMAP_MBOX_REG.iterkeys():
 | 
			
		||||
            IMAP_MBOX_REG[self.account.dir][IMAP_ACC_CONN_NUM] -= 1
 | 
			
		||||
            if IMAP_MBOX_REG[self.account.dir][IMAP_ACC_CONN_NUM] <= 0:
 | 
			
		||||
                for m in IMAP_MBOX_REG[self.account.dir].keys():
 | 
			
		||||
                    if m == IMAP_ACC_CONN_NUM:
 | 
			
		||||
                        continue
 | 
			
		||||
                    for l in IMAP_MBOX_REG[self.account.dir][m].listeners:
 | 
			
		||||
                        l.transport.loseConnection()
 | 
			
		||||
                        IMAP_MBOX_REG[self.account.dir][m].removeListener(l)
 | 
			
		||||
                    IMAP_MBOX_REG[self.account.dir][m].close()
 | 
			
		||||
                    del IMAP_MBOX_REG[self.account.dir][m]
 | 
			
		||||
                del IMAP_MBOX_REG[self.account.dir]
 | 
			
		||||
                    if IMAP_MBOX_REG[self.account.dir][m].closed:
 | 
			
		||||
                        del IMAP_MBOX_REG[self.account.dir][m]
 | 
			
		||||
                if IMAP_MBOX_REG[self.account.dir].keys() == []:
 | 
			
		||||
                    del IMAP_MBOX_REG[self.account.dir]
 | 
			
		||||
            self.account = None
 | 
			
		||||
    def timeoutConnection(self):
 | 
			
		||||
        self.sendLine('* BYE Autologout; connection idle too long')
 | 
			
		||||
        self.connectionLost('timeout')
 | 
			
		||||
        self.state = 'timeout'
 | 
			
		||||
        
 | 
			
		||||
    def _parseMbox(self, name):
 | 
			
		||||
        if isinstance(name, unicode):
 | 
			
		||||
 | 
			
		||||
@ -32,8 +32,6 @@ conf.imap_TRASH = 'Trash'
 | 
			
		||||
conf.imap_JUNK = 'Junk'
 | 
			
		||||
conf.imap_ARCHIVE = 'Archive'
 | 
			
		||||
conf.imap_DRAFTS = 'Drafts'
 | 
			
		||||
conf.imap_msg_info = 'msg_info.db'
 | 
			
		||||
conf.imap_mbox_info = 'mbox_info.db'
 | 
			
		||||
conf.imap_auto_mbox = {'INBOX':             '\\INBOX',
 | 
			
		||||
                       conf.imap_SENT:      '\\Sent', 
 | 
			
		||||
                       conf.imap_TRASH:     '\\Trash',
 | 
			
		||||
@ -43,3 +41,6 @@ conf.imap_auto_mbox = {'INBOX':             '\\INBOX',
 | 
			
		||||
                       }
 | 
			
		||||
conf.imap_expunge_on_close = True
 | 
			
		||||
conf.imap_check_new_interval = 10.0         # Период проверки новых сообщений в ящике
 | 
			
		||||
conf.imap_msg_flags = 'msg_flags.db'
 | 
			
		||||
conf.imap_msg_uids = 'msg_uids.db'
 | 
			
		||||
conf.imap_mbox_info = 'mbox_info.db'
 | 
			
		||||
@ -69,7 +69,8 @@ class MailDirStore(object):
 | 
			
		||||
        inbox = os.path.join(mdir, 'INBOX')
 | 
			
		||||
        mailbox = self.mbox.IMAPMailbox(inbox)
 | 
			
		||||
        try:
 | 
			
		||||
            mailbox.addMessage(message, [IMAP_FLAGS['RECENT']])
 | 
			
		||||
            #mailbox.addMessage(message, [IMAP_FLAGS['RECENT']])
 | 
			
		||||
            mailbox.addMessage(message, [])
 | 
			
		||||
            return True
 | 
			
		||||
        except:
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
@ -66,6 +66,7 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, path):
 | 
			
		||||
        maildir.initializeMaildir(path)
 | 
			
		||||
        self.closed = False
 | 
			
		||||
        self.listeners = []
 | 
			
		||||
        self.path = path
 | 
			
		||||
        self.open_flags()
 | 
			
		||||
@ -73,8 +74,9 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        self.__check_flags_()
 | 
			
		||||
    
 | 
			
		||||
    def open_flags(self):
 | 
			
		||||
        self.msg_info = SqliteDict(os.path.join(self.path, conf.imap_msg_info))
 | 
			
		||||
        self.mbox_info = SqliteDict(os.path.join(self.path, conf.imap_mbox_info))
 | 
			
		||||
        self.msg_flags = SqliteDict(os.path.join(self.path, conf.imap_msg_flags), autocommit = True)
 | 
			
		||||
        self.msg_uids = SqliteDict(os.path.join(self.path, conf.imap_msg_uids), autocommit = True)
 | 
			
		||||
        self.mbox_info = SqliteDict(os.path.join(self.path, conf.imap_mbox_info), autocommit = True)
 | 
			
		||||
 | 
			
		||||
    def _start_monitor(self):
 | 
			
		||||
        self.notifier = inotify.INotify()
 | 
			
		||||
@ -90,8 +92,10 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
 | 
			
		||||
    def _new_files(self, wo, path, code):
 | 
			
		||||
        if code == inotify.IN_MOVED_TO or code == inotify.IN_DELETE:
 | 
			
		||||
            c = self.getMessageCount()
 | 
			
		||||
            r = self.getRecentCount()
 | 
			
		||||
            for l in self.listeners:
 | 
			
		||||
                l.newMessages(self.getMessageCount(), self.getRecentCount())
 | 
			
		||||
                l.newMessages(c, r)
 | 
			
		||||
 | 
			
		||||
    def __check_flags_(self):
 | 
			
		||||
        if 'subscribed' not in self.mbox_info.keys(): self.mbox_info['subscribed'] = False
 | 
			
		||||
@ -99,17 +103,17 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        if 'special' not in self.mbox_info.keys(): self.mbox_info['special'] = ''
 | 
			
		||||
        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
 | 
			
		||||
        if 'recent' not in self.mbox_info.keys(): self.mbox_info['recent'] = []
 | 
			
		||||
        #self.mbox_info.commit(blocking=False)    # XXX
 | 
			
		||||
        l = [l for l in self.__msg_list_()]
 | 
			
		||||
        for i in l:
 | 
			
		||||
            fn = i.split('/')[-1]
 | 
			
		||||
            if fn not in self.msg_info.keys():
 | 
			
		||||
                val1 = {'uid': self.getUIDNext()}
 | 
			
		||||
            if fn not in self.msg_uids.iterkeys():
 | 
			
		||||
                self.msg_uids[fn] =  self.getUIDNext()
 | 
			
		||||
                if i.split('/')[-2] == 'new':
 | 
			
		||||
                    val1['flags'] = []
 | 
			
		||||
                    self.msg_flags[fn] = []
 | 
			
		||||
                else:
 | 
			
		||||
                    val1['flags'] = [misc.IMAP_FLAGS['SEEN']]
 | 
			
		||||
                self.msg_info[fn] = val1
 | 
			
		||||
                    self.msg_flags[fn] = [misc.IMAP_FLAGS['SEEN']]
 | 
			
		||||
        #self.msg_info.commit(blocking=False)    # XXX
 | 
			
		||||
 | 
			
		||||
    def subscribe(self):
 | 
			
		||||
@ -124,8 +128,7 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        return self.mbox_info['subscribed']
 | 
			
		||||
 | 
			
		||||
    def __count_flagged_msgs_(self, flag):
 | 
			
		||||
        val1 = [0 for fn in self.msg_info.keys() if flag in self.msg_info[fn]['flags']]
 | 
			
		||||
        return len(val1)
 | 
			
		||||
        return sum(1 for flags in self.msg_flags.itervalues() if flag in flags)
 | 
			
		||||
    
 | 
			
		||||
    def getHierarchicalDelimiter(self):
 | 
			
		||||
        return misc.IMAP_HDELIM
 | 
			
		||||
@ -164,22 +167,22 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
            self.removeFlag(misc.MBOX_FLAGS['HASCHILDREN'])
 | 
			
		||||
 | 
			
		||||
    def getMessageCount(self):
 | 
			
		||||
        val1 = [0 for fn in self.msg_info.keys() if misc.IMAP_FLAGS['DELETED'] not in self.msg_info[fn]['flags']]
 | 
			
		||||
        return len(val1)
 | 
			
		||||
        return sum(1 for flags in self.msg_flags.itervalues() if misc.IMAP_FLAGS['DELETED'] not in flags)
 | 
			
		||||
 | 
			
		||||
    def getRecentCount(self):
 | 
			
		||||
        c = 0
 | 
			
		||||
        for fn in self.msg_info.keys():
 | 
			
		||||
            if misc.IMAP_FLAGS['RECENT'] in self.msg_info[fn]['flags']:
 | 
			
		||||
                c += 1
 | 
			
		||||
                info = self.msg_info[fn]
 | 
			
		||||
                info['flags'] = set(info['flags']).difference(set([misc.IMAP_FLAGS['RECENT']]))
 | 
			
		||||
                self.msg_info[fn] = info
 | 
			
		||||
        #self.msg_info.commit(blocking=False)    # XXX
 | 
			
		||||
        #c = 0
 | 
			
		||||
        #for m_items in self.msg_flags.iteritems():
 | 
			
		||||
        #    if misc.IMAP_FLAGS['RECENT'] in m_items[1]:
 | 
			
		||||
        #        c += 1
 | 
			
		||||
        #        self.msg_flags[m_items[0]] = list(set(m_items[1]).difference(set([misc.IMAP_FLAGS['RECENT']])))
 | 
			
		||||
        ##self.msg_info.commit(blocking=False)    # XXX
 | 
			
		||||
        c = len(self.mbox_info['recent'])
 | 
			
		||||
        if c > 0: 
 | 
			
		||||
            self.mbox_info['recent'] = []
 | 
			
		||||
        return c
 | 
			
		||||
    
 | 
			
		||||
    def getUnseenCount(self):
 | 
			
		||||
        return self.getMessageCount() - self.__count_flagged_msgs_(misc.IMAP_FLAGS['SEEN'])
 | 
			
		||||
        return sum(1 for flags in self.msg_flags.itervalues() if misc.IMAP_FLAGS['SEEN'] not in flags)
 | 
			
		||||
 | 
			
		||||
    def isWriteable(self):
 | 
			
		||||
        return True
 | 
			
		||||
@ -203,11 +206,13 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        path = self.lastadded
 | 
			
		||||
        self.lastadded = None
 | 
			
		||||
        fn = path.split('/')[-1]
 | 
			
		||||
        self.msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags}
 | 
			
		||||
        self.msg_uids[fn] = self.getUIDNext()
 | 
			
		||||
        self.msg_flags[fn] = flags
 | 
			
		||||
        #self.msg_info.commit(blocking=False)    # XXX
 | 
			
		||||
        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)
 | 
			
		||||
        self.mbox_info['recent'] = list(set(self.mbox_info['recent']).union(set([fn])))
 | 
			
		||||
 | 
			
		||||
    def __msg_list_(self):
 | 
			
		||||
        a = []
 | 
			
		||||
@ -231,7 +236,7 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
    def fetch(self, messages, uid):
 | 
			
		||||
        return [[seq, MaildirMessage(seq,
 | 
			
		||||
                                     file(filename, 'rb').read(),
 | 
			
		||||
                                     self.msg_info[filename.split('/')[-1]]['flags'],
 | 
			
		||||
                                     self.msg_flags[filename.split('/')[-1]],
 | 
			
		||||
                                     rfc822date())]
 | 
			
		||||
                for seq, filename in self.__fetch_(messages, uid).iteritems()]
 | 
			
		||||
    def __fetch_(self, messages, uid):
 | 
			
		||||
@ -239,7 +244,7 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
            messagesToFetch = {}
 | 
			
		||||
            if not messages.last:
 | 
			
		||||
                messages.last = self.mbox_info['uidnext']
 | 
			
		||||
            fn_uid = dict((fn, self.msg_info[fn]['uid']) for fn in self.msg_info.keys())
 | 
			
		||||
            fn_uid = dict((fn, self.msg_uids[fn]) for fn in self.msg_uids.iterkeys())
 | 
			
		||||
            for uid in messages:
 | 
			
		||||
                if uid in fn_uid.values():
 | 
			
		||||
                    for name, _id in fn_uid.iteritems():
 | 
			
		||||
@ -256,24 +261,18 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        for _id, path in self.__fetch_(messages, uid).iteritems():
 | 
			
		||||
            filename = path.split('/')[-1]
 | 
			
		||||
            if mode < 0:
 | 
			
		||||
                old_f = self.msg_info[filename]
 | 
			
		||||
                old_f['flags'] = list(set(old_f['flags']).difference(set(flags)))
 | 
			
		||||
                self.msg_info[filename] = old_f
 | 
			
		||||
                self.msg_flags[filename] = list(set(self.msg_flags[filename]).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:
 | 
			
		||||
                old_f = self.msg_info[filename]
 | 
			
		||||
                old_f['flags'] = flags
 | 
			
		||||
                self.msg_info[filename] = old_f
 | 
			
		||||
                self.msg_flags[filename] = flags
 | 
			
		||||
            elif mode > 0:
 | 
			
		||||
                old_f = self.msg_info[filename]
 | 
			
		||||
                old_f['flags'] = list(set(old_f['flags']).union(set(flags)))
 | 
			
		||||
                self.msg_info[filename] = old_f
 | 
			
		||||
                self.msg_flags[filename] = list(set(self.msg_flags[filename]).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']
 | 
			
		||||
            d[_id] = self.msg_flags[filename]
 | 
			
		||||
        #self.msg_info.commit(blocking=False)    # XXX
 | 
			
		||||
        return d
 | 
			
		||||
    
 | 
			
		||||
@ -281,12 +280,13 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        uids = []
 | 
			
		||||
        for path in self.__msg_list_():
 | 
			
		||||
            fn = path.split('/')[-1]
 | 
			
		||||
            if fn not in self.msg_info.keys():
 | 
			
		||||
            if fn not in self.msg_uids.iterkeys():
 | 
			
		||||
                continue
 | 
			
		||||
            uid = self.msg_info[fn]['uid']
 | 
			
		||||
            if misc.IMAP_FLAGS['DELETED'] in self.msg_info[fn]['flags']:
 | 
			
		||||
            uid = self.msg_uids[fn]
 | 
			
		||||
            if misc.IMAP_FLAGS['DELETED'] in self.msg_flags[fn]:
 | 
			
		||||
                os.remove(path)
 | 
			
		||||
                del self.msg_info[fn]
 | 
			
		||||
                del self.msg_flags[fn]
 | 
			
		||||
                del self.msg_uids[fn]
 | 
			
		||||
                uids.append(uid)
 | 
			
		||||
        #self.msg_info.commit(blocking=False)    # XXX
 | 
			
		||||
        return uids
 | 
			
		||||
@ -306,15 +306,11 @@ class IMAPMailbox(ExtendedMaildir):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        print('!!! %s - %d !!!' % (self.path, len(self.listeners)))
 | 
			
		||||
        if len(self.listeners) == 0:
 | 
			
		||||
            self._stop_monitor() 
 | 
			
		||||
            if conf.imap_expunge_on_close:
 | 
			
		||||
                self.expunge()
 | 
			
		||||
            self.msg_info.commit(blocking=False)
 | 
			
		||||
            self.mbox_info.commit(blocking = False)
 | 
			
		||||
            self.msg_info.close()
 | 
			
		||||
            self.mbox_info.close()
 | 
			
		||||
            self.closed = True
 | 
			
		||||
 | 
			
		||||
class MaildirMessagePart(object):
 | 
			
		||||
    implements(imap4.IMessagePart)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user