Beispiel #1
0
 def _create_incoming_mail_fetcher(self, nicknym, soledad, account,
                                   user_mail):
     inbox = yield account.callWhenReady(
         lambda _: account.getMailbox('INBOX'))
     defer.returnValue(
         IncomingMail(nicknym.keymanager, soledad, inbox.collection,
                      user_mail))
        def setUpFetcher(inbox):
            # Soledad sync makes trial block forever. The sync it's mocked to
            # fix this problem. _mock_soledad_get_from_index can be used from
            # the tests to provide documents.
            # TODO ---- see here http://www.pythoneye.com/83_20424875/
            self._soledad.sync = Mock(return_value=defer.succeed(None))

            self.fetcher = IncomingMail(
                self._km,
                self._soledad,
                inbox.collection,
                ADDRESS)

            # The messages don't exist on soledad will fail on deletion
            self.fetcher._delete_incoming_message = Mock(
                return_value=defer.succeed(None))
Beispiel #3
0
 def setUpIncomingMail(inbox):
     incoming_mail = IncomingMail(keymanager,
                                  soledad,
                                  inbox,
                                  userid,
                                  check_period=get_mail_check_period())
     return incoming_mail
        def setUpFetcher(inbox):
            # Soledad sync makes trial block forever. The sync it's mocked to
            # fix this problem. _mock_soledad_get_from_index can be used from
            # the tests to provide documents.
            # TODO ---- see here http://www.pythoneye.com/83_20424875/
            self._soledad.sync = Mock(return_value=defer.succeed(None))

            self.fetcher = IncomingMail(
                self._km,
                self._soledad,
                inbox.collection,
                ADDRESS)

            # The messages don't exist on soledad will fail on deletion
            self.fetcher._delete_incoming_message = Mock(
                return_value=defer.succeed(None))
class IncomingMailTestCase(TestCaseWithKeyManager):
    """
    Tests for the incoming mail parser
    """
    NICKSERVER = "http://domain"
    BODY = """
Governments of the Industrial World, you weary giants of flesh and steel, I
come from Cyberspace, the new home of Mind. On behalf of the future, I ask
you of the past to leave us alone. You are not welcome among us. You have
no sovereignty where we gather.
    """
    EMAIL = """from: Test from SomeDomain <%(from)s>
to: %(to)s
subject: independence of cyberspace

%(body)s
    """ % {
        "from": ADDRESS_2,
        "to": ADDRESS,
        "body": BODY
    }

    def setUp(self):
        def getInbox(_):
            d = defer.Deferred()
            theAccount = IMAPAccount(ADDRESS, self._soledad, d=d)
            d.addCallback(
                lambda _: theAccount.getMailbox(INBOX_NAME))
            return d

        def setUpFetcher(inbox):
            # Soledad sync makes trial block forever. The sync it's mocked to
            # fix this problem. _mock_soledad_get_from_index can be used from
            # the tests to provide documents.
            # TODO ---- see here http://www.pythoneye.com/83_20424875/
            self._soledad.sync = Mock(return_value=defer.succeed(None))

            self.fetcher = IncomingMail(
                self._km,
                self._soledad,
                inbox.collection,
                ADDRESS)

            # The messages don't exist on soledad will fail on deletion
            self.fetcher._delete_incoming_message = Mock(
                return_value=defer.succeed(None))

        d = super(IncomingMailTestCase, self).setUp()
        d.addCallback(getInbox)
        d.addCallback(setUpFetcher)
        return d

    def tearDown(self):
        del self.fetcher
        return super(IncomingMailTestCase, self).tearDown()

    def testExtractOpenPGPHeader(self):
        """
        Test the OpenPGP header key extraction
        """
        KEYURL = "https://leap.se/key.txt"
        OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,)

        message = Parser().parsestr(self.EMAIL)
        message.add_header("OpenPGP", OpenPGP)
        self.fetcher._keymanager.fetch_key = Mock(
            return_value=defer.succeed(None))

        def fetch_key_called(ret):
            self.fetcher._keymanager.fetch_key.assert_called_once_with(
                ADDRESS_2, KEYURL, OpenPGPKey)

        d = self._create_incoming_email(message.as_string())
        d.addCallback(
            lambda email:
            self._mock_soledad_get_from_index(fields.JUST_MAIL_IDX, [email]))
        d.addCallback(lambda _: self.fetcher.fetch())
        d.addCallback(fetch_key_called)
        return d

    def testExtractOpenPGPHeaderInvalidUrl(self):
        """
        Test the OpenPGP header key extraction
        """
        KEYURL = "https://someotherdomain.com/key.txt"
        OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,)

        message = Parser().parsestr(self.EMAIL)
        message.add_header("OpenPGP", OpenPGP)
        self.fetcher._keymanager.fetch_key = Mock()

        def fetch_key_called(ret):
            self.assertFalse(self.fetcher._keymanager.fetch_key.called)

        d = self._create_incoming_email(message.as_string())
        d.addCallback(
            lambda email:
            self._mock_soledad_get_from_index(fields.JUST_MAIL_IDX, [email]))
        d.addCallback(lambda _: self.fetcher.fetch())
        d.addCallback(fetch_key_called)
        return d

    def testExtractAttachedKey(self):
        KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..."

        message = MIMEMultipart()
        message.add_header("from", ADDRESS_2)
        key = MIMEApplication("", "pgp-keys")
        key.set_payload(KEY)
        message.attach(key)
        self.fetcher._keymanager.put_raw_key = Mock(
            return_value=defer.succeed(None))

        def put_raw_key_called(_):
            self.fetcher._keymanager.put_raw_key.assert_called_once_with(
                KEY, OpenPGPKey, address=ADDRESS_2)

        d = self._do_fetch(message.as_string())
        d.addCallback(put_raw_key_called)
        return d

    def testExtractInvalidAttachedKey(self):
        KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..."

        message = MIMEMultipart()
        message.add_header("from", ADDRESS_2)
        key = MIMEApplication("", "pgp-keys")
        key.set_payload(KEY)
        message.attach(key)
        self.fetcher._keymanager.put_raw_key = Mock(
            return_value=defer.fail(KeyAddressMismatch()))

        def put_raw_key_called(_):
            self.fetcher._keymanager.put_raw_key.assert_called_once_with(
                KEY, OpenPGPKey, address=ADDRESS_2)

        d = self._do_fetch(message.as_string())
        d.addCallback(put_raw_key_called)
        return d

    def testExtractAttachedKeyAndNotOpenPGPHeader(self):
        KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..."
        KEYURL = "https://leap.se/key.txt"
        OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,)

        message = MIMEMultipart()
        message.add_header("from", ADDRESS_2)
        message.add_header("OpenPGP", OpenPGP)
        key = MIMEApplication("", "pgp-keys")
        key.set_payload(KEY)
        message.attach(key)

        self.fetcher._keymanager.put_raw_key = Mock(
            return_value=defer.succeed(None))
        self.fetcher._keymanager.fetch_key = Mock()

        def put_raw_key_called(_):
            self.fetcher._keymanager.put_raw_key.assert_called_once_with(
                KEY, OpenPGPKey, address=ADDRESS_2)
            self.assertFalse(self.fetcher._keymanager.fetch_key.called)

        d = self._do_fetch(message.as_string())
        d.addCallback(put_raw_key_called)
        return d

    def testExtractOpenPGPHeaderIfInvalidAttachedKey(self):
        KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..."
        KEYURL = "https://leap.se/key.txt"
        OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,)

        message = MIMEMultipart()
        message.add_header("from", ADDRESS_2)
        message.add_header("OpenPGP", OpenPGP)
        key = MIMEApplication("", "pgp-keys")
        key.set_payload(KEY)
        message.attach(key)

        self.fetcher._keymanager.put_raw_key = Mock(
            return_value=defer.fail(KeyAddressMismatch()))
        self.fetcher._keymanager.fetch_key = Mock()

        def put_raw_key_called(_):
            self.fetcher._keymanager.put_raw_key.assert_called_once_with(
                KEY, OpenPGPKey, address=ADDRESS_2)
            self.fetcher._keymanager.fetch_key.assert_called_once_with(
                ADDRESS_2, KEYURL, OpenPGPKey)

        d = self._do_fetch(message.as_string())
        d.addCallback(put_raw_key_called)
        return d

    def testAddDecryptedHeader(self):
        class DummyMsg():
            def __init__(self):
                self.headers = {}

            def add_header(self, k, v):
                self.headers[k] = v

        msg = DummyMsg()
        self.fetcher._add_decrypted_header(msg)

        self.assertEquals(msg.headers['X-Leap-Encryption'], 'decrypted')

    def testDecryptEmail(self):
        self.fetcher._decryption_error = Mock()
        self.fetcher._add_decrypted_header = Mock()

        def create_encrypted_message(encstr):
            message = Parser().parsestr(self.EMAIL)
            newmsg = MultipartEncrypted('application/pgp-encrypted')
            for hkey, hval in message.items():
                newmsg.add_header(hkey, hval)

            encmsg = MIMEApplication(
                encstr, _subtype='octet-stream', _encoder=lambda x: x)
            encmsg.add_header('content-disposition', 'attachment',
                              filename='msg.asc')
            # create meta message
            metamsg = PGPEncrypted()
            metamsg.add_header('Content-Disposition', 'attachment')
            # attach pgp message parts to new message
            newmsg.attach(metamsg)
            newmsg.attach(encmsg)
            return newmsg

        def decryption_error_not_called(_):
            self.assertFalse(self.fetcher._decryption_error.called,
                             "There was some errors with decryption")

        def add_decrypted_header_called(_):
            self.assertTrue(self.fetcher._add_decrypted_header.called,
                            "There was some errors with decryption")

        d = self._km.encrypt(
            self.EMAIL,
            ADDRESS, OpenPGPKey, sign=ADDRESS_2)
        d.addCallback(create_encrypted_message)
        d.addCallback(
            lambda message:
            self._do_fetch(message.as_string()))
        return d

    def testListener(self):
        self.called = False

        def listener(uid):
            self.called = True

        def listener_called(_):
            self.assertTrue(self.called)

        self.fetcher.add_listener(listener)
        d = self._do_fetch(self.EMAIL)
        d.addCallback(listener_called)
        return d

    def _do_fetch(self, message):
        d = self._create_incoming_email(message)
        d.addCallback(
            lambda email:
            self._mock_soledad_get_from_index(fields.JUST_MAIL_IDX, [email]))
        d.addCallback(lambda _: self.fetcher.fetch())
        return d

    def _create_incoming_email(self, email_str):
        email = SoledadDocument()
        data = json.dumps(
            {"incoming": True, "content": email_str},
            ensure_ascii=False)

        def set_email_content(encr_data):
            email.content = {
                fields.INCOMING_KEY: True,
                fields.ERROR_DECRYPTING_KEY: False,
                ENC_SCHEME_KEY: EncryptionSchemes.PUBKEY,
                ENC_JSON_KEY: encr_data
            }
            return email
        d = self._km.encrypt(data, ADDRESS, OpenPGPKey, fetch_remote=False)
        d.addCallback(set_email_content)
        return d

    def _mock_soledad_get_from_index(self, index_name, value):
        get_from_index = self._soledad.get_from_index

        def soledad_mock(idx_name, *key_values):
            if index_name == idx_name:
                return defer.succeed(value)
            return get_from_index(idx_name, *key_values)
        self.fetcher._soledad.get_from_index = Mock(side_effect=soledad_mock)
class IncomingMailTestCase(TestCaseWithKeyManager):
    """
    Tests for the incoming mail parser
    """
    NICKSERVER = "http://domain"
    BODY = """
Governments of the Industrial World, you weary giants of flesh and steel, I
come from Cyberspace, the new home of Mind. On behalf of the future, I ask
you of the past to leave us alone. You are not welcome among us. You have
no sovereignty where we gather.
    """
    EMAIL = """from: Test from SomeDomain <%(from)s>
to: %(to)s
subject: independence of cyberspace

%(body)s
    """ % {
        "from": ADDRESS_2,
        "to": ADDRESS,
        "body": BODY
    }

    def setUp(self):
        def getInbox(_):
            d = defer.Deferred()
            theAccount = IMAPAccount(ADDRESS, self._soledad, d=d)
            d.addCallback(
                lambda _: theAccount.getMailbox(INBOX_NAME))
            return d

        def setUpFetcher(inbox):
            # Soledad sync makes trial block forever. The sync it's mocked to
            # fix this problem. _mock_soledad_get_from_index can be used from
            # the tests to provide documents.
            # TODO ---- see here http://www.pythoneye.com/83_20424875/
            self._soledad.sync = Mock(return_value=defer.succeed(None))

            self.fetcher = IncomingMail(
                self._km,
                self._soledad,
                inbox.collection,
                ADDRESS)

            # The messages don't exist on soledad will fail on deletion
            self.fetcher._delete_incoming_message = Mock(
                return_value=defer.succeed(None))

        d = super(IncomingMailTestCase, self).setUp()
        d.addCallback(getInbox)
        d.addCallback(setUpFetcher)
        return d

    def tearDown(self):
        del self.fetcher
        return super(IncomingMailTestCase, self).tearDown()

    def testExtractOpenPGPHeader(self):
        """
        Test the OpenPGP header key extraction
        """
        KEYURL = "https://leap.se/key.txt"
        OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,)

        message = Parser().parsestr(self.EMAIL)
        message.add_header("OpenPGP", OpenPGP)
        self.fetcher._keymanager.fetch_key = Mock(
            return_value=defer.succeed(None))

        def fetch_key_called(ret):
            self.fetcher._keymanager.fetch_key.assert_called_once_with(
                ADDRESS_2, KEYURL, OpenPGPKey)

        d = self._create_incoming_email(message.as_string())
        d.addCallback(
            lambda email:
            self._mock_soledad_get_from_index(fields.JUST_MAIL_IDX, [email]))
        d.addCallback(lambda _: self.fetcher.fetch())
        d.addCallback(fetch_key_called)
        return d

    def testExtractOpenPGPHeaderInvalidUrl(self):
        """
        Test the OpenPGP header key extraction
        """
        KEYURL = "https://someotherdomain.com/key.txt"
        OpenPGP = "id=12345678; url=\"%s\"; preference=signencrypt" % (KEYURL,)

        message = Parser().parsestr(self.EMAIL)
        message.add_header("OpenPGP", OpenPGP)
        self.fetcher._keymanager.fetch_key = Mock()

        def fetch_key_called(ret):
            self.assertFalse(self.fetcher._keymanager.fetch_key.called)

        d = self._create_incoming_email(message.as_string())
        d.addCallback(
            lambda email:
            self._mock_soledad_get_from_index(fields.JUST_MAIL_IDX, [email]))
        d.addCallback(lambda _: self.fetcher.fetch())
        d.addCallback(fetch_key_called)
        return d

    def testExtractAttachedKey(self):
        """
        Test the OpenPGP header key extraction
        """
        KEY = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n..."

        message = MIMEMultipart()
        message.add_header("from", ADDRESS_2)
        key = MIMEApplication("", "pgp-keys")
        key.set_payload(KEY)
        message.attach(key)
        self.fetcher._keymanager.put_raw_key = Mock(
            return_value=defer.succeed(None))
        self.fetcher._keymanager.fetch_key = Mock()

        def put_raw_key_called(_):
            self.fetcher._keymanager.put_raw_key.assert_called_once_with(
                KEY, OpenPGPKey, address=ADDRESS_2)

        d = self._do_fetch(message.as_string())
        d.addCallback(put_raw_key_called)
        return d

    def testDecryptEmail(self):
        self.fetcher._decryption_error = Mock()

        def create_encrypted_message(encstr):
            message = Parser().parsestr(self.EMAIL)
            newmsg = MultipartEncrypted('application/pgp-encrypted')
            for hkey, hval in message.items():
                newmsg.add_header(hkey, hval)

            encmsg = MIMEApplication(
                encstr, _subtype='octet-stream', _encoder=lambda x: x)
            encmsg.add_header('content-disposition', 'attachment',
                              filename='msg.asc')
            # create meta message
            metamsg = PGPEncrypted()
            metamsg.add_header('Content-Disposition', 'attachment')
            # attach pgp message parts to new message
            newmsg.attach(metamsg)
            newmsg.attach(encmsg)
            return newmsg

        def decryption_error_not_called(_):
            self.assertFalse(self.fetcher._decyption_error.called,
                             "There was some errors with decryption")

        d = self._km.encrypt(
            self.EMAIL,
            ADDRESS, OpenPGPKey, sign=ADDRESS_2)
        d.addCallback(create_encrypted_message)
        d.addCallback(
            lambda message:
            self._do_fetch(message.as_string()))
        return d

    def testListener(self):
        self.called = False

        def listener(uid):
            self.called = True

        def listener_called(_):
            self.assertTrue(self.called)

        self.fetcher.add_listener(listener)
        d = self._do_fetch(self.EMAIL)
        d.addCallback(listener_called)
        return d

    def _do_fetch(self, message):
        d = self._create_incoming_email(message)
        d.addCallback(
            lambda email:
            self._mock_soledad_get_from_index(fields.JUST_MAIL_IDX, [email]))
        d.addCallback(lambda _: self.fetcher.fetch())
        return d

    def _create_incoming_email(self, email_str):
        email = SoledadDocument()
        data = json.dumps(
            {"incoming": True, "content": email_str},
            ensure_ascii=False)

        def set_email_content(encr_data):
            email.content = {
                fields.INCOMING_KEY: True,
                fields.ERROR_DECRYPTING_KEY: False,
                ENC_SCHEME_KEY: EncryptionSchemes.PUBKEY,
                ENC_JSON_KEY: encr_data
            }
            return email
        d = self._km.encrypt(data, ADDRESS, OpenPGPKey, fetch_remote=False)
        d.addCallback(set_email_content)
        return d

    def _mock_soledad_get_from_index(self, index_name, value):
        get_from_index = self._soledad.get_from_index

        def soledad_mock(idx_name, *key_values):
            if index_name == idx_name:
                return defer.succeed(value)
            return get_from_index(idx_name, *key_values)
        self.fetcher._soledad.get_from_index = Mock(side_effect=soledad_mock)