From 23adb48b900ffe734b3d223b148cb3a8306c80e8 Mon Sep 17 00:00:00 2001 From: inpos Date: Fri, 10 Jun 2016 16:30:49 +0300 Subject: [PATCH] ... --- mech_imap.py | 51 +++++++++++++++++++++++++++++++++++++++-------- serpent/config.py | 15 +++++++++++--- serpent/misc.py | 10 +++++++++- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/mech_imap.py b/mech_imap.py index bd27e53..3d966f3 100644 --- a/mech_imap.py +++ b/mech_imap.py @@ -25,11 +25,19 @@ class IMAPUserAccount(object): else: IMAP_MBOX_REG[self.dir] = {} 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(): +<<<<<<< HEAD if isinstance(m, unicode): 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] = 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() self.subscribe(m) @@ -54,7 +62,7 @@ class IMAPUserAccount(object): if path in os.listdir(self.dir): return self.create(path) else: - raise imap4.NoSuchMailbox, path + return None def addMailbox(self, name, mbox = None): if mbox: @@ -71,18 +79,22 @@ class IMAPUserAccount(object): if subpath not in IMAP_MBOX_REG[self.dir].keys(): try: IMAP_MBOX_REG[self.dir][subpath] = self._getMailbox(IMAP_HDELIM.join(paths[:accum])) + IMAP_MBOX_REG[self.dir][subpath].subscribe() except imap4.MailboxCollision: pass + IMAP_MBOX_REG[self.dir][subpath].hasChildren() 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] def delete(self, pathspec): if isinstance(pathspec, unicode): 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 if pathspec not in IMAP_MBOX_REG[self.dir].keys(): - raise imap4.MailboxException("No such mailbox") + raise imap4.NoSuchMailbox, pathspec inferiors = self._inferiorNames(pathspec) if r'\Noselect' in IMAP_MBOX_REG[self.dir][pathspec].getFlags(): # Check for hierarchically inferior mailboxes with this one @@ -98,7 +110,7 @@ class IMAPUserAccount(object): return True def rename(self, oldname, newname): - if oldname in conf.imap_auto_mbox: + if oldname in conf.imap_auto_mbox.keys(): raise imap4.MailboxException, oldname if isinstance(oldname, unicode): oldname = oldname.encode('imap4-utf-7') @@ -111,9 +123,15 @@ class IMAPUserAccount(object): if new in IMAP_MBOX_REG[self.dir].keys(): raise imap4.MailboxCollision, new 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)) 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) +<<<<<<< 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] return True @@ -122,19 +140,27 @@ class IMAPUserAccount(object): name = name.encode('imap4-utf-7') if name in IMAP_MBOX_REG[self.dir].keys(): IMAP_MBOX_REG[self.dir][name].subscribe() + return True + #raise imap4.NoSuchMailbox, name def unsubscribe(self, name): - if name in conf.imap_auto_mbox: - raise imap4.MailboxException, name + if name in conf.imap_auto_mbox.keys(): + return False + # 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].unsubscribe() + return True + #raise imap4.NoSuchMailbox, name def isSubscribed(self, name): if isinstance(name, unicode): 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): name_l = name.split(IMAP_HDELIM) @@ -281,6 +307,14 @@ class IMAPServerProtocol(imap4.IMAP4Server): self.sendPositiveResponse(tag, 'STATUS complete') def __ebStatus(self, failure, tag, box): 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) contextFactory = cert.options() p = IMAPServerProtocol(contextFactory = contextFactory) + p.setTimeout(conf.imap_connection_timeout) if conf.tls: p.canStartTLS = True p.IDENT = '%s ready' % conf.SRVNAME diff --git a/serpent/config.py b/serpent/config.py index f365764..b271977 100644 --- a/serpent/config.py +++ b/serpent/config.py @@ -6,9 +6,10 @@ conf = Config() conf.VERSION = '0.1.0' conf.SRVNAME = 'Serpent' conf.srv_version = '%s %s' % (conf.SRVNAME, conf.VERSION) +conf.imap_connection_timeout = 120 conf.local_domains = ['dom.lan'] # Список доменов, для которых будет приниматься почта conf.tls = True -conf.tls_pem = './serpent.pem' +conf.tls_pem = u'./serpent.pem' conf.smtp_open_relay = False # Разрешить ли пересылку откуда угодно куда угодно conf.smtp_email_delim = '@' 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_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_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_check_new_interval = 10.0 # Период проверки новых сообщений в ящике \ No newline at end of file diff --git a/serpent/misc.py b/serpent/misc.py index 6a05744..b82b719 100644 --- a/serpent/misc.py +++ b/serpent/misc.py @@ -10,6 +10,14 @@ IMAP_FLAGS = { 'T': '\\Trashed', 'D': '\\Draft' } +MBOX_FLAGS = { + 'NOINFERIORS': '\\Noinferiors', + 'NOSELECT': '\\Noselect', + 'MARKED': '\\Marked', + 'UNMARKED': '\\Unmarked', + 'HASCHILDREN': '\\HasChildren', + 'HASNOCHILDREN': '\\HasNoChildren' + } IMAP_HDELIM = '.' IMAP_ACC_CONN_NUM = '...ConnectionNumber...' -IMAP_MBOX_REG = {} \ No newline at end of file +IMAP_MBOX_REG = {}