diff options
Diffstat (limited to 'mail')
| -rw-r--r-- | mail/changes/feature-mail-notifications | 1 | ||||
| -rw-r--r-- | mail/src/leap/mail/imap/fetch.py | 44 | ||||
| -rw-r--r-- | mail/src/leap/mail/imap/server.py | 48 | ||||
| -rw-r--r-- | mail/src/leap/mail/imap/service/imap.py | 4 | 
4 files changed, 80 insertions, 17 deletions
| diff --git a/mail/changes/feature-mail-notifications b/mail/changes/feature-mail-notifications new file mode 100644 index 0000000..8e52493 --- /dev/null +++ b/mail/changes/feature-mail-notifications @@ -0,0 +1 @@ +  o Notify MUA of new mail, using IDLE as advertised. Closes: #3671 diff --git a/mail/src/leap/mail/imap/fetch.py b/mail/src/leap/mail/imap/fetch.py index 2775d71..dd65def 100644 --- a/mail/src/leap/mail/imap/fetch.py +++ b/mail/src/leap/mail/imap/fetch.py @@ -31,9 +31,6 @@ from twisted.internet.threads import deferToThread  from leap.common import events as leap_events  from leap.common.check import leap_assert, leap_assert_type -from leap.soledad.client import Soledad -from leap.soledad.common.crypto import ENC_SCHEME_KEY, ENC_JSON_KEY -  from leap.common.events.events_pb2 import IMAP_FETCHED_INCOMING  from leap.common.events.events_pb2 import IMAP_MSG_PROCESSING  from leap.common.events.events_pb2 import IMAP_MSG_DECRYPTED @@ -41,6 +38,9 @@ from leap.common.events.events_pb2 import IMAP_MSG_SAVED_LOCALLY  from leap.common.events.events_pb2 import IMAP_MSG_DELETED_INCOMING  from leap.common.events.events_pb2 import IMAP_UNREAD_MAIL  from leap.common.mail import get_email_charset +from leap.keymanager import errors as keymanager_errors +from leap.soledad.client import Soledad +from leap.soledad.common.crypto import ENC_SCHEME_KEY, ENC_JSON_KEY  logger = logging.getLogger(__name__) @@ -198,6 +198,29 @@ class LeapIncomingMail(object):              logger.warning('Unknown error while '                             'syncing soledad: %r' % (err,)) +    def _log_err(self, failure): +        """ +        Generic errback +        """ +        err = failure.value +        logger.error("error!: %r" % (err,)) + +    def _decryption_error(self, failure): +        """ +        Errback for decryption errors. +        """ +        # XXX should signal unrecoverable maybe. +        err = failure.value +        logger.error("error decrypting msg: %s" % (err,)) + +    def _saving_error(self, failure): +        """ +        Errback for local save errors. +        """ +        # XXX should signal unrecoverable maybe. +        err = failure.value +        logger.error("error saving msg locally: %s" % (err,)) +      def _process_doclist(self, doclist):          """          Iterates through the doclist, checks if each doc @@ -228,7 +251,13 @@ class LeapIncomingMail(object):                  # Deferred chain for individual messages                  d = deferToThread(self._decrypt_msg, doc, encdata)                  d.addCallback(self._process_decrypted) +                d.addErrback(self._log_err)                  d.addCallback(self._add_message_locally) +                d.addErrback(self._log_err) +                # XXX check this, add_locally should not get called if we +                # get an error in process +                #d.addCallbacks(self._process_decrypted, self._decryption_error) +                #d.addCallbacks(self._add_message_locally, self._saving_error)                  docs_cb.append(d)              else:                  # Ooops, this does not. @@ -289,8 +318,12 @@ class LeapIncomingMail(object):          rawmsg = msg.get(self.CONTENT_KEY, None)          if not rawmsg:              return False -        data = self._maybe_decrypt_gpg_msg(rawmsg) -        return doc, data +        try: +            data = self._maybe_decrypt_gpg_msg(rawmsg) +            return doc, data +        except keymanager_errors.EncryptionDecryptionFailed as exc: +            logger.error(exc) +            raise      def _maybe_decrypt_gpg_msg(self, data):          """ @@ -384,6 +417,7 @@ class LeapIncomingMail(object):                           incoming message          :type msgtuple: (SoledadDocument, str)          """ +        print "adding message locally....."          doc, data = msgtuple          self._inbox.addMessage(data, (self.RECENT_FLAG,))          leap_events.signal(IMAP_MSG_SAVED_LOCALLY) diff --git a/mail/src/leap/mail/imap/server.py b/mail/src/leap/mail/imap/server.py index 9e3e23e..7a9f810 100644 --- a/mail/src/leap/mail/imap/server.py +++ b/mail/src/leap/mail/imap/server.py @@ -573,7 +573,7 @@ class SoledadBackedAccount(WithMsgFields, IndexedDB):          return "<SoledadBackedAccount (%s)>" % self._account_name  ####################################### -# Soledad Message, MessageCollection +# LeapMessage, MessageCollection  # and Mailbox  ####################################### @@ -1099,6 +1099,7 @@ class SoledadMailbox(WithMsgFields):      which we instantiate and make accessible in the `messages` attribute.      """      implements(imap4.IMailboxInfo, imap4.IMailbox, imap4.ICloseableMailbox) +    # XXX should finish the implementation of IMailboxListener      messages = None      _closed = False @@ -1115,6 +1116,8 @@ class SoledadMailbox(WithMsgFields):      CMD_UIDVALIDITY = "UIDVALIDITY"      CMD_UNSEEN = "UNSEEN" +    listeners = [] +      def __init__(self, mbox, soledad=None, rw=1):          """          SoledadMailbox constructor. Needs to get passed a name, plus a @@ -1147,15 +1150,35 @@ class SoledadMailbox(WithMsgFields):          if not self.getFlags():              self.setFlags(self.INIT_FLAGS) -        # XXX what is/was this used for? -------- -        # ---> mail/imap4.py +1155, -        #      _cbSelectWork makes use of this -        # probably should implement hooks here -        # using leap.common.events -        self.listeners = [] -        self.addListener = self.listeners.append -        self.removeListener = self.listeners.remove -        #------------------------------------------ +        # the server itself is a listener to the mailbox. +        # so we can notify it (and should!) after chanes in flags +        # and number of messages. +        print "emptying the listeners" +        map(lambda i: self.listeners.remove(i), self.listeners) + +    def addListener(self, listener): +        """ +        Rdds a listener to the listeners queue. + +        :param listener: listener to add +        :type listener: an object that implements IMailboxListener +        """ +        logger.debug('adding mailbox listener: %s' % listener) +        self.listeners.append(listener) + +    def removeListener(self, listener): +        """ +        Removes a listener from the listeners queue. + +        :param listener: listener to remove +        :type listener: an object that implements IMailboxListener +        """ +        logger.debug('removing mailbox listener: %s' % listener) +        try: +            self.listeners.remove(listener) +        except ValueError: +            logger.error( +                "removeListener: cannot remove listener %s" % listener)      def _get_mbox(self):          """ @@ -1180,6 +1203,7 @@ class SoledadMailbox(WithMsgFields):          #return map(str, self.INIT_FLAGS)          # XXX CHECK against thunderbird XXX +        # XXX I think this is slightly broken.. :/          mbox = self._get_mbox()          if not mbox: @@ -1352,6 +1376,10 @@ class SoledadMailbox(WithMsgFields):          self.messages.add_msg(message, flags=flags, date=date,                                uid=uid_next) +        exists = len(self.messages) +        recent = len(self.messages.get_recent()) +        for listener in self.listeners: +            listener.newMessages(exists, recent)          return defer.succeed(None)      # commands, do not rename methods diff --git a/mail/src/leap/mail/imap/service/imap.py b/mail/src/leap/mail/imap/service/imap.py index b641d2e..5f7322a 100644 --- a/mail/src/leap/mail/imap/service/imap.py +++ b/mail/src/leap/mail/imap/service/imap.py @@ -77,7 +77,7 @@ class LeapIMAPServer(imap4.IMAP4Server):          #self.theAccount = theAccount      def lineReceived(self, line): -        if "login" in line: +        if "login" in line.lower():              # avoid to log the pass, even though we are using a dummy auth              # by now.              msg = line[:7] + " [...]" @@ -160,7 +160,7 @@ def run_service(*args, **kwargs):      try:          tport = reactor.listenTCP(port, factory, -                                 interface="localhost") +                                  interface="localhost")          fetcher = LeapIncomingMail(              keymanager,              soledad, | 
