From 15662055b24b1bf4b6007a6a07b642234b264521 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Thu, 12 Jan 2017 15:19:02 +0100 Subject: [feat] Get more detailed status report for email - Resolves: #8754 --- src/leap/bitmask/cli/mail.py | 29 +++++++++++- src/leap/bitmask/core/dispatcher.py | 5 ++- src/leap/bitmask/core/mail_services.py | 74 +++++++++++++++++++++++++++++-- src/leap/bitmask/mail/incoming/service.py | 7 +++ 4 files changed, 109 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/leap/bitmask/cli/mail.py b/src/leap/bitmask/cli/mail.py index 46251313..73e21965 100644 --- a/src/leap/bitmask/cli/mail.py +++ b/src/leap/bitmask/cli/mail.py @@ -17,6 +17,11 @@ """ Bitmask Command Line interface: mail """ +import argparse +import sys + +from colorama import Fore + from leap.bitmask.cli import command @@ -35,4 +40,26 @@ SUBCOMMANDS: '''.format(name=command.appname) - commands = ['enable', 'disable', 'status', 'get_token'] + commands = ['enable', 'disable', 'get_token'] + + def status(self, raw_args): + parser = argparse.ArgumentParser( + description='Bitmask email status', + prog='%s %s %s' % tuple(sys.argv[:3])) + parser.add_argument('uid', nargs='?', default=None, + help='uid to check the status of') + subargs = parser.parse_args(raw_args) + + self.data.append('status') + if subargs.uid: + self.data.append(subargs.uid) + return self._send(self._print_status) + + def _print_status(self, status, depth=0): + spaces = depth * " " + for k, v in status.items(): + if type(v) == dict: + print(spaces + k + ":") + self._print_status(v, depth + 1) + else: + print(spaces + k + ": " + Fore.GREEN + str(v) + Fore.RESET) diff --git a/src/leap/bitmask/core/dispatcher.py b/src/leap/bitmask/core/dispatcher.py index f96bd457..7c1cdbd4 100644 --- a/src/leap/bitmask/core/dispatcher.py +++ b/src/leap/bitmask/core/dispatcher.py @@ -229,7 +229,10 @@ class MailCmd(SubCommand): @register_method('dict') def do_STATUS(self, mail, *parts, **kw): - d = mail.do_status() + userid = None + if len(parts) > 2: + userid = parts[2] + d = mail.do_status(userid) return d @register_method('dict') diff --git a/src/leap/bitmask/core/mail_services.py b/src/leap/bitmask/core/mail_services.py index bc85889d..2842b5d8 100644 --- a/src/leap/bitmask/core/mail_services.py +++ b/src/leap/bitmask/core/mail_services.py @@ -449,6 +449,7 @@ class StandardMailService(service.MultiService, HookableService): self._sendmail_opts = {} self._service_tokens = {} self._active_user = None + self._status = {} super(StandardMailService, self).__init__() self.initializeChildrenServices() @@ -560,9 +561,41 @@ class StandardMailService(service.MultiService, HookableService): # commands - def do_status(self): - status = 'running' if self.running else 'disabled' - return {'mail': status} + @defer.inlineCallbacks + def do_status(self, userid=None): + smtp = self.getServiceNamed('smtp') + imap = self.getServiceNamed('imap') + childrenStatus = { + 'smtp': smtp.status(), + 'imap': imap.status() + } + if userid is not None: + incoming = self.getServiceNamed('incoming_mail') + childrenStatus['incoming'] = yield incoming.status(userid) + + def key(service): + status = childrenStatus[service] + level = { + "on": 0, + "starting": 1, + "off": 10, + "stopping": 11, + "failure": 100 + } + return level.get(status["status"], -1) + + service = max(childrenStatus, key=key) + + status = childrenStatus[service]["status"] + error = childrenStatus[service]["error"] + + res = {} + for s in childrenStatus.values(): + res.update(s) + res['status'] = status + res['error'] = error + res['childrenStatus'] = childrenStatus + defer.returnValue(res) def get_token(self): active_user = self._active_user @@ -624,6 +657,12 @@ class IMAPService(service.Service): self._factory.doStop() super(IMAPService, self).stopService() + def status(self): + return { + 'status': 'on' if self.running else 'off', + 'error': None + } + class SMTPService(service.Service): @@ -660,6 +699,12 @@ class SMTPService(service.Service): self._factory.doStop() super(SMTPService, self).stopService() + def status(self): + return { + 'status': 'on' if self.running else 'off', + 'error': None + } + class IncomingMailService(service.MultiService): """ @@ -671,6 +716,7 @@ class IncomingMailService(service.MultiService): def __init__(self, mail_service): super(IncomingMailService, self).__init__() self._mail = mail_service + self._status = {} def startService(self): logger.info('starting incoming mail service') @@ -682,6 +728,7 @@ class IncomingMailService(service.MultiService): # Individual accounts def startInstance(self, userid): + self._status[userid] = {"status": "starting", "error": None} soledad = self._mail.get_soledad_session(userid) keymanager = self._mail.get_keymanager_session(userid) @@ -689,6 +736,16 @@ class IncomingMailService(service.MultiService): self._start_incoming_mail_instance( keymanager, soledad, userid) + @defer.inlineCallbacks + def status(self, userid): + if userid not in self._status: + defer.returnValue({'status': 'off', 'error': None, 'unread': None}) + + status = self._status[userid] + incoming = self.getServiceNamed(userid) + status['unread'] = yield incoming.unread() + defer.returnValue(status) + def _start_incoming_mail_instance(self, keymanager, soledad, userid, start_sync=True): @@ -701,13 +758,22 @@ class IncomingMailService(service.MultiService): incoming_mail.setName(userid) self.addService(incoming_mail) + def setStatusOn(res): + self._status[userid]["status"] = "on" + return res + acc = Account(soledad, userid) d = acc.callWhenReady( lambda _: acc.get_collection_by_mailbox(INBOX_NAME)) d.addCallback(setUpIncomingMail) - d.addErrback(lambda r: logger.error(str(r))) + d.addCallback(setStatusOn) + d.addErrback(self._errback, userid) return d + def _errback(self, failure, userid): + self._status[userid] = {"status": "failure", "error": str(failure)} + logger.error(str(failure)) + # -------------------------------------------------------------------- # # config utilities. should be moved to bonafide diff --git a/src/leap/bitmask/mail/incoming/service.py b/src/leap/bitmask/mail/incoming/service.py index 4807c8f7..ac7a5d18 100644 --- a/src/leap/bitmask/mail/incoming/service.py +++ b/src/leap/bitmask/mail/incoming/service.py @@ -205,6 +205,13 @@ class IncomingMail(Service): self._loop = None Service.stopService(self) + def unread(self): + """ + :returns: a deferred that will be fired with the number of unread + messages + """ + return self._inbox_collection.count_unseen() + # # Private methods. # -- cgit v1.2.3