mailbox
inpos 2016-06-10 16:30:49 +03:00
parent 5ac9c36546
commit 23adb48b90
3 changed files with 64 additions and 12 deletions

View File

@ -25,11 +25,19 @@ 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():
<<<<<<< HEAD
if isinstance(m, unicode): if isinstance(m, unicode):
m = m.encode('imap4-utf-7') m = m.encode('imap4-utf-7')
IMAP_MBOX_REG[self.dir][m] = ExtendedMaildir(os.path.join(self.dir, m)) IMAP_MBOX_REG[self.dir][m] = ExtendedMaildir(os.path.join(self.dir, m))
=======
IMAP_MBOX_REG[self.dir][m] = self.create(m)
IMAP_MBOX_REG[self.dir][m].setSpecial(conf.imap_auto_mbox[name])
>>>>>>> refs/remotes/origin/sqlitedict
IMAP_MBOX_REG[self.dir][m]._start_monitor() IMAP_MBOX_REG[self.dir][m]._start_monitor()
self.subscribe(m) self.subscribe(m)
@ -54,7 +62,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 +79,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 +110,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,9 +123,15 @@ 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)
<<<<<<< HEAD
=======
IMAP_MBOX_REG[self.dir][new].open_flags()
IMAP_MBOX_REG[self.dir][new]._start_monitor()
>>>>>>> refs/remotes/origin/sqlitedict
del IMAP_MBOX_REG[self.dir][old] del IMAP_MBOX_REG[self.dir][old]
return True return True
@ -122,19 +140,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)
@ -281,6 +307,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,))
################################################################################ ################################################################################
@ -295,6 +329,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

View File

@ -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 = 120
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 # Период проверки новых сообщений в ящике

View File

@ -10,6 +10,14 @@ IMAP_FLAGS = {
'T': '\\Trashed', 'T': '\\Trashed',
'D': '\\Draft' 'D': '\\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 = '...ConnectionNumber...'
IMAP_MBOX_REG = {} IMAP_MBOX_REG = {}