diff options
| author | Ruben Pollan <meskio@sindominio.net> | 2017-01-12 15:19:02 +0100 | 
|---|---|---|
| committer | Kali Kaneko (leap communications) <kali@leap.se> | 2017-02-09 12:00:57 +0100 | 
| commit | 15662055b24b1bf4b6007a6a07b642234b264521 (patch) | |
| tree | 77762b106364c8ff9103d0c836fe7fc6977664ea | |
| parent | 776febf6970deeef999255392c6480d1ff34c6f6 (diff) | |
[feat] Get more detailed status report for email
- Resolves: #8754
| -rw-r--r-- | src/leap/bitmask/cli/mail.py | 29 | ||||
| -rw-r--r-- | src/leap/bitmask/core/dispatcher.py | 5 | ||||
| -rw-r--r-- | src/leap/bitmask/core/mail_services.py | 74 | ||||
| -rw-r--r-- | src/leap/bitmask/mail/incoming/service.py | 7 | ||||
| -rw-r--r-- | ui/app/lib/bitmask.js | 9 | 
5 files changed, 116 insertions, 8 deletions
| 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.      # diff --git a/ui/app/lib/bitmask.js b/ui/app/lib/bitmask.js index a6cf8e56..21dbb652 100644 --- a/ui/app/lib/bitmask.js +++ b/ui/app/lib/bitmask.js @@ -223,10 +223,15 @@ var bitmask = function(){              /**               * Check the status of the email service               * +             * @param {string} uid The uid to get status about +             *               * @return {Promise<string>} User readable status               */ -            status: function() { -                return call(['mail', 'status']); +            status: function(uid) { +                if (typeof uid !== 'string') { +                    uid = null +                } +                return call(['mail', 'status', uid]);              },              /** | 
