# -*- coding: utf-8 -*- import sys import hashlib import unittest from tests.util import * TEXT = """MIME-Version: 1.0 Sender: chirila@spamexperts.com Received: by 10.216.90.129 with HTTP; Fri, 23 Aug 2013 01:59:03 -0700 (PDT) Date: Fri, 23 Aug 2013 11:59:03 +0300 Delivered-To: chirila@spamexperts.com X-Google-Sender-Auth: p6ay4c-tEtdFpavndA9KBmP0CVs Message-ID: Subject: Test From: Alexandru Chirila To: Alexandru Chirila Content-Type: multipart/alternative; boundary=001a11c2893246a9e604e4999ea3 --001a11c2893246a9e604e4999ea3 Content-Type: text/plain; charset=ISO-8859-1 %s --001a11c2893246a9e604e4999ea3 """ HTML_TEXT = """MIME-Version: 1.0 Sender: chirila@gapps.spamexperts.com Received: by 10.216.157.70 with HTTP; Thu, 16 Jan 2014 00:43:31 -0800 (PST) Date: Thu, 16 Jan 2014 10:43:31 +0200 Delivered-To: chirila@gapps.spamexperts.com X-Google-Sender-Auth: ybCmONS9U9D6ZUfjx-9_tY-hF2Q Message-ID: Subject: Test From: Alexandru Chirila To: Alexandru Chirila Content-Type: multipart/alternative; boundary=001a11c25ff293069304f0126bfd --001a11c25ff293069304f0126bfd Content-Type: text/plain; charset=ISO-8859-1 Email spam. Email spam, also known as junk email or unsolicited bulk email, is a subset of electronic spam involving nearly identical messages sent to numerous recipients by email. Clicking on links in spam email may send users to phishing web sites or sites that are hosting malware. --001a11c25ff293069304f0126bfd Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Email spam.

Email spam, also= known as junk email or unsolicited bulk email, is a subset of electronic s= pam involving nearly identical messages sent to numerous recipients by emai= l. Clicking on links in spam email may send users to phishing web sites or = sites that are hosting malware.
--001a11c25ff293069304f0126bfd-- """ TEXT_ATTACHMENT = """MIME-Version: 1.0 Received: by 10.76.127.40 with HTTP; Fri, 17 Jan 2014 02:21:43 -0800 (PST) Date: Fri, 17 Jan 2014 12:21:43 +0200 Delivered-To: chirila.s.alexandru@gmail.com Message-ID: Subject: Test From: Alexandru Chirila To: Alexandru Chirila Content-Type: multipart/mixed; boundary=f46d040a62c49bb1c804f027e8cc --f46d040a62c49bb1c804f027e8cc Content-Type: multipart/alternative; boundary=f46d040a62c49bb1c404f027e8ca --f46d040a62c49bb1c404f027e8ca Content-Type: text/plain; charset=ISO-8859-1 This is a test mailing --f46d040a62c49bb1c404f027e8ca-- --f46d040a62c49bb1c804f027e8cc Content-Type: image/png; name="tar.png" Content-Disposition: attachment; filename="tar.png" Content-Transfer-Encoding: base64 X-Attachment-Id: f_hqjas5ad0 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 QmCC --f46d040a62c49bb1c804f027e8cc--""" class PyzorPreDigestTest(PyzorTestBase): # we don't need the pyzord server to test this @classmethod def setUpClass(cls): pass @classmethod def tearDownClass(cls): pass def setUp(self): # no argument necessary self.client_args = {} def test_predigest_email(self): """Test email removal in the predigest process""" emails = ["t@abc.ro", "t1@abc.ro", "t+@abc.ro", "t.@abc.ro", ] message = "Test %s Test2" expected = b"TestTest2\n" for email in emails: msg = message % email res = self.check_pyzor("predigest", None, input=TEXT % msg) self.assertEqual(res, expected) def test_predigest_long(self): """Test long "words" removal in the predigest process""" strings = ["0A2D3f%a#S", "3sddkf9jdkd9", "@@#@@@@@@@@@"] message = "Test %s Test2" expected = b"TestTest2\n" for s in strings: msg = message % s res = self.check_pyzor("predigest", None, input=TEXT % msg) self.assertEqual(res, expected) def test_predigest_line_length(self): """Test small lines removal in the predigest process""" msg = "This line is included\n"\ "not this\n"\ "This also" expected = b"Thislineisincluded\nThisalso\n" res = self.check_pyzor("predigest", None, input=TEXT % msg) self.assertEqual(res, expected) def test_predigest_atomic(self): """Test atomic messages (lines <= 4) in the predigest process""" msg = "All this message\nShould be included\nIn the predigest" expected = b"Allthismessage\nShouldbeincluded\nInthepredigest\n" res = self.check_pyzor("predigest", None, input=TEXT % msg) self.assertEqual(res, expected) def test_predigest_pieced(self): """Test pieced messages (lines > 4) in the predigest process""" msg = "" for i in range(100): msg += "Line%d test test test\n" % i expected = b"" for i in [20, 21, 22, 60, 61, 62]: expected += ("Line%dtesttesttest\n" % i).encode("utf8") res = self.check_pyzor("predigest", None, input=TEXT % msg) self.assertEqual(res, expected) def test_predigest_html(self): expected = """Emailspam,alsoknownasjunkemailorbulkemail,isasubset ofspaminvolvingnearlyidenticalmessagessenttonumerous byemail.Clickingonlinksinspamemailmaysendusersto byemail.Clickingonlinksinspamemailmaysendusersto phishingwebsitesorsitesthatarehostingmalware. Emailspam.Emailspam,alsoknownasjunkemailorbulkemail,isasubsetofspaminvolvingnearlyidenticalmessagessenttonumerousbyemail.Clickingonlinksinspamemailmaysenduserstophishingwebsitesorsitesthatarehostingmalware. """.encode("utf8") res = self.check_pyzor("predigest", None, input=HTML_TEXT) self.assertEqual(res, expected) def test_predigest_attachemnt(self): expected = b"Thisisatestmailing\n" res = self.check_pyzor("predigest", None, input=TEXT_ATTACHMENT) self.assertEqual(res, expected) class PyzorDigestTest(PyzorTestBase): # we don't need the pyzord server to test this @classmethod def setUpClass(cls): pass @classmethod def tearDownClass(cls): pass def setUp(self): # no argument necessary self.client_args = {} def test_digest_email(self): """Test email removal in the digest process""" emails = ["t@abc.ro", "t1@abc.ro", "t+@abc.ro", "t.@abc.ro", ] message = "Test %s Test2" expected = b"TestTest2" for email in emails: msg = message % email res = self.check_pyzor("digest", None, input=TEXT % msg) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") def test_digest_long(self): """Test long "words" removal in the digest process""" strings = ["0A2D3f%a#S", "3sddkf9jdkd9", "@@#@@@@@@@@@"] message = "Test %s Test2" expected = b"TestTest2" for s in strings: msg = message % s res = self.check_pyzor("digest", None, input=TEXT % msg) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") def test_digest_line_length(self): """Test small lines removal in the digest process""" msg = "This line is included\n"\ "not this\n"\ "This also" expected = b"ThislineisincludedThisalso" res = self.check_pyzor("digest", None, input=TEXT % msg) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") def test_digest_atomic(self): """Test atomic messages (lines <= 4) in the digest process""" msg = "All this message\nShould be included\nIn the digest" expected = b"AllthismessageShouldbeincludedInthedigest" res = self.check_pyzor("digest", None, input=TEXT % msg) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") def test_digest_pieced(self): """Test pieced messages (lines > 4) in the digest process""" msg = "" for i in range(100): msg += "Line%d test test test\n" % i expected = b"" for i in [20, 21, 22, 60, 61, 62]: expected += ("Line%dtesttesttest" % i).encode("utf8") res = self.check_pyzor("digest", None, input=TEXT % msg) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") def test_digest_html(self): expected = """Emailspam,alsoknownasjunkemailorbulkemail,isasubset ofspaminvolvingnearlyidenticalmessagessenttonumerous byemail.Clickingonlinksinspamemailmaysendusersto byemail.Clickingonlinksinspamemailmaysendusersto phishingwebsitesorsitesthatarehostingmalware. Emailspam.Emailspam,alsoknownasjunkemailorbulkemail,isasubsetofspaminvolvingnearlyidenticalmessagessenttonumerousbyemail.Clickingonlinksinspamemailmaysenduserstophishingwebsitesorsitesthatarehostingmalware. """.replace("\n", "").encode("utf8") res = self.check_pyzor("digest", None, input=HTML_TEXT) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") def test_digest_attachemnt(self): expected = b"Thisisatestmailing" res = self.check_pyzor("digest", None, input=TEXT_ATTACHMENT) self.assertEqual(res.decode("utf8"), hashlib.sha1(expected).hexdigest().lower() + "\n") ENCODING_TEST_EMAIL = """From nobody Tue Apr 1 13:18:54 2014 Content-Type: multipart/related; boundary="===============0632694142025794937==" MIME-Version: 1.0 This is a multi-part message in MIME format. --===============0632694142025794937== Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Thist is a t=E9st --===============0632694142025794937== MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qg5r+A5YWJ6YCZ --===============0632694142025794937== MIME-Version: 1.0 Content-Type: text/plain; charset="cp1258" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHTpc3Qg4qXG --===============0632694142025794937==-- """ BAD_ENCODING = """From nobody Tue Apr 1 13:18:54 2014 Content-Type: multipart/related; boundary="===============0632694142025794937==" MIME-Version: 1.0 This is a multi-part message in MIME format. --===============0632694142025794937== Content-Type: text/plain; charset=ISO-8859-1Content-Transfer-Encoding: quoted-printable This is a test --===============0632694142025794937== Content-Type: text/plain; charset=us-asciia Content-Transfer-Encoding: quoted-printable This is a test --===============0632694142025794937== """ class PyzorEncodingTest(PyzorTestBase): # we don't need the pyzord server to test this @classmethod def setUpClass(cls): pass @classmethod def tearDownClass(cls): pass def setUp(self): # no argument necessary self.client_args = {} def test_encodings(self): expected = "47a83cd0e5cc9bd2c64c06c00e3853f79e63014f\n" res = self.check_pyzor("digest", None, input=ENCODING_TEST_EMAIL) self.assertEqual(res.decode("utf8"), expected) def test_bad_encoding(self): expected = "2b4dbf2fb521edd21d997f3f04b1c7155ba91fff\n" res = self.check_pyzor("digest", None, input=BAD_ENCODING) self.assertEqual(res.decode("utf8"), expected) def suite(): """Gather all the tests from this module in a test suite.""" test_suite = unittest.TestSuite() test_suite.addTest(unittest.makeSuite(PyzorDigestTest)) test_suite.addTest(unittest.makeSuite(PyzorPreDigestTest)) test_suite.addTest(unittest.makeSuite(PyzorEncodingTest)) return test_suite if __name__ == '__main__': unittest.main()