Compare commits
6 Commits
Author | SHA1 | Date |
---|---|---|
inpos | ea035c1e54 | |
inpos | e60d89c1b6 | |
inpos | 5e23c30797 | |
inpos | 3b43af2b2f | |
inpos | 9956b94649 | |
inpos | 4547c85237 |
50
mech_imap.py
50
mech_imap.py
|
@ -25,11 +25,13 @@ class IMAPUserAccount(object):
|
||||||
else:
|
else:
|
||||||
IMAP_MBOX_REG[self.dir] = {}
|
IMAP_MBOX_REG[self.dir] = {}
|
||||||
IMAP_MBOX_REG[self.dir][IMAP_ACC_CONN_NUM] = 0
|
IMAP_MBOX_REG[self.dir][IMAP_ACC_CONN_NUM] = 0
|
||||||
for m in conf.imap_auto_mbox:
|
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].keys():
|
||||||
if isinstance(m, unicode):
|
IMAP_MBOX_REG[self.dir][m] = self.create(m)
|
||||||
m = m.encode('imap4-utf-7')
|
IMAP_MBOX_REG[self.dir][m].setSpecial(conf.imap_auto_mbox[name])
|
||||||
IMAP_MBOX_REG[self.dir][m] = IMAPMailbox(os.path.join(self.dir, m))
|
|
||||||
IMAP_MBOX_REG[self.dir][m]._start_monitor()
|
IMAP_MBOX_REG[self.dir][m]._start_monitor()
|
||||||
self.subscribe(m)
|
self.subscribe(m)
|
||||||
|
|
||||||
|
@ -54,7 +56,7 @@ class IMAPUserAccount(object):
|
||||||
if path in os.listdir(self.dir):
|
if path in os.listdir(self.dir):
|
||||||
return self.create(path)
|
return self.create(path)
|
||||||
else:
|
else:
|
||||||
raise imap4.NoSuchMailbox, path
|
return None
|
||||||
|
|
||||||
def addMailbox(self, name, mbox = None):
|
def addMailbox(self, name, mbox = None):
|
||||||
if mbox:
|
if mbox:
|
||||||
|
@ -71,18 +73,22 @@ class IMAPUserAccount(object):
|
||||||
if subpath not in IMAP_MBOX_REG[self.dir].keys():
|
if subpath not in IMAP_MBOX_REG[self.dir].keys():
|
||||||
try:
|
try:
|
||||||
IMAP_MBOX_REG[self.dir][subpath] = self._getMailbox(IMAP_HDELIM.join(paths[:accum]))
|
IMAP_MBOX_REG[self.dir][subpath] = self._getMailbox(IMAP_HDELIM.join(paths[:accum]))
|
||||||
|
IMAP_MBOX_REG[self.dir][subpath].subscribe()
|
||||||
except imap4.MailboxCollision:
|
except imap4.MailboxCollision:
|
||||||
pass
|
pass
|
||||||
|
IMAP_MBOX_REG[self.dir][subpath].hasChildren()
|
||||||
IMAP_MBOX_REG[self.dir][pathspec] = self._getMailbox(pathspec)
|
IMAP_MBOX_REG[self.dir][pathspec] = self._getMailbox(pathspec)
|
||||||
|
IMAP_MBOX_REG[self.dir][pathspec].hasNoChildren()
|
||||||
|
IMAP_MBOX_REG[self.dir][pathspec].subscribe()
|
||||||
return IMAP_MBOX_REG[self.dir][pathspec]
|
return IMAP_MBOX_REG[self.dir][pathspec]
|
||||||
|
|
||||||
def delete(self, pathspec):
|
def delete(self, pathspec):
|
||||||
if isinstance(pathspec, unicode):
|
if isinstance(pathspec, unicode):
|
||||||
pathspec = pathspec.encode('imap4-utf-7')
|
pathspec = pathspec.encode('imap4-utf-7')
|
||||||
if pathspec in conf.imap_auto_mbox:
|
if pathspec in conf.imap_auto_mbox.keys():
|
||||||
raise imap4.MailboxException, pathspec
|
raise imap4.MailboxException, pathspec
|
||||||
if pathspec not in IMAP_MBOX_REG[self.dir].keys():
|
if pathspec not in IMAP_MBOX_REG[self.dir].keys():
|
||||||
raise imap4.MailboxException("No such mailbox")
|
raise imap4.NoSuchMailbox, pathspec
|
||||||
inferiors = self._inferiorNames(pathspec)
|
inferiors = self._inferiorNames(pathspec)
|
||||||
if r'\Noselect' in IMAP_MBOX_REG[self.dir][pathspec].getFlags():
|
if r'\Noselect' in IMAP_MBOX_REG[self.dir][pathspec].getFlags():
|
||||||
# Check for hierarchically inferior mailboxes with this one
|
# Check for hierarchically inferior mailboxes with this one
|
||||||
|
@ -98,7 +104,7 @@ class IMAPUserAccount(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def rename(self, oldname, newname):
|
def rename(self, oldname, newname):
|
||||||
if oldname in conf.imap_auto_mbox:
|
if oldname in conf.imap_auto_mbox.keys():
|
||||||
raise imap4.MailboxException, oldname
|
raise imap4.MailboxException, oldname
|
||||||
if isinstance(oldname, unicode):
|
if isinstance(oldname, unicode):
|
||||||
oldname = oldname.encode('imap4-utf-7')
|
oldname = oldname.encode('imap4-utf-7')
|
||||||
|
@ -111,11 +117,12 @@ class IMAPUserAccount(object):
|
||||||
if new in IMAP_MBOX_REG[self.dir].keys():
|
if new in IMAP_MBOX_REG[self.dir].keys():
|
||||||
raise imap4.MailboxCollision, new
|
raise imap4.MailboxCollision, new
|
||||||
for (old, new) in inferiors:
|
for (old, new) in inferiors:
|
||||||
|
IMAP_MBOX_REG[self.dir][old]._stop_monitor()
|
||||||
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].open_flags()
|
||||||
IMAP_MBOX_REG[self.dir][new].path_mbox_info = os.path.join(self.dir, conf.imap_mbox_info)
|
IMAP_MBOX_REG[self.dir][new]._start_monitor()
|
||||||
del IMAP_MBOX_REG[self.dir][old]
|
del IMAP_MBOX_REG[self.dir][old]
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -124,19 +131,27 @@ class IMAPUserAccount(object):
|
||||||
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].subscribe()
|
IMAP_MBOX_REG[self.dir][name].subscribe()
|
||||||
|
return True
|
||||||
|
#raise imap4.NoSuchMailbox, name
|
||||||
|
|
||||||
def unsubscribe(self, name):
|
def unsubscribe(self, name):
|
||||||
if name in conf.imap_auto_mbox:
|
if name in conf.imap_auto_mbox.keys():
|
||||||
raise imap4.MailboxException, name
|
return False
|
||||||
|
# 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].unsubscribe()
|
IMAP_MBOX_REG[self.dir][name].unsubscribe()
|
||||||
|
return True
|
||||||
|
#raise imap4.NoSuchMailbox, name
|
||||||
|
|
||||||
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].is_subscribed()
|
if name in IMAP_MBOX_REG[self.dir].keys():
|
||||||
|
return IMAP_MBOX_REG[self.dir][name].is_subscribed()
|
||||||
|
else:
|
||||||
|
raise imap4.NoSuchMailbox, name
|
||||||
|
|
||||||
def _inferiorNames(self, name):
|
def _inferiorNames(self, name):
|
||||||
name_l = name.split(IMAP_HDELIM)
|
name_l = name.split(IMAP_HDELIM)
|
||||||
|
@ -283,6 +298,14 @@ class IMAPServerProtocol(imap4.IMAP4Server):
|
||||||
self.sendPositiveResponse(tag, 'STATUS complete')
|
self.sendPositiveResponse(tag, 'STATUS complete')
|
||||||
def __ebStatus(self, failure, tag, box):
|
def __ebStatus(self, failure, tag, box):
|
||||||
self.sendBadResponse(tag, 'STATUS %s failed: %s' % (box, str(failure.value)))
|
self.sendBadResponse(tag, 'STATUS %s failed: %s' % (box, str(failure.value)))
|
||||||
|
def _cbListWork(self, mailboxes, tag, sub, cmdName):
|
||||||
|
for (name, box) in mailboxes:
|
||||||
|
if not sub or self.account.isSubscribed(name):
|
||||||
|
flags = box.getMboxFlags()
|
||||||
|
delim = box.getHierarchicalDelimiter()
|
||||||
|
resp = (imap4.DontQuoteMe(cmdName), map(imap4.DontQuoteMe, flags), delim, name.encode('imap4-utf-7'))
|
||||||
|
self.sendUntaggedResponse(imap4.collapseNestedLists(resp))
|
||||||
|
self.sendPositiveResponse(tag, '%s completed' % (cmdName,))
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
|
@ -297,6 +320,7 @@ class SerpentIMAPFactory(protocol.Factory):
|
||||||
cert = ssl.PrivateCertificate.loadPEM(tls_data)
|
cert = ssl.PrivateCertificate.loadPEM(tls_data)
|
||||||
contextFactory = cert.options()
|
contextFactory = cert.options()
|
||||||
p = IMAPServerProtocol(contextFactory = contextFactory)
|
p = IMAPServerProtocol(contextFactory = contextFactory)
|
||||||
|
p.setTimeout(conf.imap_connection_timeout)
|
||||||
if conf.tls:
|
if conf.tls:
|
||||||
p.canStartTLS = True
|
p.canStartTLS = True
|
||||||
p.IDENT = '%s ready' % conf.SRVNAME
|
p.IDENT = '%s ready' % conf.SRVNAME
|
||||||
|
|
|
@ -6,9 +6,10 @@ conf = Config()
|
||||||
conf.VERSION = '0.1.0'
|
conf.VERSION = '0.1.0'
|
||||||
conf.SRVNAME = 'Serpent'
|
conf.SRVNAME = 'Serpent'
|
||||||
conf.srv_version = '%s %s' % (conf.SRVNAME, conf.VERSION)
|
conf.srv_version = '%s %s' % (conf.SRVNAME, conf.VERSION)
|
||||||
|
conf.imap_connection_timeout = 60 * 30
|
||||||
conf.local_domains = ['dom.lan'] # Список доменов, для которых будет приниматься почта
|
conf.local_domains = ['dom.lan'] # Список доменов, для которых будет приниматься почта
|
||||||
conf.tls = True
|
conf.tls = True
|
||||||
conf.tls_pem = './serpent.pem'
|
conf.tls_pem = u'./serpent.pem'
|
||||||
conf.smtp_open_relay = False # Разрешить ли пересылку откуда угодно куда угодно
|
conf.smtp_open_relay = False # Разрешить ли пересылку откуда угодно куда угодно
|
||||||
conf.smtp_email_delim = '@'
|
conf.smtp_email_delim = '@'
|
||||||
conf.smtp_header = '''from [{sender_ip}] (helo={sender_host})
|
conf.smtp_header = '''from [{sender_ip}] (helo={sender_host})
|
||||||
|
@ -28,9 +29,17 @@ conf.smtp_email_tls_required = True
|
||||||
|
|
||||||
conf.imap_SENT = 'Sent'
|
conf.imap_SENT = 'Sent'
|
||||||
conf.imap_TRASH = 'Trash'
|
conf.imap_TRASH = 'Trash'
|
||||||
conf.imap_subscribed = '.subscribed'
|
conf.imap_JUNK = 'Junk'
|
||||||
|
conf.imap_ARCHIVE = 'Archive'
|
||||||
|
conf.imap_DRAFTS = 'Drafts'
|
||||||
conf.imap_msg_info = 'msg_info.db'
|
conf.imap_msg_info = 'msg_info.db'
|
||||||
conf.imap_mbox_info = 'mbox_info.db'
|
conf.imap_mbox_info = 'mbox_info.db'
|
||||||
conf.imap_auto_mbox = ['INBOX', 'Sent', 'Trash']
|
conf.imap_auto_mbox = {'INBOX': '\\INBOX',
|
||||||
|
conf.imap_SENT: '\\Sent',
|
||||||
|
conf.imap_TRASH: '\\Trash',
|
||||||
|
conf.imap_JUNK: '\\Junk',
|
||||||
|
conf.imap_ARCHIVE: '\\Archive',
|
||||||
|
conf.imap_DRAFTS: '\\Drafts'
|
||||||
|
}
|
||||||
conf.imap_expunge_on_close = True
|
conf.imap_expunge_on_close = True
|
||||||
conf.imap_check_new_interval = 10.0 # Период проверки новых сообщений в ящике
|
conf.imap_check_new_interval = 10.0 # Период проверки новых сообщений в ящике
|
|
@ -10,7 +10,7 @@ from threading import Thread
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import email
|
import email
|
||||||
from pickle import load, dump
|
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class SerpentAppendMessageTask(maildir._MaildirMailboxAppendMessageTask):
|
||||||
try:
|
try:
|
||||||
self.osrename(self.tmpname, newname)
|
self.osrename(self.tmpname, newname)
|
||||||
break
|
break
|
||||||
except OSError, (err, estr):
|
except OSError, (err, _):
|
||||||
import errno
|
import errno
|
||||||
# if the newname exists, retry with a new newname.
|
# if the newname exists, retry with a new newname.
|
||||||
if err != errno.EEXIST:
|
if err != errno.EEXIST:
|
||||||
|
@ -68,10 +68,13 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
maildir.initializeMaildir(path)
|
maildir.initializeMaildir(path)
|
||||||
self.listeners = []
|
self.listeners = []
|
||||||
self.path = path
|
self.path = path
|
||||||
self.msg_info = SqliteDict(os.path.join(path, conf.imap_msg_info))
|
self.open_flags()
|
||||||
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 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))
|
||||||
|
|
||||||
def _start_monitor(self):
|
def _start_monitor(self):
|
||||||
self.notifier = inotify.INotify()
|
self.notifier = inotify.INotify()
|
||||||
|
@ -81,6 +84,10 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
self.notifier.watch(filepath.FilePath(os.path.join(self.path,'cur')),
|
self.notifier.watch(filepath.FilePath(os.path.join(self.path,'cur')),
|
||||||
callbacks=[self._new_files])
|
callbacks=[self._new_files])
|
||||||
|
|
||||||
|
def _stop_monitor(self):
|
||||||
|
self.notifier.stopReading()
|
||||||
|
self.notifier.loseConnection()
|
||||||
|
|
||||||
def _new_files(self, wo, path, code):
|
def _new_files(self, wo, path, code):
|
||||||
if code == inotify.IN_MOVED_TO or code == inotify.IN_DELETE:
|
if code == inotify.IN_MOVED_TO or code == inotify.IN_DELETE:
|
||||||
for l in self.listeners:
|
for l in self.listeners:
|
||||||
|
@ -88,28 +95,30 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
|
|
||||||
def __check_flags_(self):
|
def __check_flags_(self):
|
||||||
if 'subscribed' not in self.mbox_info.keys(): self.mbox_info['subscribed'] = False
|
if 'subscribed' not in self.mbox_info.keys(): self.mbox_info['subscribed'] = False
|
||||||
|
if 'flags' not in self.mbox_info.keys(): self.mbox_info['flags'] = []
|
||||||
|
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 '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 'uidnext' not in self.mbox_info.keys(): self.mbox_info['uidnext'] = 1
|
||||||
self.mbox_info.commit(blocking=False)
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
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 self.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
|
self.msg_info[fn] = val1
|
||||||
self.msg_info.commit(blocking=False)
|
#self.msg_info.commit(blocking=False) # XXX
|
||||||
|
|
||||||
def subscribe(self):
|
def subscribe(self):
|
||||||
self.mbox_info['subscribed'] = True
|
self.mbox_info['subscribed'] = True
|
||||||
self.mbox_info.commit(blocking=False)
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
|
|
||||||
def unsubscribe(self):
|
def unsubscribe(self):
|
||||||
self.mbox_info['subscribed'] = False
|
self.mbox_info['subscribed'] = False
|
||||||
self.mbox_info.commit(blocking=False)
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
|
|
||||||
def is_subscribed(self):
|
def is_subscribed(self):
|
||||||
return self.mbox_info['subscribed']
|
return self.mbox_info['subscribed']
|
||||||
|
@ -121,15 +130,53 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
def getHierarchicalDelimiter(self):
|
def getHierarchicalDelimiter(self):
|
||||||
return misc.IMAP_HDELIM
|
return misc.IMAP_HDELIM
|
||||||
|
|
||||||
|
def setSpecial(self, special):
|
||||||
|
self.mbox_info['special'] = special
|
||||||
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
|
|
||||||
def getFlags(self):
|
def getFlags(self):
|
||||||
return misc.IMAP_FLAGS.values()
|
return sorted(misc.IMAP_FLAGS.values())
|
||||||
|
|
||||||
|
def getMboxFlags(self):
|
||||||
|
f = list(self.mbox_info['flags'])
|
||||||
|
if self.mbox_info['special'] != '': f.append(self.mbox_info['special'])
|
||||||
|
return f
|
||||||
|
|
||||||
|
def addFlag(self, flag):
|
||||||
|
self.mbox_info['flags'] = list(set(self.mbox_info['flags']).union([flag]))
|
||||||
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
|
|
||||||
|
def removeFlag(self, flag):
|
||||||
|
self.mbox_info['flags'] = list(set(self.mbox_info['flags']).difference([flag]))
|
||||||
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
|
|
||||||
|
def hasChildren(self):
|
||||||
|
flags = self.getFlags()
|
||||||
|
if misc.MBOX_FLAGS['HASCHILDREN'] not in flags:
|
||||||
|
self.addFlag(misc.MBOX_FLAGS['HASCHILDREN'])
|
||||||
|
if misc.MBOX_FLAGS['HASNOCHILDREN'] in flags:
|
||||||
|
self.removeFlag(misc.MBOX_FLAGS['HASNOCHILDREN'])
|
||||||
|
def hasNoChildren(self):
|
||||||
|
flags = self.getFlags()
|
||||||
|
if misc.MBOX_FLAGS['HASNOCHILDREN'] not in flags:
|
||||||
|
self.addFlag(misc.MBOX_FLAGS['HASNOCHILDREN'])
|
||||||
|
if misc.MBOX_FLAGS['HASCHILDREN'] in flags:
|
||||||
|
self.removeFlag(misc.MBOX_FLAGS['HASCHILDREN'])
|
||||||
|
|
||||||
def getMessageCount(self):
|
def getMessageCount(self):
|
||||||
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 self.msg_info.keys() if misc.IMAP_FLAGS['DELETED'] not in self.msg_info[fn]['flags']]
|
||||||
return len(val1)
|
return len(val1)
|
||||||
|
|
||||||
def getRecentCount(self):
|
def getRecentCount(self):
|
||||||
return self.__count_flagged_msgs_(misc.IMAP_FLAGS['RECENT'])
|
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
|
||||||
|
return c
|
||||||
|
|
||||||
def getUnseenCount(self):
|
def getUnseenCount(self):
|
||||||
return self.getMessageCount() - self.__count_flagged_msgs_(misc.IMAP_FLAGS['SEEN'])
|
return self.getMessageCount() - self.__count_flagged_msgs_(misc.IMAP_FLAGS['SEEN'])
|
||||||
|
@ -143,7 +190,7 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
def getUIDNext(self):
|
def getUIDNext(self):
|
||||||
un = self.mbox_info['uidnext']
|
un = self.mbox_info['uidnext']
|
||||||
self.mbox_info['uidnext'] += 1
|
self.mbox_info['uidnext'] += 1
|
||||||
self.mbox_info.commit(blocking=False)
|
#self.mbox_info.commit(blocking=False) # XXX
|
||||||
return un
|
return un
|
||||||
|
|
||||||
def getUID(self, num):
|
def getUID(self, num):
|
||||||
|
@ -157,7 +204,7 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
self.lastadded = None
|
self.lastadded = None
|
||||||
fn = path.split('/')[-1]
|
fn = path.split('/')[-1]
|
||||||
self.msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags}
|
self.msg_info[fn] = {'uid': self.getUIDNext(), 'flags': flags}
|
||||||
self.msg_info.commit(blocking=False)
|
#self.msg_info.commit(blocking=False) # XXX
|
||||||
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)
|
||||||
|
@ -209,21 +256,25 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
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 = self.msg_info[filename]
|
||||||
self.msg_info[filename]['flags'] = list(set(old_f).difference(set(flags)))
|
old_f['flags'] = list(set(old_f['flags']).difference(set(flags)))
|
||||||
|
self.msg_info[filename] = old_f
|
||||||
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
|
old_f = self.msg_info[filename]
|
||||||
|
old_f['flags'] = flags
|
||||||
|
self.msg_info[filename] = old_f
|
||||||
elif mode > 0:
|
elif mode > 0:
|
||||||
old_f = self.msg_info[filename]['flags']
|
old_f = self.msg_info[filename]
|
||||||
self.msg_info[filename]['flags'] = list(set(old_f).union(set(flags)))
|
old_f['flags'] = list(set(old_f['flags']).union(set(flags)))
|
||||||
|
self.msg_info[filename] = old_f
|
||||||
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] = self.msg_info[filename]['flags']
|
||||||
msg_info.commit(blocking=False)
|
#self.msg_info.commit(blocking=False) # XXX
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def expunge(self):
|
def expunge(self):
|
||||||
|
@ -237,14 +288,16 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
del self.msg_info[fn]
|
del self.msg_info[fn]
|
||||||
uids.append(uid)
|
uids.append(uid)
|
||||||
self.msg_info.commit(blocking=False)
|
#self.msg_info.commit(blocking=False) # XXX
|
||||||
return uids
|
return uids
|
||||||
|
|
||||||
def addListener(self, listener):
|
def addListener(self, listener):
|
||||||
self.listeners.append(listener)
|
self.listeners.append(listener)
|
||||||
|
return True
|
||||||
|
|
||||||
def removeListener(self, listener):
|
def removeListener(self, listener):
|
||||||
self.listeners.remove(listener)
|
self.listeners.remove(listener)
|
||||||
|
return True
|
||||||
|
|
||||||
def requestStatus(self, names):
|
def requestStatus(self, names):
|
||||||
return imap4.statusRequestHelper(self, names)
|
return imap4.statusRequestHelper(self, names)
|
||||||
|
@ -253,10 +306,15 @@ class IMAPMailbox(ExtendedMaildir):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.notifier.stopReading()
|
print('!!! %s - %d !!!' % (self.path, len(self.listeners)))
|
||||||
self.notifier.loseConnection()
|
if len(self.listeners) == 0:
|
||||||
if conf.imap_expunge_on_close:
|
self._stop_monitor()
|
||||||
l = self.expunge()
|
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()
|
||||||
|
|
||||||
class MaildirMessagePart(object):
|
class MaildirMessagePart(object):
|
||||||
implements(imap4.IMessagePart)
|
implements(imap4.IMessagePart)
|
||||||
|
|
|
@ -10,6 +10,14 @@ IMAP_FLAGS = {
|
||||||
'DELETED': '\\Deleted',
|
'DELETED': '\\Deleted',
|
||||||
'DRAFT': '\\Draft'
|
'DRAFT': '\\Draft'
|
||||||
}
|
}
|
||||||
|
MBOX_FLAGS = {
|
||||||
|
'NOINFERIORS': '\\Noinferiors',
|
||||||
|
'NOSELECT': '\\Noselect',
|
||||||
|
'MARKED': '\\Marked',
|
||||||
|
'UNMARKED': '\\Unmarked',
|
||||||
|
'HASCHILDREN': '\\HasChildren',
|
||||||
|
'HASNOCHILDREN': '\\HasNoChildren'
|
||||||
|
}
|
||||||
IMAP_HDELIM = '.'
|
IMAP_HDELIM = '.'
|
||||||
IMAP_ACC_CONN_NUM = '...ConnectionNumber...'
|
IMAP_ACC_CONN_NUM = '...ConnectionUUID...'
|
||||||
IMAP_MBOX_REG = {}
|
IMAP_MBOX_REG = {}
|
Loading…
Reference in New Issue