예제 #1
0
 def test_add_in_classical_thread(self):
     # msg1
     # |-msg2
     # | `-msg4
     # `-msg3
     msgs = []
     for num in range(1, 5):
         msg = Message()
         msg["From"] = "*****@*****.**" % num
         msg["Message-ID"] = "<msg%d>" % num
         msg.set_payload("message %d" % num)
         msgs.append(msg)
     msgs[1]["In-Reply-To"] = "<msg1>"
     msgs[2]["In-Reply-To"] = "<msg1>"
     msgs[3]["In-Reply-To"] = "<msg2>"
     for msg in msgs:
         add_to_list("example-list", msg)
     msgs = []
     for num in range(1, 5):
         msg = Email.objects.filter(mailinglist=self.mlist, message_id="msg%d" % num).first()
         msgs.append(msg)
     msg1, msg2, msg3, msg4 = msgs  # pylint: disable=unbalanced-tuple-unpacking
     self.assertEqual(msg1.thread_order, 0)
     self.assertEqual(msg1.thread_depth, 0)
     self.assertEqual(msg2.thread_order, 1)
     self.assertEqual(msg2.thread_depth, 1)
     self.assertEqual(msg3.thread_order, 3)
     self.assertEqual(msg3.thread_depth, 1)
     self.assertEqual(msg4.thread_order, 2)
     self.assertEqual(msg4.thread_depth, 2)
예제 #2
0
 def setUp(self):
     self.user = User.objects.create_user(
         'testuser', '*****@*****.**', 'testPass')
     self.client.login(username='******', password='******')
     # Create test data
     MailingList.objects.create(
         name="*****@*****.**", subject_prefix="[example] ")
     # Create 3 threads
     messages = []
     for msgnum in range(3):
         msg = Message()
         msg["From"] = "*****@*****.**"
         msg["Message-ID"] = "<id%d>" % (msgnum+1)
         msg["Subject"] = "Dummy message %d" % (msgnum+1)
         msg.set_payload("Dummy message")
         add_to_list("*****@*****.**", msg)
         messages.append(msg)
     # 1st is unread, 2nd is read, 3rd is updated
     thread_2 = Thread.objects.get(thread_id=get_message_id_hash("<id2>"))
     thread_3 = Thread.objects.get(thread_id=get_message_id_hash("<id3>"))
     LastView.objects.create(user=self.user, thread=thread_2)
     LastView.objects.create(user=self.user, thread=thread_3)
     msg4 = Message()
     msg4["From"] = "*****@*****.**"
     msg4["Message-ID"] = "<id4>"
     msg4["Subject"] = "Dummy message 4"
     msg4["In-Reply-To"] = "<id3>"
     msg4.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg4)
예제 #3
0
 def test_weird_timezone(self):
     # An email has a timezone with a strange offset (seen in the wild).
     # Make sure it does not break our _is_old_enough() method.
     mbox = mailbox.mbox(os.path.join(self.tmpdir, "test.mbox"))
     # First message is already imported
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2008-01-01 12:00:00"
     msg1.set_payload("msg1")
     add_to_list("*****@*****.**", msg1)
     # Second message is in the mbox to import
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["Date"] = "Sat, 30 Aug 2008 16:40:31 +05-30"
     msg2.set_payload("msg2")
     mbox.add(msg2)
     # do the import
     output = StringIO()
     kw = self.common_cmd_args.copy()
     kw["stdout"] = kw["stderr"] = output
     try:
         self.command.execute(os.path.join(self.tmpdir, "test.mbox"), **kw)
     except ValueError as e:
         self.fail(format_exc(e))
     # Message must have been accepted
     self.assertEqual(MailingList.objects.count(), 1)
     self.assertEqual(Email.objects.count(), 2)
예제 #4
0
 def test_delete_all_messages_in_thread(self):
     self.user.is_staff = True
     self.user.save()
     msg = Email.objects.get(message_id="msg")
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["In-Reply-To"] = "<msg>"
     msg2.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg2)
     msg2 = Email.objects.get(message_id="msg2")
     thread_id = msg.thread.pk
     url = reverse('hk_thread_delete',
                   args=("*****@*****.**", msg.thread.thread_id))
     response = self.client.post(url, {"email": [msg.pk, msg2.pk]})
     self.assertRedirects(
         response, reverse('hk_list_overview', kwargs={
             "mlist_fqdn": "*****@*****.**"}))
     # Flash message
     messages = get_flash_messages(response)
     self.assertEqual(len(messages), 1)
     self.assertEqual(messages[0].tags, "success")
     # Alls messages and the thread must be deleted.
     self.assertFalse(Email.objects.filter(message_id="msg").exists())
     self.assertFalse(Email.objects.filter(message_id="msg2").exists())
     self.assertFalse(Thread.objects.filter(pk=thread_id).exists())
예제 #5
0
 def test_vote_cancel(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg1>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
     msg.replace_header("Message-ID", "<msg2>")
     add_to_list("*****@*****.**", msg)
     msg1 = Email.objects.get(mailinglist__name="*****@*****.**",
                              message_id="msg1")
     msg1.vote(1, self.user)
     msg2 = Email.objects.get(mailinglist__name="*****@*****.**",
                              message_id="msg2")
     msg2.vote(-1, self.user)
     self.assertEqual(msg1.get_votes()["likes"], 1)
     self.assertEqual(msg2.get_votes()["dislikes"], 1)
     for msg in (msg1, msg2):
         url = reverse('hk_message_vote', args=("*****@*****.**",
                       msg.message_id_hash))
         resp = self.client.post(url, {"vote": "0"})
         self.assertEqual(resp.status_code, 200)
         votes = msg.get_votes()
         self.assertEqual(votes["likes"], 0)
         self.assertEqual(votes["dislikes"], 0)
         result = json.loads(resp.content)
         self.assertEqual(result["like"], 0)
         self.assertEqual(result["dislike"], 0)
예제 #6
0
 def test_impacted_threads(self):
     # existing message
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2015-01-01 12:00:00"
     msg1.set_payload("msg1")
     add_to_list("*****@*****.**", msg1)
     # new message in the imported mbox
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["Date"] = "2015-02-01 12:00:00"
     msg2.set_payload("msg1")
     mbox = mailbox.mbox(os.path.join(self.tmpdir, "test.mbox"))
     mbox.add(msg2)
     # do the import
     output = StringIO()
     with patch("hyperkitty.management.commands.hyperkitty_import.compute_thread_order_and_depth") as mock_compute:
         self.command.execute(os.path.join(self.tmpdir, "test.mbox"),
             verbosity=2, stdout=output, stderr=output,
             list_address="*****@*****.**",
             since=None, no_download=True, no_sync_mailman=True,
         )
     #print(mock_compute.call_args_list)
     self.assertEqual(mock_compute.call_count, 1)
     thread = mock_compute.call_args[0][0]
     self.assertEqual(thread.emails.count(), 1)
     self.assertEqual(thread.starting_email.message_id, "msg2")
예제 #7
0
 def test_get_threads_between(self):
     # the get_threads_between method should return all threads that have
     # been active between the two specified dates, including the threads
     # started in between those dates but updated later
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2015-02-15 00:00:00 UTC"
     msg1.set_payload("message 1")
     add_to_list(self.ml.name, msg1)
     # The thread started in Feb, it should show up in the Feb threads but
     # not in the January or March threads.
     self.assertEqual(Thread.objects.count(), 1)
     jan_threads = self.ml.get_threads_between(
         datetime(2015, 1, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 1, 31, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(jan_threads.count(), 0)
     feb_threads = self.ml.get_threads_between(
         datetime(2015, 2, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 2, 28, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(feb_threads.count(), 1)
     march_threads = self.ml.get_threads_between(
         datetime(2015, 3, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 3, 31, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(march_threads.count(), 0)
예제 #8
0
 def test_since_override(self):
     # When there's mail already and the "since" option is not used, it
     # defaults to the last email's date
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2015-01-01 12:00:00"
     msg1.set_payload("msg1")
     add_to_list("*****@*****.**", msg1)
     mailbox.mbox(os.path.join(self.tmpdir, "test.mbox"))
     # do the import
     output = StringIO()
     with patch("hyperkitty.management.commands.hyperkitty_import.DbImporter"
         ) as DbImporterMock:
         instance = Mock()
         instance.impacted_thread_ids = []
         DbImporterMock.side_effect = lambda *a, **kw: instance
         self.command.execute(os.path.join(self.tmpdir, "test.mbox"),
             verbosity=2, stdout=output, stderr=output,
             list_address="*****@*****.**",
             since="2010-01-01 00:00:00 UTC",
             no_download=True, no_sync_mailman=True,
         )
     self.assertEqual(DbImporterMock.call_args[0][1]["since"],
                      datetime(2010, 1, 1, tzinfo=utc))
예제 #9
0
 def test_as_message_attachments(self):
     msg_in = Message()
     msg_in["From"] = "*****@*****.**"
     msg_in["Message-ID"] = "<msg>"
     msg_in.attach(MIMEText("Dummy message"))
     msg_in.attach(MIMEText("<html><body>Dummy message</body></html>", _subtype="html"))
     add_to_list("*****@*****.**", msg_in)
     email = Email.objects.get(message_id="msg")
     msg = email.as_message()
     self.assertEqual(msg["From"], "dummy at example.com")
     self.assertEqual(msg["Message-ID"], "<msg>")
     self.assertTrue(msg.is_multipart())
     payload = msg.get_payload()
     self.assertEqual(len(payload), 2)
     self.assertEqual(
         payload[0].get_payload(decode=True).strip(), "Dummy message")
     # The filename extension detection from content type is a bit random
     # (depends on the PYTHON_HASHSEED), make sure we get the right one
     # here for testing.
     expected_ext = guess_all_extensions("text/html", strict=False)[0]
     self.assertEqual(payload[1].get_content_type(), "text/html")
     self.assertEqual(payload[1]["Content-Disposition"],
         'attachment; filename="attachment%s"' % expected_ext)
     self.assertEqual(
         payload[1].get_payload(decode=True),
         "<html><body>Dummy message</body></html>")
예제 #10
0
 def test_get_threads_between_across_two_months(self):
     # the get_threads_between method should return all threads that have
     # been active between the two specified dates, including the threads
     # started in between those dates but updated later
     msg1 = Message()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["Date"] = "2015-01-15 00:00:00 UTC"
     msg1.set_payload("message 1")
     add_to_list(self.ml.name, msg1)
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["In-Reply-To"] = "<msg1>"
     msg2["Date"] = "2015-03-15 00:00:00 UTC"
     msg2.set_payload("message 2")
     add_to_list(self.ml.name, msg2)
     # The thread started in Jan, was updated in March. It should show up in
     # the Jan, Feb and March threads.
     self.assertEqual(Thread.objects.count(), 1)
     jan_threads = self.ml.get_threads_between(
         datetime(2015, 1, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 1, 31, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(jan_threads.count(), 1)
     feb_threads = self.ml.get_threads_between(
         datetime(2015, 2, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 2, 28, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(feb_threads.count(), 1)
     march_threads = self.ml.get_threads_between(
         datetime(2015, 3, 1, 0, 0, 0, tzinfo=utc),
         datetime(2015, 3, 31, 0, 0, 0, tzinfo=utc),
         )
     self.assertEqual(march_threads.count(), 1)
예제 #11
0
 def test_delete_single_in_thread(self):
     # Delete an email in a thread that contains other emails
     self.user.is_staff = True
     self.user.save()
     msg = Email.objects.get(message_id="msg")
     msg2 = Message()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["In-Reply-To"] = "<msg>"
     msg2.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg2)
     msg2 = Email.objects.get(message_id="msg2")
     thread_id = msg.thread.thread_id
     url = reverse('hk_message_delete',
                   args=("*****@*****.**", msg.message_id_hash))
     response = self.client.post(url, {"email": msg.pk})
     self.assertRedirects(
         response, reverse('hk_thread', kwargs={
             "mlist_fqdn": "*****@*****.**",
             "threadid": thread_id}))
     # Flash message
     messages = get_flash_messages(response)
     self.assertEqual(len(messages), 1)
     self.assertEqual(messages[0].tags, "success")
     # The message must be deleted, but not the other message or the thread.
     self.assertFalse(Email.objects.filter(message_id="msg").exists())
     self.assertTrue(Email.objects.filter(message_id="msg2").exists())
     thread = Thread.objects.get(thread_id=thread_id)
     self.assertIsNotNone(thread)
     # msg2 must now be the thread starter.
     msg2.refresh_from_db()
     self.assertIsNone(msg2.parent_id)
     self.assertEqual(thread.starting_email.message_id, "msg2")
예제 #12
0
 def setUp(self):
     # Create the list by adding a dummy message
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
예제 #13
0
    def from_mbox(self, mbfile):
        """
        Insert all the emails contained in an mbox file into the database.

        :arg mbfile: a mailbox file
        """
        #self.store.search_index = make_delayed(self.store.search_index)
        mbox = mailbox.mbox(mbfile)
        progress_marker = ProgressMarker(self.verbose, self.stdout)
        if not self.since:
            progress_marker.total = len(mbox)
        for message in mbox:
            if self._is_too_old(message):
                continue
            progress_marker.tick(message["Message-Id"])
            # Un-wrap the subject line if necessary
            if message["subject"]:
                message.replace_header("subject",
                        TEXTWRAP_RE.sub(" ", message["subject"]))
            # Now insert the message
            try:
                with transaction.atomic():
                    add_to_list(self.list_address, message)
            except DuplicateMessage as e:
                if self.verbose:
                    self.stderr.write(
                        "Duplicate email with message-id '%s'" % e.args[0])
                continue
            except ValueError as e:
                if len(e.args) != 2:
                    raise # Regular ValueError exception
                try:
                    self.stderr.write("%s from %s about %s"
                        % (e.args[0], e.args[1].get("From"),
                           e.args[1].get("Subject")))
                except UnicodeDecodeError:
                    self.stderr.write("%s with message-id %s"
                        % (e.args[0], e.args[1].get("Message-ID")))
                continue
            except DatabaseError:
                try:
                    print_exc(file=self.stderr)
                except UnicodeError:
                    pass
                self.stderr.write("Message %s failed to import, skipping"
                      % unquote(message["Message-Id"]))
                continue
            email = Email.objects.get(
                mailinglist__name=self.list_address,
                message_id=get_message_id(message))
            ## Commit every time to be able to rollback on error
            #if not transaction.get_autocommit():
            #    transaction.commit()
            # Store the list of impacted threads to be able to compute the
            # thread_order and thread_depth values
            self.impacted_thread_ids.add(email.thread_id)
            progress_marker.count_imported += 1
        #self.store.search_index.flush() # Now commit to the search index
        progress_marker.finish()
예제 #14
0
 def test_attachment_insert_order(self):
     """Attachments must not be inserted in the DB before the email"""
     with open(get_test_file("attachment-1.txt")) as email_file:
         msg = message_from_file(email_file)
     try:
         add_to_list("example-list", msg)
     except IntegrityError, e:
         self.fail(e)
예제 #15
0
 def setUp(self):
     self.user = User.objects.create(username="******")
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg>"
     msg.set_payload("message")
     add_to_list("example-list", msg)
     self.thread = Thread.objects.all()[0]
예제 #16
0
 def test_get_sender_name(self):
     msg = Message()
     msg["From"] = "Sender Name <*****@*****.**>"
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     add_to_list("example-list", msg)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertEqual(stored_msg.sender.name, "Sender Name")
예제 #17
0
 def test_date_aware(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummy>"
     msg["Date"] = "Fri, 02 Nov 2012 16:07:54 +0100"
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError, e:
         self.fail(e)
예제 #18
0
 def test_as_message_timezone(self):
     msg_in = Message()
     msg_in["From"] = "*****@*****.**"
     msg_in["Message-ID"] = "<msg>"
     msg_in["Date"] = "Fri, 02 Nov 2012 16:07:54 +0400"
     msg_in.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg_in)
     email = Email.objects.get(message_id="msg")
     msg = email.as_message()
     self.assertEqual(msg["Date"], msg_in["Date"])
예제 #19
0
 def test_non_ascii_email_address(self):
     """Non-ascii email addresses should raise a ValueError exception"""
     msg = Message()
     msg["From"] = b"dummy-non-ascii-\xc3\[email protected]"
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except ValueError, e:
         self.assertEqual(e.__class__.__name__, "ValueError")
예제 #20
0
 def setUp(self):
     # Create the list by adding a dummy message
     # The message must be old to create multiple year accordion panels in
     # the months list.
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg>"
     msg["Date"] = "2010-02-01 00:00:00 UTC"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
예제 #21
0
 def test_duplicate(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     add_to_list("example-list", msg)
     mlist = MailingList.objects.get(name="example-list")
     self.assertEqual(mlist.emails.count(), 1)
     self.assertTrue(mlist.emails.filter(message_id="dummy").exists())
     self.assertRaises(DuplicateMessage, add_to_list, "example-list", msg)
     self.assertEqual(mlist.emails.count(), 1)
예제 #22
0
 def test_subject(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummymsg>"
     msg["Date"] = "Fri, 02 Nov 2012 16:07:54 +0000"
     msg["Subject"] = "Dummy subject"
     msg.set_payload("Dummy message")
     add_to_list("example-list", msg)
     self.assertEqual(Thread.objects.count(), 1)
     thread = Thread.objects.all()[0]
     self.assertEqual(thread.subject, "Dummy subject")
예제 #23
0
 def test_between_dates(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Date"] = "2015-09-01 00:00:00"
     msg["Message-ID"] = "<msg2>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
     mbox = self._get_mbox(qs="start=2015-09-01&end=2015-10-01")
     self.assertEqual(len(mbox), 1)
     mbox_msg = mbox.values()[0]
     self.assertEqual(mbox_msg["Message-ID"], "<msg2>")
예제 #24
0
 def setUp(self):
     self.user = User.objects.create_user('testuser', '*****@*****.**',
                                          'testPass')
     self.client.login(username='******', password='******')
     # Create a dummy message to test on
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msg>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
예제 #25
0
 def test_email_escaped_body(self):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msgid2>"
     msg["In-Reply-To"] = "<msgid>"
     msg.set_payload("Email address: [email protected]")
     add_to_list("*****@*****.**", msg)
     url = reverse('hk_thread', args=["*****@*****.**", self.threadid])
     response = self.client.get(url)
     self.assertNotContains(response, "*****@*****.**", status_code=200)
예제 #26
0
 def test_long_message_id(self):
     # Some message-ids are more than 255 chars long
     # Check with assert here because SQLite will not enforce the limit
     # (http://www.sqlite.org/faq.html#q9)
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "X" * 260
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError, e:
         self.fail(e)
예제 #27
0
 def test_email_escaped_body(self):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msgid2>"
     msg["In-Reply-To"] = "<msgid>"
     msg.set_payload("Email address: [email protected]")
     add_to_list("*****@*****.**", msg)
     url = reverse('hk_thread', args=["*****@*****.**", self.threadid])
     response = self.client.get(url)
     self.assertNotContains(response, "*****@*****.**", status_code=200)
예제 #28
0
 def test_email_escaped_sender(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msg2>"
     msg.set_payload("Dummy content")
     add_to_list("*****@*****.**", msg)
     url = reverse('hk_message_index', args=("*****@*****.**",
                   get_message_id_hash("msg2")))
     response = self.client.get(url)
     self.assertNotContains(response, "*****@*****.**", status_code=200)
예제 #29
0
 def setUp(self):
     self.user = User.objects.create_user(
             'testuser', '*****@*****.**', 'testPass')
     self.client.login(username='******', password='******')
     # Create a dummy message to test on
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msg>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
예제 #30
0
 def test_do_not_catch_exceptions(self):
     class SpecificError(Exception):
         pass
     def boom(sender, **kwargs): # pylint: disable=unused-argument
         raise SpecificError
     new_email.connect(boom)
     msg = self._make_message()
     try:
         add_to_list("example-list", msg)
     except SpecificError:
         pass
     else:
         self.fail("The exception should have been propagated")
예제 #31
0
 def test_long_subject(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummy>"
     msg["Subject"] = "x" * 600
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError as e:
         self.fail(e)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertEqual(len(stored_msg.subject), 512)
예제 #32
0
 def _create_tree(self, tree):
     emails = []
     for msgid in tree:
         msg = Message()
         msg["From"] = "*****@*****.**"
         msg["Message-ID"] = "<%s>" % msgid
         parent_id = msgid.rpartition(".")[0]
         if Email.objects.filter(message_id=parent_id).exists():
             msg["In-Reply-To"] = "<%s>" % parent_id
         msg.set_payload("dummy message")
         add_to_list("example-list", msg)
         emails.append(Email.objects.get(message_id=msgid))
     return emails
예제 #33
0
 def test_no_sender_name_or_address(self):
     msg = Message()
     msg["From"] = ""
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError as e:
         self.fail(e)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertEqual(stored_msg.sender.name, "")
     self.assertEqual(stored_msg.sender.address, "*****@*****.**")
 def test_no_sender_name_or_address(self):
     msg = EmailMessage()
     msg["From"] = ""
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError as e:
         self.fail(e)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertEqual(stored_msg.sender_name, "")
     self.assertEqual(stored_msg.sender.address, "*****@*****.**")
 def test_long_subject(self):
     msg = EmailMessage()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummy>"
     msg["Subject"] = "x" * 600
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError as e:
         self.fail(e)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertEqual(len(stored_msg.subject), 512)
 def test_archived_date_unparseable(self):
     msg = EmailMessage()
     msg["From"] = "*****@*****.**"
     msg["Subject"] = "Fake Subject"
     msg["Message-ID"] = "<dummy>"
     msg["Date"] = "Fri, 02 Nov 2012 16:07:54"
     msg.set_payload("Fake Message")
     msg.set_unixfrom("[email protected] Something that cant be parsed")
     add_to_list("example-list", msg)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     one_hour_ago = timezone.now() - datetime.timedelta(hours=1)
     self.assertTrue(stored_msg.archived_date > one_hour_ago)
 def test_no_date(self):
     msg = EmailMessage()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     now = timezone.now()
     try:
         add_to_list("example-list", msg)
     except IntegrityError as e:
         self.fail(e)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertTrue(stored_msg.date >= now)
예제 #38
0
 def _create_tree(self, tree):
     emails = []
     for msgid in tree:
         msg = Message()
         msg["From"] = "*****@*****.**"
         msg["Message-ID"] = "<%s>" % msgid
         parent_id = msgid.rpartition(".")[0]
         if Email.objects.filter(message_id=parent_id).exists():
             msg["In-Reply-To"] = "<%s>" % parent_id
         msg.set_payload("dummy message")
         add_to_list("example-list", msg)
         emails.append(Email.objects.get(message_id=msgid))
     return emails
 def test_non_ascii_email_address(self):
     """Non-ascii email addresses should raise a ValueError exception"""
     msg = EmailMessage(policy=default)
     msg["From"] = "dummy-non-ascii-\xc3\[email protected]"
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except ValueError as e:
         self.assertEqual(e.__class__.__name__, "ValueError")
     else:
         self.fail("No ValueError was raised")
     self.assertEqual(
         MailingList.objects.get(name="example-list").emails.count(), 0)
예제 #40
0
 def test_email_escaped_sender(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msg2>"
     msg.set_payload("Dummy content")
     add_to_list("*****@*****.**", msg)
     url = reverse('hk_message_index',
                   args=("*****@*****.**", get_message_id_hash("msg2")))
     response = self.client.get(url)
     self.assertNotContains(response,
                            "*****@*****.**",
                            status_code=200)
 def test_archived_date(self):
     msg = EmailMessage()
     msg["From"] = "*****@*****.**"
     msg["Subject"] = "Fake Subject"
     msg["Message-ID"] = "<dummy>"
     msg["Date"] = "Fri, 02 Nov 2012 16:07:54"
     msg.set_payload("Fake Message")
     msg.set_unixfrom("[email protected] Mon Jul 21 11:59:48 2013")
     add_to_list("example-list", msg)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertEqual(
         stored_msg.archived_date,
         datetime.datetime(2013, 7, 21, 11, 59, 48, tzinfo=timezone.utc))
예제 #42
0
 def test_as_message_unicode(self):
     msg_in = EmailMessage()
     msg_in["From"] = "*****@*****.**"
     msg_in["Message-ID"] = "<msg>"
     msg_in.set_payload("Dummy message ünîcödé", charset="utf-8")
     add_to_list("*****@*****.**", msg_in)
     email = Email.objects.get(message_id="msg")
     msg = email.as_message()
     self.assertEqual(msg["From"], "*****@*****.**")
     self.assertEqual(msg["Message-ID"], "<msg>")
     self.assertTrue(msg.is_multipart())
     payload = msg.get_payload()
     self.assertEqual(len(payload), 1)
     payload = payload[0]
     self.assertEqual(payload.get_payload(), "Dummy message ünîcödé\n")
예제 #43
0
def archive(request):
    if request.method != 'POST':
        raise SuspiciousOperation
    mlist_fqdn = request.POST["mlist"]
    if "message" not in request.FILES:
        raise SuspiciousOperation
    msg = message_from_file(request.FILES['message'])
    try:
        add_to_list(mlist_fqdn, msg)
    except DuplicateMessage as e:
        logger.info("Duplicate email with message-id '%s'", e.args[0])
    url = _get_url(mlist_fqdn, msg['Message-Id'])
    logger.info("Archived message %s to %s", msg['Message-Id'], url)
    return HttpResponse(json.dumps({"url": url}),
                        content_type='application/javascript')
 def _send_message(self):
     msg = EmailMessage()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Message-ID"] = "<msg>"
     msg["Subject"] = "Dummy message"
     msg.set_payload("Dummy content")
     return add_to_list("*****@*****.**", msg)
예제 #45
0
 def test_top_participants(self):
     expected = [
         ("name3", "email3", 3),
         ("name2", "email2", 2),
         ("name1", "email1", 1),
     ]
     for name, email, count in expected:
         for num in range(count):
             msg = Message()
             msg["From"] = "%s <%s>" % (name, email)
             msg["Message-ID"] = "<%s_%s>" % (name, num)
             msg.set_payload("Dummy message")
             add_to_list("example-list", msg)
     mlist = MailingList.objects.get(name="example-list")
     result = [(p.name, p.address, p.count) for p in mlist.top_posters]
     self.assertEqual(expected, result)
예제 #46
0
 def _send_message(self, mlist):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Message-ID"] = "<msg>"
     msg["Subject"] = "Dummy message"
     msg.set_payload("Dummy content with keyword")
     return add_to_list(mlist.name, msg)
예제 #47
0
 def test_email_in_link_in_body(self):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msgid2>"
     msg["In-Reply-To"] = "<msgid>"
     link = "http://example.com/list/[email protected]/message"
     msg.set_payload("Email address in link: %s" % link)
     add_to_list("*****@*****.**", msg)
     url = reverse('hk_thread', args=["*****@*****.**", self.threadid])
     response = self.client.get(url)
     self.assertContains(
         response,
         '<a href="{0}" rel="nofollow">{0}</a>'.format(link),
         status_code=200)
예제 #48
0
 def _add_message(self, msgid="msg", list="*****@*****.**"):
     msg = EmailMessage()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Message-ID"] = "<%s>" % msgid
     msg["Subject"] = "Dummy message"
     msg.set_payload("Dummy content with keyword")
     return add_to_list(list, msg)
예제 #49
0
 def test_same_msgid_different_lists(self):
     # Vote on messages with the same msgid but on different lists
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg>"
     msg.set_payload("message")
     add_to_list("example-list-1", msg)
     add_to_list("example-list-2", msg)
     self.assertEqual(Email.objects.count(), 2)
     for msg in Email.objects.all():
         msg.vote(1, self.user)
     self.assertEqual(Thread.objects.count(), 2)
     for thread in Thread.objects.all():
         votes = thread.get_votes()
         self.assertEqual(votes["likes"], 1)
         self.assertEqual(votes["dislikes"], 0)
 def test_non_ascii_text_attachment_declared_as_ascii(self):
     # Some defective mail has a text attachment declared as ascii but
     # containing non-ascii. We should just replace the non-ascii character.
     with open(get_test_file("attachment-4.txt")) as email_file:
         msg = message_from_file(email_file, EmailMessage, policy=default)
     try:
         add_to_list("example-list", msg)
     except Exception as e:
         self.fail(e)
     self.assertEqual(Attachment.objects.count(), 1)
     self.assertEqual(
         Attachment.objects.all()[0].content,
         b'All votes are reported in the form "*Y-N-A*" '
         b'(*in favor-Y???opposed-N???abstentions-A*; e.g. '
         b'"5-1-2" means "5 in favor, 1 opposed, and 2 '
         b'abstentions").\n')
 def test_duplicate_nonascii(self):
     msg = EmailMessage()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<dummy>"
     msg.set_payload("Dummy message")
     add_to_list("example-list", msg)
     mlist = MailingList.objects.get(name="example-list")
     self.assertEqual(mlist.emails.count(), 1)
     self.assertTrue(mlist.emails.filter(message_id="dummy").exists())
     msg.replace_header("From", "dummy-non-ascii\xc3\[email protected]")
     try:
         self.assertRaises(DuplicateMessage, add_to_list, "example-list",
                           msg)
     except UnicodeDecodeError as e:
         self.fail("Died on a non-ascii header message: %s" % (e))
     self.assertEqual(mlist.emails.count(), 1)
예제 #52
0
 def test_order(self):
     # The Thread instances returned by get_or_set() should be returned in
     # the order of the list returned by get_value().
     # Create users to vote
     users = []
     for uid in range(20):
         users.append(User.objects.create(username="******" % uid))
     # Create the threads to be voted on
     votes_count = list(range(1, 21))
     shuffle(votes_count)
     # Add the emails in random order
     for votes_num in votes_count:
         msg = EmailMessage()
         msg["From"] = "*****@*****.**"
         msg["Message-ID"] = "<msg%d>" % votes_num
         msg["Date"] = datetime.now().strftime("%d %b %Y %H:%M:%S %Z")
         msg.set_payload("message %d" % votes_num)
         msg_id = add_to_list(self.ml.name, msg)
         # Vote on the thread
         thread = Thread.objects.get(thread_id=msg_id)
         for uid in range(votes_num):
             thread.starting_email.vote(1, users[uid])
     # The PopularThreads value should be reverse-sorted by vote.
     self.assertListEqual(
         [t.starting_email.message_id for t in self.cached_value()],
         ["msg%d" % i for i in range(20, 0, -1)])
 def test_starting_message_1(self):
     # A basic thread: msg2 replies to msg1
     msg1 = EmailMessage()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1.set_payload("message 1")
     add_to_list("example-list", msg1)
     msg2 = EmailMessage()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2.set_payload("message 2")
     msg2["In-Reply-To"] = msg1["Message-ID"]
     add_to_list("example-list", msg2)
     self.assertEqual(Thread.objects.count(), 1)
     thread = Thread.objects.all()[0]
     self.assertEqual(thread.starting_email.message_id, "msg1")
예제 #54
0
 def test_display_fixed(self):
     msg = Message()
     msg["From"] = "Dummy Sender <*****@*****.**>"
     msg["Subject"] = "Dummy Subject"
     msg["Date"] = "Mon, 02 Feb 2015 13:00:00 +0300"
     msg["Message-ID"] = "<msg2>"
     msg.set_payload("Dummy message with @@ signs (looks like a patch)")
     add_to_list("*****@*****.**", msg)
     url1 = reverse('hk_message_index',
                    args=("*****@*****.**", get_message_id_hash("msg")))
     response1 = self.client.get(url1)
     self.assertNotContains(response1, "email-body fixed", status_code=200)
     url2 = reverse('hk_message_index',
                    args=("*****@*****.**", get_message_id_hash("msg2")))
     response2 = self.client.get(url2)
     self.assertContains(response2, "email-body fixed", status_code=200)
예제 #55
0
 def setUp(self):
     self.user = User.objects.create_user('testuser', '*****@*****.**',
                                          'testPass')
     MailingList.objects.create(name="*****@*****.**",
                                subject_prefix="[example] ",
                                archive_policy=ArchivePolicy.private.value)
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msgid>"
     msg["Subject"] = "Dummy message"
     msg.set_payload("Dummy message")
     msg["Message-ID-Hash"] = self.msgid = add_to_list(
         "*****@*****.**", msg)
     # Set the mailman_client after the message has been added to the list,
     # otherwise MailingList.update_from_mailman() will overwrite the list
     # properties.
     self.mailman_client.get_list.side_effect = \
         lambda name: FakeMMList(name)
     self.mm_user = Mock()
     self.mm_user.user_id = "dummy"
     self.mailman_client.get_user.side_effect = lambda name: self.mm_user
     self.mm_user.subscriptions = [
         FakeMMMember("list.example.com", self.user.email),
     ]
     self.mm_user.addresses = ['*****@*****.**']
예제 #56
0
    def setUp(self):
        MailingList.objects.create(name="*****@*****.**",
                                   subject_prefix="[example] ",
                                   archive_policy=ArchivePolicy.private.value)
        msg = EmailMessage()
        msg["From"] = "*****@*****.**"
        msg["Message-ID"] = "<msgid>"
        msg["Subject"] = "Dummy message"
        msg.set_payload("Dummy message")
        msg["Message-ID-Hash"] = self.msgid = add_to_list(
            "*****@*****.**", msg)
        self.mailman_client.get_list.side_effect = \
            lambda name: FakeMMList(name)

        User.objects.create_user('superuser',
                                 '*****@*****.**',
                                 'testPass',
                                 is_superuser=True)

        self.mm_subbed_user = self._create_user('subbeduser',
                                                '*****@*****.**')
        self.mm_subbed_user.subscriptions = [
            FakeMMMember("list.example.com", '*****@*****.**'),
        ]
        self.mm_unsubbed_user = self._create_user('unsubbeduser',
                                                  '*****@*****.**')
        self.mm_unsubbed_user.subscriptions = []

        def mm_get_user(email):
            if email == '*****@*****.**':
                return self.mm_subbed_user
            else:
                return self.mm_unsubbed_user

        self.mailman_client.get_user.side_effect = mm_get_user
예제 #57
0
def _create_email(num, reply_to=None):
    msg = EmailMessage()
    msg["From"] = "*****@*****.**" % num
    msg["Message-ID"] = "<msg%d>" % num
    msg.set_payload("message %d" % num)
    if reply_to is not None:
        msg["In-Reply-To"] = "<msg%d>" % reply_to
    return add_to_list("example-list", msg)
예제 #58
0
 def test_thread(self):
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg2>"
     msg["In-Reply-To"] = "<msg>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
     # Add a message in a different thread:
     msg = Message()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "<msg3>"
     msg.set_payload("Dummy message")
     add_to_list("*****@*****.**", msg)
     thread_id = Email.objects.get(message_id="msg").thread.thread_id
     mbox = self._get_mbox(qs="thread=%s" % thread_id)
     self.assertEqual(len(mbox), 2)
     self.assertEqual([m["Message-ID"] for m in mbox], ["<msg>", "<msg2>"])
 def test_starting_message_2(self):
     # A partially-imported thread: msg1 replies to something we don't have
     msg1 = EmailMessage()
     msg1["From"] = "*****@*****.**"
     msg1["Message-ID"] = "<msg1>"
     msg1["In-Reply-To"] = "<msg0>"
     msg1.set_payload("message 1")
     add_to_list("example-list", msg1)
     msg2 = EmailMessage()
     msg2["From"] = "*****@*****.**"
     msg2["Message-ID"] = "<msg2>"
     msg2["In-Reply-To"] = msg1["Message-ID"]
     msg2.set_payload("message 2")
     add_to_list("example-list", msg2)
     self.assertEqual(Thread.objects.count(), 1)
     thread = Thread.objects.all()[0]
     self.assertEqual(thread.starting_email.message_id, "msg1")
 def test_long_message_id(self):
     # Some message-ids are more than 255 chars long
     # Check with assert here because SQLite will not enforce the limit
     # (http://www.sqlite.org/faq.html#q9)
     msg = EmailMessage()
     msg["From"] = "*****@*****.**"
     msg["Message-ID"] = "X" * 260
     msg.set_payload("Dummy message")
     try:
         add_to_list("example-list", msg)
     except IntegrityError as e:
         self.fail(e)
     self.assertEqual(Email.objects.count(), 1)
     stored_msg = Email.objects.all()[0]
     self.assertTrue(
         len(stored_msg.message_id) <= 255,
         "Very long message-id headers are not truncated")