Example #1
0
    def test_running_total(self):
        tasks.statistics.delay()
        stats = models.Statistic.objects.get()
        self.assertEqual(stats.emails["email_count__sum"], 0)
        self.assertEqual(stats.emails["running_total"], 0)

        stats.delete()

        factories.InboxFactory()
        factories.EmailFactory.create_batch(2)

        # first count
        tasks.statistics.delay()
        stats = models.Statistic.objects.get()
        self.assertEqual(stats.emails["email_count__sum"], 2)
        self.assertEqual(stats.emails["running_total"], 2)

        # running total should not have gone down
        models.Email.objects.first().delete()
        tasks.statistics.delay()
        stats = models.Statistic.objects.latest("date")
        self.assertEqual(stats.emails["email_count__sum"], 1)
        self.assertEqual(stats.emails["running_total"], 2)

        # running total should now increase
        factories.EmailFactory()
        tasks.statistics.delay()
        stats = models.Statistic.objects.latest("date")
        self.assertEqual(stats.emails["email_count__sum"], 2)
        self.assertEqual(stats.emails["running_total"], 3)
Example #2
0
    def test_task(self):
        params = [
            [True, False],  # important
            [True, False],  # read
            [True, False],  # auto-delete
            [
                # received_date
                timedelta(days=settings.INBOX_AUTO_DELETE_TIME - 1),
                timedelta(days=settings.INBOX_AUTO_DELETE_TIME),
                timedelta(days=settings.INBOX_AUTO_DELETE_TIME + 1),
            ],
        ]

        now = timezone.now()

        for args in itertools.product(*params):
            email = factories.EmailFactory(important=args[0],
                                           read=args[1],
                                           received_date=now - args[3],
                                           inbox__user=factories.UserFactory())
            email.inbox.user.inboxenprofile.auto_delete = args[2]
            email.inbox.user.inboxenprofile.save()

        self.assertEqual(models.Email.objects.count(), 24)

        tasks.auto_delete_emails.delay()

        # 2/3 of emails will be old enough
        # 1/2 not marked import
        # 1/2 users have auto-deleted enabled
        # therefore 1/6 emails can be deleted
        self.assertEqual(models.Email.objects.count(), 20)
Example #3
0
    def test_header_null_bytes(self):
        name = "X-Hello"
        data = "Hewwo \x00 test"
        body = models.Body.objects.create(data=b"Hello", hashed="fakehash")
        part = models.PartList.objects.create(email=factories.EmailFactory(), body=body)

        header, _ = part.header_set.create(name=name, data=data, ordinal=0)
        self.assertNotEqual(header.data.data, data)
        self.assertEqual(header.data.data, "Hewwo  test")
Example #4
0
    def test_encoders_used(self):
        # make message with base64 part, uuencode part, 8bit part, 7bit part,
        # quopri part, and some invalid part
        body_data = b"Hello\n\nHow are you?\n"
        email = factories.EmailFactory(inbox=self.inbox)
        body = factories.BodyFactory(data=body_data)
        first_part = factories.PartListFactory(
            email=email, body=factories.BodyFactory(data=b""))
        factories.HeaderFactory(
            part=first_part,
            name="Content-Type",
            data="multipart/mixed; boundary=\"=-3BRZDE/skgKPPh+RuFa/\"")

        encodings = {
            "base64": check_base64,
            "quoted-printable": check_quopri,
            "uuencode": check_uu,
            "x-uuencode": check_uu,
            "uue": check_uu,
            "x-uue": check_uu,
            "7-bit": check_noop,
            "8-bit": check_noop,
            "9-bit": check_unknown,  # unknown encoding
        }

        for enc in encodings.keys():
            part = factories.PartListFactory(email=email,
                                             parent=first_part,
                                             body=body)
            factories.HeaderFactory(part=part,
                                    name="Content-Type",
                                    data="text/plain; name=\"my-file.txt\"")
            factories.HeaderFactory(part=part,
                                    name="Content-Transfer-Encoding",
                                    data=enc)

        # finally, make a part without content headers
        factories.PartListFactory(email=email, parent=first_part, body=body)

        # and now export
        message_object = make_message(email)

        for message_part in message_object.walk():
            ct = message_part.get("Content-Type", None)
            cte = message_part.get("Content-Transfer-Encoding", None)
            if ct is None:
                # default is to assume 7-bit
                check_noop(message_part, body_data)
                self.assertEqual(message_part.get_payload(decode=True),
                                 body_data)
            elif ct.startswith("multipart/mixed"):
                pass
            else:
                encodings[cte](message_part, body_data)
                self.assertEqual(message_part.get_payload(decode=True),
                                 body_data)
Example #5
0
    def test_delete_inboxen_item(self):
        email = factories.EmailFactory(inbox__user=self.user)
        tasks.delete_inboxen_item.delay("email", email.id)

        with self.assertRaises(models.Email.DoesNotExist):
            models.Email.objects.get(id=email.id)

        # we can send off the same task, but it won't error if there's no object
        tasks.delete_inboxen_item.delay("email", email.id)

        # test with an empty list
        tasks.delete_inboxen_item.chunks([], 500)()
Example #6
0
    def test_get_cached_result(self, task_mock):
        factories.EmailFactory(inbox__user=self.user)

        task_mock.return_value.id = "abc"
        task_mock.return_value.get.side_effect = exceptions.TimeoutError

        cache.cache.set(
            self.key, {
                "results": list(
                    SearchEntry.objects.values_list("id", flat=True)),
                "has_next": True,
                "has_previous": False,
                "first": "some-randomstring",
                "last": "somerandom-string",
            })

        response = self.client.get(self.url)
        self.assertEqual(response.status_code, 200)

        self.assertEqual(task_mock.call_count, 0)
        self.assertCountEqual(response.context["search_results"]["results"],
                              SearchEntry.objects.all())
        self.assertEqual(response.context["search_results"]["has_next"], True)
        self.assertEqual(response.context["search_results"]["last"],
                         "somerandom-string")
        self.assertEqual(response.context["search_results"]["has_previous"],
                         False)
        self.assertEqual(response.context["search_results"]["first"],
                         "some-randomstring")
        self.assertEqual(response.context["waiting"], False)

        cache.cache.set(
            self.key, {
                "results": [],
                "has_next": True,
                "has_previous": False,
                "first": "some-randomstring",
                "last": "somerandom-string",
            })

        response = self.client.get(self.url)
        self.assertEqual(response.status_code, 200)

        self.assertEqual(task_mock.call_count, 0)
        self.assertCountEqual(response.context["search_results"]["results"],
                              [])
        self.assertEqual(response.context["search_results"]["has_next"], False)
        self.assertEqual(response.context["search_results"]["last"], None)
        self.assertEqual(response.context["search_results"]["has_previous"],
                         False)
        self.assertEqual(response.context["search_results"]["first"], None)
Example #7
0
    def test_add_last_activity(self):
        now = timezone.now()

        email = factories.EmailFactory(received_date=now)
        email.inbox.created = now - datetime.timedelta(2)
        email.inbox.save()

        inbox = factories.InboxFactory()
        inbox.created = now - datetime.timedelta(1)
        inbox.save()

        inboxes = list(models.Inbox.objects.all().add_last_activity())
        self.assertEqual(inboxes[0].last_activity, now)
        self.assertEqual(inboxes[1].last_activity, now - datetime.timedelta(1))
Example #8
0
    def setUp(self):
        super(AttachmentTestCase, self).setUp()

        self.user = factories.UserFactory()
        self.email = factories.EmailFactory(inbox__user=self.user)
        body = factories.BodyFactory(data=BODY)
        self.part = factories.PartListFactory(email=self.email, body=body)
        self.content_type_header, _ = factories.HeaderFactory(part=self.part, name="Content-Type",
                                                              data="text/html; charset=\"utf-8\"")

        login = self.client.login(username=self.user.username, password="******", request=MockRequest(self.user))

        if not login:
            raise Exception("Could not log in")
Example #9
0
    def setUp(self):
        super(BadEmailTestCase, self).setUp()

        self.user = factories.UserFactory()
        self.email = factories.EmailFactory(inbox__user=self.user)
        body = factories.BodyFactory(data=BODY)
        part = factories.PartListFactory(email=self.email, body=body)
        factories.HeaderFactory(part=part, name="From")
        factories.HeaderFactory(part=part, name="Subject")
        factories.HeaderFactory(part=part, name="Content-Type", data="text/html; charset=\"windows-1252\"")
        factories.HeaderFactory(part=part, name="Content-Disposition", data="inline; filename=\"He\n\rl\rlo\nß.jpg\"")

        self.email_metaless = factories.EmailFactory(inbox__user=self.user)
        body = factories.BodyFactory(data=METALESS_BODY)
        part = factories.PartListFactory(email=self.email_metaless, body=body)
        factories.HeaderFactory(part=part, name="From")
        factories.HeaderFactory(part=part, name="Subject")
        factories.HeaderFactory(part=part, name="Content-Type", data="text/html; charset=\"ascii\"")

        login = self.client.login(username=self.user.username, password="******", request=MockRequest(self.user))

        if not login:
            raise Exception("Could not log in")
Example #10
0
    def test_header_create(self):
        name = "X-Hello"
        data = "Hewwo"
        body = models.Body.objects.create(data=b"Hello", hashed="fakehash")
        part = models.PartList.objects.create(email=factories.EmailFactory(), body=body)

        header1 = part.header_set.create(name=name, data=data, ordinal=0)
        header2 = part.header_set.create(name=name, data=data, ordinal=1)

        self.assertEqual(header1[0].name_id, header2[0].name_id)
        self.assertEqual(header1[0].data_id, header2[0].data_id)
        self.assertEqual(header1[0].name.name, name)
        self.assertEqual(header1[0].data.data, data)
        self.assertTrue(header1[1])
        self.assertFalse(header2[1])
Example #11
0
    def test_email_viewable(self):
        user = factories.UserFactory()
        other_user = factories.UserFactory(username="******")

        # all the permutations of Emailss that can be viewed
        params = (
            [0, models.Inbox.flags.deleted, ~models.Inbox.flags.deleted],
            [user, other_user, None],
            [0, models.Email.flags.deleted, ~models.Email.flags.deleted],
        )
        for args in itertools.product(*params):
            factories.EmailFactory(inbox__flags=args[0],
                                   inbox__user=args[1],
                                   flags=args[2])

        count = models.Email.objects.viewable(user).count()
        self.assertEqual(count, 4)
Example #12
0
    def test_find_bodies_with_bad_mime_tree(self):
        email = factories.EmailFactory()
        body = factories.BodyFactory(
            data=b"This mail body is searchable")  # build 1 body and use that

        # the root part, multipart/alternative
        root_part = factories.PartListFactory(email=email, body=body)
        factories.HeaderFactory(part=root_part,
                                name="Content-Type",
                                data="multipart/alternative")

        # first text part
        alt1_part = factories.PartListFactory(email=email,
                                              body=body,
                                              parent=root_part)
        factories.HeaderFactory(part=alt1_part,
                                name="Content-Type",
                                data="text/plain; charset=\"ascii\"")

        # second text part
        alt2_part = factories.PartListFactory(email=email,
                                              body=body,
                                              parent=root_part)
        factories.HeaderFactory(part=alt2_part,
                                name="Content-Type",
                                data="text/plain; charset=\"ascii\"")

        # make first text part invalid by giving it a child
        alt1_child_part = factories.PartListFactory(email=email,
                                                    body=body,
                                                    parent=alt1_part)
        factories.HeaderFactory(part=alt1_child_part,
                                name="Content-Type",
                                data="text/plain; charset=\"ascii\"")

        # find_bodies returns a list of lists, so flatten it out
        bodies = [
            part for part_list in email_utils.find_bodies(email.get_parts())
            for part in part_list
        ]
        # we should only see one part
        self.assertEqual(len(bodies), 1)
        # and it should be a leaf node
        self.assertTrue(bodies[0].is_leaf_node())
        self.assertEqual(bodies[0], alt2_part)
Example #13
0
    def test_delete_inboxen_item(self):
        email = factories.EmailFactory(inbox__user=self.user)
        self.assertEqual(
            SearchEntry.objects.filter(content_type__model="email").count(), 1)

        tasks.delete_inboxen_item.delay("email", email.id)

        self.assertEqual(
            SearchEntry.objects.filter(content_type__model="email").count(), 0)

        with self.assertRaises(models.Email.DoesNotExist):
            models.Email.objects.get(id=email.id)

        # we can send off the same task, but it won't error if there's no object
        tasks.delete_inboxen_item.delay("email", email.id)

        # test with an empty list
        tasks.delete_inboxen_item.chunks([], 500)()
Example #14
0
    def test_email_viewable(self):
        user = factories.UserFactory()
        other_user = factories.UserFactory(username="******")

        # all the permutations of Emailss that can be viewed
        params = (
            [True, False],             # inbox deleted
            [True, False],             # inbox disabled
            [user, other_user, None],  # user
            [True, False],             # email deleted
            [True, False],             # email read (i.e. any other bool has been set)
        )
        for args in itertools.product(*params):
            factories.EmailFactory(
                inbox__deleted=args[0],
                inbox__disabled=args[1],
                inbox__user=args[2],
                deleted=args[3],
                read=args[4],
            )

        count = models.Email.objects.viewable(user).count()
        self.assertEqual(count, 4)
Example #15
0
    def test_encoders_used(self):
        # make message with base64 part, uuencode part, 8bit part, 7bit part,
        # quopri part, and some invalid part
        unicode_body_data = "Hello\n\nHow are you?\nPó på pə pë\n".encode()
        ascii_body_data = "Hello\n\nHow are you?\n".encode()
        email = factories.EmailFactory(inbox=self.inbox)
        unicode_body = factories.BodyFactory(data=unicode_body_data)
        ascii_body = factories.BodyFactory(data=ascii_body_data)
        first_part = factories.PartListFactory(
            email=email, body=factories.BodyFactory(data=b""))
        factories.HeaderFactory(
            part=first_part,
            name="Content-Type",
            data="multipart/mixed; boundary=\"=-3BRZDE/skgKPPh+RuFa/\"")

        unicode_encodings = {
            "base64": check_base64,
            "quoted-printable": check_quopri,
            "uuencode": check_uu,
            "x-uuencode": check_uu,
            "uue": check_uu,
            "x-uue": check_uu,
        }
        ascii_encodings = {
            "7-bit": check_noop,
            "8-bit": check_noop,
            "9-bit": check_unknown,  # unknown encoding
        }
        encodings = {}
        encodings.update(unicode_encodings)
        encodings.update(ascii_encodings)

        for enc in unicode_encodings.keys():
            part = factories.PartListFactory(email=email,
                                             parent=first_part,
                                             body=unicode_body)
            factories.HeaderFactory(part=part,
                                    name="Content-Type",
                                    data="text/plain; name=\"my-file.txt\"")
            factories.HeaderFactory(part=part,
                                    name="Content-Transfer-Encoding",
                                    data=enc)

        for enc in ascii_encodings.keys():
            part = factories.PartListFactory(email=email,
                                             parent=first_part,
                                             body=ascii_body)
            factories.HeaderFactory(part=part,
                                    name="Content-Type",
                                    data="text/plain; name=\"my-file.txt\"")
            factories.HeaderFactory(part=part,
                                    name="Content-Transfer-Encoding",
                                    data=enc)

        # finally, make a part without content headers
        factories.PartListFactory(email=email,
                                  parent=first_part,
                                  body=ascii_body)

        # and now export
        message_object = make_message(email)

        for message_part in message_object.walk():
            ct = message_part.get("Content-Type", None)
            cte = message_part.get("Content-Transfer-Encoding", None)
            if ct is None:
                # default is to assume 7-bit
                check_noop(message_part, ascii_body_data)
                self.assertEqual(message_part.get_payload(decode=True),
                                 ascii_body_data)
            elif ct.startswith("multipart/mixed"):
                pass
            elif cte in ascii_encodings:
                encodings[cte](message_part, ascii_body_data)
                self.assertEqual(message_part.get_payload(decode=True),
                                 ascii_body_data)
            elif cte in unicode_encodings:
                encodings[cte](message_part, unicode_body_data)
                self.assertEqual(message_part.get_payload(decode=True),
                                 unicode_body_data)
            else:
                raise AssertionError(
                    "Unknown Content-Type or Content-Type-Encoding")

        # check that we can decode the whole lot in one go
        output_bytes = message_object.as_string().encode("ascii")
        self.assertNotEqual(len(output_bytes), 0)
        self.assertEqual(
            output_bytes.count(b"text/plain; name=\"my-file.txt\""),
            len(encodings))