# -*- coding: iso-8859-1 -* ## ## ## import sys, os import stat if __name__ == '__main__': execfile(os.path.join(sys.path[0], 'framework.py')) from base import TestBase #------------------------------------------------------------------------------ # # Some constants # #------------------------------------------------------------------------------ class POP3TestCase(TestBase): """ Test to create a POP3 account object and several accepting email accounts inside it. """ def test_creatingAccount(self): """ test to create a POP3 account """ tracker = self.folder.tracker self.assertEqual(tracker.getPOP3Accounts(), []) tracker.createPOP3Account('mail.example.com', 'peter', 'secret') self.assertEqual(len(tracker.getPOP3Accounts()), 1) account = tracker.getPOP3Accounts()[0] self.assertEqual(account.getTitle(), 'mail.example.com') self.assertEqual(account.getHostname(), 'mail.example.com') self.assertEqual(account.getPort(), 110) self.assertEqual(account.getUsername(), 'peter') self.assertFalse(account.doDeleteAfter()) self.assertFalse(account.doSSL()) self.assertEqual(len(account.getAcceptingEmails()), 0) # try editing it account.manage_editAccount(hostname='m.example.com', username='peterbe', portnr=210, delete_after=1) self.assertEqual(account.getHostname(), 'm.example.com') self.assertEqual(account.getPort(), 210) self.assertEqual(account.getUsername(), 'peterbe') self.assertTrue(account.doDeleteAfter()) def test_creatingAcceptingEmail(self): """ test to create a POP3 account accepting email object """ tracker = self.folder.tracker account = tracker.createPOP3Account('mail.example.com', 'peter', 'secret') # there are unfortunately two different ways to create accepting email # objects. Either directly on the account or via the issuetracker # itself. With the latter option, you have to pass the ID of the # account. # The latter one is more user friendly and easier to "access" because # that's what the DTML files do. ae = tracker.createAcceptingEmail(account.getId(), 'mail@example.com') self.assertEqual(ae.aq_parent.absolute_url(), account.absolute_url()) self.assertEqual(ae.getEmailAddress(), 'mail@example.com') self.assertFalse(ae.doSendConfirm()) self.assertFalse(ae.revealIssueURL()) ## try to mess with it # invalid email address self.assertRaises(ValueError, tracker.createAcceptingEmail, account.getId(), 'mail @ example.com') # non-existant pop3 account self.assertRaises(AttributeError, tracker.createAcceptingEmail, 'zxy', 'mail@example.com') ## test to edit the accepting email object ae.editDetails(email_address='www@example.com', send_confirm=True, reveal_issue_url=True) self.assertEqual(ae.getEmailAddress(), 'www@example.com') self.assertTrue(ae.doSendConfirm()) self.assertTrue(ae.revealIssueURL()) def test_acceptingEmailMatch(self): """ try creating a accepting email address and add some whitelist and blacklist email addresses. """ tracker = self.folder.tracker account = tracker.createPOP3Account('mail.example.com', 'peter', 'secret') ae = tracker.createAcceptingEmail(account.getId(), 'mail@example.com') # just blacklist ae.editDetails(blacklist_emails=['test@peterbe.com']) self.assertFalse(ae.acceptOriginatorEmail('TEST@peterbe.COM')) self.assertTrue(ae.acceptOriginatorEmail('TEST.ElSE@peterbe.COM')) ae.editDetails(blacklist_emails=['*@peterbe.com'], whitelist_emails=['exception@peterbe.com']) self.assertFalse(ae.acceptOriginatorEmail('TEST@peterbe.COM')) self.assertTrue(ae.acceptOriginatorEmail('eXception@peterbe.COM')) from poplib import POP3, error_proto class FakePOP3(POP3): username = 'test' password = 'test' files = [] def __init__(self, hostname, port=110): self.hostname = hostname self.port = port def getwelcome(self): return "Welcome to fake account" def user(self, user): if user != self.username: raise error_proto("Wrong username.") def pass_(self, pswd): if pswd != self.password: raise error_proto("Wrong password.") def list(self, which=None): # eg. ('+OK 4 messages:', ['1 71017', '2 2201', '3 7723', '4 44152'], 34) files = self.files responses = [] for i, f in enumerate(files): responses.append('%s %s' % (i+1, os.stat(f)[stat.ST_SIZE])) return ('+OK %s messages:' % len(files), responses, None) def retr(self, which): # ['response', ['line', ...], octets] filename = self.files[which-1] return ('response', open(filename, 'r').xreadlines(), None) def quit(self): pass class EmailInTestCase(TestBase): """ Here we'll try to actually send some emails in to the issuetracker by setting up a fake POP3 server. """ def test_emailIn1(self): """ test a very basic email in """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) FakePOP3.files = [abs_path('email-in-1.email')] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) # this should have created an issue self.assertEqual(len(tracker.getIssueObjects()), 1) def test_emailIn1_with_autoreply(self): """ test a very basic email in """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) FakePOP3.files = [abs_path('email-in-1_with-autoreply.email'), abs_path('email-in-2_with-autoreply.email')] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 0 issues') > -1) # this should have created an issue self.assertEqual(len(tracker.getIssueObjects()), 0) def test_emailIn2(self): """ test rejecting an email based on from address """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) ae.editDetails(blacklist_emails=['*@peterbe.com'], whitelist_emails=['special@peterbe.com']) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # this sends from mail@peterbe.com and another one from special@peterbe.com FakePOP3.files = [abs_path('email-in-1.email'), abs_path('email-in-2.email')] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) # this should have created an issue self.assertEqual(len(tracker.getIssueObjects()), 1) def test_emailIn3(self): """ test setting section, urgency and type by the subject line """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # this sends from mail@peterbe.com and another one from special@peterbe.com FakePOP3.files = [abs_path('email-in-3.email'),] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) issue = tracker.getIssueObjects()[0] self.assertEqual(issue.getSections(), ['General']) self.assertEqual(issue.getUrgency(), 'critical') self.assertEqual(issue.getType(), 'bug report') self.assertEqual(issue.getTitle(), 'NonExistant: There is a problem') def test_emailIn4(self): """ Test emails CCed in """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-4.email' sends to peter@example.com but is CCed to # mail@example.com FakePOP3.files = [abs_path('email-in-4.email'),] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) # this should have created an issue self.assertEqual(len(tracker.getIssueObjects()), 1) def test_emailIn5(self): """ Test emails in multipart """ tracker = self.folder.tracker self._send_in_emails('email-in-5.email') result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) issue = tracker.getIssueObjects()[0] self.assertTrue(isinstance(issue.getTitle(), unicode)) # XXX I'm not sure what this test is meant to test. # Perhaps the functionality of emailing in HTML emails should # change to show HTML safely. def test_emailIn6(self): """ Test emails with type and urgency in the subject line """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-4.email' sends to peter@example.com but is CCed to # mail@example.com FakePOP3.files = [abs_path('email-in-6.email'),] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) # this should have created an issue self.assertEqual(len(tracker.getIssueObjects()), 1) issue = tracker.getIssueObjects()[0] self.assertEqual(issue.getUrgency(), 'critical') self.assertEqual(issue.getType(), 'bug report') self.assertEqual(issue.getSections(), ['Homepage']) self.assertEqual(issue.getTitle(), u'Subject line') self.assertTrue(isinstance(issue.getTitle(), unicode)) def test_emailIn7(self): """ Test emails with 'Re:' in the subject line """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-4.email' sends to peter@example.com but is CCed to # mail@example.com FakePOP3.files = [abs_path('email-in-7.email'),] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) issue = tracker.getIssueObjects()[0] self.assertEqual(issue.getTitle(), u'Re: Hello') def test_emailIn8(self): """ Test what the email in receipt says when emailing in """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) ae.send_confirm = True abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-4.email' sends to peter@example.com but is CCed to # mail@example.com FakePOP3.files = [abs_path('email-in-8.email'),] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) receipt = self.snatched_emails[0] self.assertEqual(receipt['to'], 'Mr Exception ') self.assertTrue(receipt['subject'].count(tracker.getTitle())) # expect the issue id to be mentioned in the email msg issue = tracker.getIssueObjects()[0] self.assertTrue(receipt['msg'].count(issue.getId())) # do it again and this time configure the receipt to # reveal the issue URL ae.reveal_issue_url = True FakePOP3.files = [abs_path('email-in-8b.email'),] result = tracker.check4MailIssues(verbose=False) assert len(tracker.getIssueObjects()) == 2 issue2 = tracker.getIssueObjects()[1] receipt = self.snatched_emails[1] self.assertTrue(receipt['msg'].count(issue2.absolute_url())) def test_emailIn9(self): """Test email with content encoding 'unicode-1-1-utf-7'""" tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) ae.send_confirm = True abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-4.email' sends to peter@example.com but is CCed to # mail@example.com FakePOP3.files = [abs_path('email-in-9.email'),] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue('Saved email' in result) def test_emailIn_none(self): """ Test emails in multipart """ tracker = self.folder.tracker self._send_in_emails([]) result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 0 issue') > -1) issues = len(tracker.getIssueObjects()) self.assertEqual(issues, 0) def test_emailInMultipart(self): """ when emailing in an email with multipart text and html, favor the text part. """ tracker = self.folder.tracker self._send_in_emails('multipart-email-with-ms.email', accepting_email='ims@issuetrackerproduct.com') result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) issue = tracker.getIssueObjects()[0] description = issue.description self.assertTrue('THIS IS THE PLAIN PART' in description) display_format = issue.display_format self.assertEqual(display_format, 'plaintext') def _send_in_emails(self, email_filenames, accepting_email='mail@example.com'): tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = accepting_email ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-5.email' is multipart/alternative and the HTML part of it # is not quoted. if not isinstance(email_filenames, (tuple, list)): email_filenames = [email_filenames] FakePOP3.files = [abs_path(x) for x in email_filenames] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 def test_jp_regression_tests(self): """ these tests come from a bug report by Jesse. """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'helpdesktest@example3.org' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-5.email' is multipart/alternative and the HTML part of it # is not quoted. FakePOP3.files = [abs_path('jp-0.email'), abs_path('jp-1.email')] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 2 issues') > -1) def test__appendEmailIssueData(self): """ test the private method _appendEmailIssueData() """ tracker = self.folder.tracker u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'helpdesktest@example3.org' ae = tracker.createAcceptingEmail(account.getId(), email) email = {'subject':'Re: Fwd: Foo, High, Bug Report: Subject line', 'to':'helpdesktest@example3.org', 'from':'test@peterbe.com' } email = tracker._appendEmailIssueData([email], account)[0] # expect certain things from this email. # Since none of the sections in this tracker was in the subject line # expect the sections to be the default self.assertEqual(email['sections'], tracker.getDefaultSections()) # The subject line contained some junk ('Fwd: Re:') followed by some # sensible parsable stuff where one word is neither section, type # or urgency. Therefor the issue subject must be 'Foo: Subject line' self.assertEqual(email['title'], u'Foo: Subject line') self.assertTrue(isinstance(email['title'], unicode)) # The urgency is 'High' in the parsable subject line self.assertEqual(email['urgency'], u'high') # And the type is Bug report self.assertEqual(email['type'], u'bug report') def test_email_in_without_General_section(self): """A stupidity test that checks that it's possible to email in an issue into an issuetracker instance that doesn't have of the default sections. """ tracker = self.folder.tracker tracker.sections_options = [u'Other', u'One'] u, p = 'test', 'test' # doesn't really matter account = tracker.createPOP3Account('mail.example.com', u, p) email = 'mail@example.com' ae = tracker.createAcceptingEmail(account.getId(), email) abs_path = lambda x: os.path.join(os.path.dirname(__file__), x) # 'email-in-5.email' is multipart/alternative and the HTML part of it # is not quoted. FakePOP3.files = [abs_path('no-general.email')] # Monkey patch! from Products.IssueTrackerProduct import IssueTracker IssueTracker.POP3 = FakePOP3 result = tracker.check4MailIssues(verbose=True) self.assertTrue(result.find('Created 1 issue') > -1) def test_suite(): from unittest import TestSuite, makeSuite suite = TestSuite() suite.addTest(makeSuite(POP3TestCase)) suite.addTest(makeSuite(EmailInTestCase)) return suite if __name__ == '__main__': framework()