Mercurial > p > roundup > code
view test/test_mailgw.py @ 4587:a2eb4fb3e6d8
New Chameleon templating engine, engine is now configurable.
We now have two configurable templating engines, the old Zope TAL
templates (called zopetal in the config) and the new Chameleon (called
chameleon in the config). A new config-option "template_engine" under
[main] can take these config-options, the default is zopetal.
Thanks to Cheer Xiao for the idea of making this configurable *and*
for the actual implementation!
Cheer Xiao commit log:
- The original TAL engine ported from Zope is thereafter referred to as
"zopetal", in speech and in code
- A new option "template_engine" under [main] introduced
- Zopetal-specific code stripped from cgi/templating.py to form the new
cgi/engine_zopetal.py
- Interface to Chameleon in cgi/engine_chameleon.py
- Engines are supposed to provide a Templates class that mimics the
behavior of the old cgi.templating.Templates. The Templates class is
preferably subclassed from cgi.templating.TemplatesBase.
- New function cgi.templating.get_templates to get the appropriate engine's
Templates instance according to the engine name
| author | Ralf Schlatterbeck <rsc@runtux.com> |
|---|---|
| date | Thu, 23 Feb 2012 18:10:03 +0100 |
| parents | 782737d1a2d7 |
| children | 6e9b9743de89 |
line wrap: on
line source
# -*- encoding: utf-8 -*- # # Copyright (c) 2001 Richard Jones, richard@bofh.asn.au. # This module is free software, and you may redistribute it and/or modify # under the same terms as Python, so long as this copyright message and # disclaimer are retained in their original form. # # This module is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # TODO: test bcc import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822, time import gpgmelib from email.parser import FeedParser try: import pyme, pyme.core except ImportError: pyme = None from cStringIO import StringIO if not os.environ.has_key('SENDMAILDEBUG'): os.environ['SENDMAILDEBUG'] = 'mail-test.log' SENDMAILDEBUG = os.environ['SENDMAILDEBUG'] from roundup import mailgw, i18n, roundupdb from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \ parseContent, IgnoreLoop, IgnoreBulk, MailUsageError, MailUsageHelp from roundup import init, instance, password, rfc2822, __version__ from roundup.anypy.sets_ import set #import db_test_base import memorydb def expectedFailure(method): """ For marking a failing test. This will *not* run the test and return success instead. """ return lambda x: 0 class Message(rfc822.Message): """String-based Message class with equivalence test.""" def __init__(self, s): rfc822.Message.__init__(self, StringIO(s.strip())) def __eq__(self, other): return (self.dict == other.dict and self.fp.read() == other.fp.read()) class Tracker(object): def open(self, journaltag): return self.db class DiffHelper: def compareMessages(self, new, old): """Compare messages for semantic equivalence.""" new, old = Message(new), Message(old) # all Roundup-generated messages have "Precedence: bulk" old['Precedence'] = 'bulk' # don't try to compare the date del new['date'], old['date'] if not new == old: res = [] replace = {} for key in new.keys(): if key.startswith('from '): # skip the unix from line continue if key.lower() == 'x-roundup-version': # version changes constantly, so handle it specially if new[key] != __version__: res.append(' %s: %r != %r' % (key, __version__, new[key])) elif key.lower() == 'content-type' and 'boundary=' in new[key]: # handle mime messages newmime = new[key].split('=',1)[-1].strip('"') oldmime = old.get(key, '').split('=',1)[-1].strip('"') replace ['--' + newmime] = '--' + oldmime replace ['--' + newmime + '--'] = '--' + oldmime + '--' elif new.get(key, '') != old.get(key, ''): res.append(' %s: %r != %r' % (key, old.get(key, ''), new.get(key, ''))) body_diff = self.compareStrings(new.fp.read(), old.fp.read(), replace=replace) if body_diff: res.append('') res.extend(body_diff) if res: res.insert(0, 'Generated message not correct (diff follows, expected vs. actual):') raise AssertionError, '\n'.join(res) def compareStrings(self, s2, s1, replace={}): '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants the first to be the "original" but in the calls in this file, the second arg is the original. Ho hum. Do replacements over the replace dict -- used for mime boundary ''' l1 = s1.strip().split('\n') l2 = [replace.get(i,i) for i in s2.strip().split('\n')] if l1 == l2: return s = difflib.SequenceMatcher(None, l1, l2) res = [] for value, s1s, s1e, s2s, s2e in s.get_opcodes(): if value == 'equal': for i in range(s1s, s1e): res.append(' %s'%l1[i]) elif value == 'delete': for i in range(s1s, s1e): res.append('- %s'%l1[i]) elif value == 'insert': for i in range(s2s, s2e): res.append('+ %s'%l2[i]) elif value == 'replace': for i, j in zip(range(s1s, s1e), range(s2s, s2e)): res.append('- %s'%l1[i]) res.append('+ %s'%l2[j]) return res class MailgwTestAbstractBase(unittest.TestCase, DiffHelper): count = 0 schema = 'classic' def setUp(self): self.old_translate_ = mailgw._ roundupdb._ = mailgw._ = i18n.get_translation(language='C').gettext self.__class__.count = self.__class__.count + 1 # and open the database / "instance" self.db = memorydb.create('admin') self.instance = Tracker() self.instance.db = self.db self.instance.config = self.db.config self.instance.MailGW = MailGW self.chef_id = self.db.user.create(username='Chef', address='chef@bork.bork.bork', realname='Bork, Chef', roles='User') self.richard_id = self.db.user.create(username='richard', address='richard@test.test', roles='User') self.mary_id = self.db.user.create(username='mary', address='mary@test.test', roles='User', realname='Contrary, Mary') self.john_id = self.db.user.create(username='john', address='john@test.test', roles='User', realname='John Doe', alternate_addresses='jondoe@test.test\njohn.doe@test.test') self.rgg_id = self.db.user.create(username='rgg', address='rgg@test.test', roles='User') def tearDown(self): roundupdb._ = mailgw._ = self.old_translate_ if os.path.exists(SENDMAILDEBUG): os.remove(SENDMAILDEBUG) self.db.close() def _allowAnonymousSubmit(self): p = [ self.db.security.getPermission('Register', 'user'), self.db.security.getPermission('Email Access', None), self.db.security.getPermission('Create', 'issue'), self.db.security.getPermission('Create', 'msg'), ] self.db.security.role['anonymous'].permissions = p def _create_mailgw(self, message, args=()): class MailGW(self.instance.MailGW): def handle_message(self, message): return self._handle_message(message) handler = MailGW(self.instance, args) handler.db = self.db return handler def _handle_mail(self, message, args=(), trap_exc=0): handler = self._create_mailgw(message, args) handler.trapExceptions = trap_exc return handler.main(StringIO(message)) def _get_mail(self): f = open(SENDMAILDEBUG) try: return f.read() finally: f.close() # Normal test-case used for both non-pgp test and a test while pgp # is enabled, so this test is run in both test suites. def testEmptyMessage(self): nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> Subject: [issue] Testing... ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...') class MailgwTestCase(MailgwTestAbstractBase): def testMessageWithFromInIt(self): nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> Subject: [issue] Testing... From here to there! ''') assert not os.path.exists(SENDMAILDEBUG) msgid = self.db.issue.get(nodeid, 'messages')[0] self.assertEqual(self.db.msg.get(msgid, 'content'), 'From here to there!') def testNoMessageId(self): self.instance.config['MAIL_DOMAIN'] = 'example.com' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Reply-To: chef@bork.bork.bork Subject: [issue] Testing... Hi there! ''') assert not os.path.exists(SENDMAILDEBUG) msgid = self.db.issue.get(nodeid, 'messages')[0] messageid = self.db.msg.get(msgid, 'messageid') x1, x2 = messageid.split('@') self.assertEqual(x2, 'example.com>') x = x1.split('.')[-1] self.assertEqual(x, 'issueNone') nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [issue%(nodeid)s] Testing... Just a test reply '''%locals()) msgid = self.db.issue.get(nodeid, 'messages')[-1] messageid = self.db.msg.get(msgid, 'messageid') x1, x2 = messageid.split('@') self.assertEqual(x2, 'example.com>') x = x1.split('.')[-1] self.assertEqual(x, "issue%s"%nodeid) def testOptions(self): nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Reply-To: chef@bork.bork.bork Subject: [issue] Testing... Hi there! ''', (('-C', 'issue'), ('-S', 'status=chatting;priority=critical'))) self.assertEqual(self.db.issue.get(nodeid, 'status'), '3') self.assertEqual(self.db.issue.get(nodeid, 'priority'), '1') def testOptionsMulti(self): nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Reply-To: chef@bork.bork.bork Subject: [issue] Testing... Hi there! ''', (('-C', 'issue'), ('-S', 'status=chatting'), ('-S', 'priority=critical'))) self.assertEqual(self.db.issue.get(nodeid, 'status'), '3') self.assertEqual(self.db.issue.get(nodeid, 'priority'), '1') def testOptionClass(self): nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Reply-To: chef@bork.bork.bork Subject: [issue] Testing... [status=chatting;priority=critical] Hi there! ''', (('-c', 'issue'),)) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...') self.assertEqual(self.db.issue.get(nodeid, 'status'), '3') self.assertEqual(self.db.issue.get(nodeid, 'priority'), '1') newmsg = '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: [issue] Testing... This is a test submission of a new issue. ''' def doNewIssue(self): nodeid = self._handle_mail(self.newmsg) assert not os.path.exists(SENDMAILDEBUG) l = self.db.issue.get(nodeid, 'nosy') l.sort() self.assertEqual(l, [self.chef_id, self.richard_id]) return nodeid def testNewIssue(self): self.doNewIssue() def testNewIssueNosy(self): self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes' nodeid = self.doNewIssue() m = self.db.issue.get(nodeid, 'messages') self.assertEqual(len(m), 1) recv = self.db.msg.get(m[0], 'recipients') self.assertEqual(recv, [self.richard_id]) def testNewIssueNosyAuthor(self): self.instance.config.ADD_AUTHOR_TO_NOSY = 'no' self.instance.config.MESSAGES_TO_AUTHOR = 'nosy' nodeid = self._handle_mail(self.newmsg) assert not os.path.exists(SENDMAILDEBUG) l = self.db.issue.get(nodeid, 'nosy') l.sort() self.assertEqual(l, [self.richard_id]) m = self.db.issue.get(nodeid, 'messages') self.assertEqual(len(m), 1) recv = self.db.msg.get(m[0], 'recipients') recv.sort() self.assertEqual(recv, [self.richard_id]) def testAlternateAddress(self): self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: John Doe <john.doe@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing... This is a test submission of a new issue. ''') userlist = self.db.user.list() assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(userlist, self.db.user.list(), "user created when it shouldn't have been") def testNewIssueNoClass(self): self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: Testing... This is a test submission of a new issue. ''') assert not os.path.exists(SENDMAILDEBUG) def testNewIssueAuthMsg(self): self.db.config.MESSAGES_TO_AUTHOR = 'yes' self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing... [nosy=mary; assignedto=richard] This is a test submission of a new issue. ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, mary@test.test, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, mary@test.test, richard@test.test From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: unread Content-Transfer-Encoding: quoted-printable New submission from Bork, Chef <chef@bork.bork.bork>: This is a test submission of a new issue. ---------- assignedto: richard messages: 1 nosy: Chef, mary, richard status: unread title: Testing... _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testNewIssueNoAuthorInfo(self): self.db.config.MAIL_ADD_AUTHORINFO = 'no' self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing... [nosy=mary; assignedto=richard] This is a test submission of a new issue. ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, mary@test.test, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: mary@test.test, richard@test.test From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: unread Content-Transfer-Encoding: quoted-printable This is a test submission of a new issue. ---------- assignedto: richard messages: 1 nosy: Chef, mary, richard status: unread title: Testing... _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testNewIssueNoAuthorEmail(self): self.db.config.MAIL_ADD_AUTHOREMAIL = 'no' self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing... [nosy=mary; assignedto=richard] This is a test submission of a new issue. ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, mary@test.test, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: mary@test.test, richard@test.test From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: unread Content-Transfer-Encoding: quoted-printable New submission from Bork, Chef: This is a test submission of a new issue. ---------- assignedto: richard messages: 1 nosy: Chef, mary, richard status: unread title: Testing... _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') multipart_msg = '''From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: multipart/mixed; boundary="bxyzzy" Content-Disposition: inline --bxyzzy Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWE" Content-Disposition: inline --bCsyhTFzCvuiizWE Content-Type: text/plain; charset=us-ascii Content-Disposition: inline test attachment first text/plain --bCsyhTFzCvuiizWE Content-Type: application/octet-stream Content-Disposition: attachment; filename="first.dvi" Content-Transfer-Encoding: base64 SnVzdCBhIHRlc3QgAQo= --bCsyhTFzCvuiizWE Content-Type: text/plain; charset=us-ascii Content-Disposition: inline test attachment second text/plain --bCsyhTFzCvuiizWE Content-Type: text/html Content-Disposition: inline <html> to be ignored. </html> --bCsyhTFzCvuiizWE-- --bxyzzy Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWF" Content-Disposition: inline --bCsyhTFzCvuiizWF Content-Type: text/plain; charset=us-ascii Content-Disposition: inline test attachment third text/plain --bCsyhTFzCvuiizWF Content-Type: application/octet-stream Content-Disposition: attachment; filename="second.dvi" Content-Transfer-Encoding: base64 SnVzdCBhIHRlc3QK --bCsyhTFzCvuiizWF-- --bxyzzy-- ''' multipart_msg_latin1 = '''From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: multipart/alternative; boundary=001485f339f8f361fb049188dbba --001485f339f8f361fb049188dbba Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable umlaut =E4=F6=FC=C4=D6=DC=DF --001485f339f8f361fb049188dbba Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <html>umlaut =E4=F6=FC=C4=D6=DC=DF</html> --001485f339f8f361fb049188dbba-- ''' multipart_msg_rfc822 = '''From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: multipart/mixed; boundary=001485f339f8f361fb049188dbba This is a multi-part message in MIME format. --001485f339f8f361fb049188dbba Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit First part: Text --001485f339f8f361fb049188dbba Content-Type: message/rfc822; name="Fwd: Original email subject.eml" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="Fwd: Original email subject.eml" Message-Id: <followup_dummy_id_2> In-Reply-To: <dummy_test_message_id_2> MIME-Version: 1.0 Subject: Fwd: Original email subject Date: Mon, 23 Aug 2010 08:23:33 +0200 Content-Type: multipart/alternative; boundary="090500050101020406060002" This is a multi-part message in MIME format. --090500050101020406060002 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit some text in inner email ======================== --090500050101020406060002 Content-Type: text/html; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit <html> some text in inner email ======================== </html> --090500050101020406060002-- --001485f339f8f361fb049188dbba-- ''' def testMultipartKeepAlternatives(self): self.doNewIssue() self._handle_mail(self.multipart_msg) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) assert(len(msg.files) == 5) names = {0 : 'first.dvi', 4 : 'second.dvi'} content = {3 : 'test attachment third text/plain\n', 4 : 'Just a test\n'} for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, names.get (n, 'unnamed')) if n in content : self.assertEqual(f.content, content [n]) self.assertEqual(msg.content, 'test attachment second text/plain') def testMultipartSeveralAttachmentMessages(self): self.doNewIssue() self._handle_mail(self.multipart_msg) messages = self.db.issue.get('1', 'messages') messages.sort() self.assertEqual(messages[-1], '2') msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 5) issue = self.db.issue.getnode ('1') self.assertEqual(len(issue.files), 5) names = {0 : 'first.dvi', 4 : 'second.dvi'} content = {3 : 'test attachment third text/plain\n', 4 : 'Just a test\n'} for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, names.get (n, 'unnamed')) if n in content : self.assertEqual(f.content, content [n]) self.assertEqual(msg.content, 'test attachment second text/plain') self.assertEqual(msg.files, ['1', '2', '3', '4', '5']) self.assertEqual(issue.files, ['1', '2', '3', '4', '5']) self._handle_mail(self.multipart_msg) issue = self.db.issue.getnode ('1') self.assertEqual(len(issue.files), 10) messages = self.db.issue.get('1', 'messages') messages.sort() self.assertEqual(messages[-1], '3') msg = self.db.msg.getnode (messages[-1]) self.assertEqual(issue.files, [str(i+1) for i in range(10)]) self.assertEqual(msg.files, ['6', '7', '8', '9', '10']) def testMultipartKeepFiles(self): self.doNewIssue() self._handle_mail(self.multipart_msg) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 5) issue = self.db.issue.getnode ('1') self.assertEqual(len(issue.files), 5) names = {0 : 'first.dvi', 4 : 'second.dvi'} content = {3 : 'test attachment third text/plain\n', 4 : 'Just a test\n'} for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, names.get (n, 'unnamed')) if n in content : self.assertEqual(f.content, content [n]) self.assertEqual(msg.content, 'test attachment second text/plain') self._handle_mail('''From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id2> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... This ist a message without attachment ''') issue = self.db.issue.getnode ('1') self.assertEqual(len(issue.files), 5) self.assertEqual(issue.files, ['1', '2', '3', '4', '5']) def testMultipartDropAlternatives(self): self.doNewIssue() self.db.config.MAILGW_IGNORE_ALTERNATIVES = True self._handle_mail(self.multipart_msg) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 2) names = {1 : 'second.dvi'} content = {0 : 'test attachment third text/plain\n', 1 : 'Just a test\n'} for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, names.get (n, 'unnamed')) if n in content : self.assertEqual(f.content, content [n]) self.assertEqual(msg.content, 'test attachment second text/plain') def testMultipartCharsetUTF8NoAttach(self): c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f' self.doNewIssue() self.db.config.NOSY_MAX_ATTACHMENT_SIZE = 0 self._handle_mail(self.multipart_msg_latin1) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 1) name = 'unnamed' content = '<html>' + c + '</html>\n' for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, name) self.assertEqual(f.content, content) self.assertEqual(msg.content, c) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting X-Roundup-Issue-Files: unnamed Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: umlaut =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F File 'unnamed' not attached - you can download it from http://tracker.examp= le/cgi-bin/roundup.cgi/bugs/file1. ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testMultipartCharsetLatin1NoAttach(self): c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f' self.doNewIssue() self.db.config.NOSY_MAX_ATTACHMENT_SIZE = 0 self.db.config.MAIL_CHARSET = 'iso-8859-1' self._handle_mail(self.multipart_msg_latin1) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 1) name = 'unnamed' content = '<html>' + c + '</html>\n' for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, name) self.assertEqual(f.content, content) self.assertEqual(msg.content, c) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="iso-8859-1" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting X-Roundup-Issue-Files: unnamed Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: umlaut =E4=F6=FC=C4=D6=DC=DF File 'unnamed' not attached - you can download it from http://tracker.examp= le/cgi-bin/roundup.cgi/bugs/file1. ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testMultipartCharsetUTF8AttachFile(self): c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f' self.doNewIssue() self._handle_mail(self.multipart_msg_latin1) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 1) name = 'unnamed' content = '<html>' + c + '</html>\n' for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, name) self.assertEqual(f.content, content) self.assertEqual(msg.content, c) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: multipart/mixed; boundary="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting X-Roundup-Issue-Files: unnamed Content-Transfer-Encoding: quoted-printable --utf-8 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: umlaut =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ --utf-8 Content-Type: text/html MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="unnamed" PGh0bWw+dW1sYXV0IMOkw7bDvMOEw5bDnMOfPC9odG1sPgo= --utf-8-- ''') def testMultipartCharsetLatin1AttachFile(self): c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f' self.doNewIssue() self.db.config.MAIL_CHARSET = 'iso-8859-1' self._handle_mail(self.multipart_msg_latin1) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 1) name = 'unnamed' content = '<html>' + c + '</html>\n' for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, name) self.assertEqual(f.content, content) self.assertEqual(msg.content, c) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: multipart/mixed; boundary="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting X-Roundup-Issue-Files: unnamed Content-Transfer-Encoding: quoted-printable --utf-8 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: umlaut =E4=F6=FC=C4=D6=DC=DF ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ --utf-8 Content-Type: text/html MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="unnamed" PGh0bWw+dW1sYXV0IMOkw7bDvMOEw5bDnMOfPC9odG1sPgo= --utf-8-- ''') def testMultipartRFC822(self): self.doNewIssue() self._handle_mail(self.multipart_msg_rfc822) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 1) name = "Fwd: Original email subject.eml" for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, name) self.assertEqual(msg.content, 'First part: Text') self.compareMessages(self._get_mail(), '''TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting X-Roundup-Issue-Files: Fwd: Original email subject.eml Content-Transfer-Encoding: quoted-printable --utf-8 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: First part: Text ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ --utf-8 Content-Type: message/rfc822 MIME-Version: 1.0 Content-Disposition: attachment; filename="Fwd: Original email subject.eml" Message-Id: <followup_dummy_id_2> In-Reply-To: <dummy_test_message_id_2> MIME-Version: 1.0 Subject: Fwd: Original email subject Date: Mon, 23 Aug 2010 08:23:33 +0200 Content-Type: multipart/alternative; boundary="090500050101020406060002" This is a multi-part message in MIME format. --090500050101020406060002 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit some text in inner email ======================== --090500050101020406060002 Content-Type: text/html; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit <html> some text in inner email ======================== </html> --090500050101020406060002-- --utf-8-- ''') def testMultipartRFC822Unpack(self): self.doNewIssue() self.db.config.MAILGW_UNPACK_RFC822 = True self._handle_mail(self.multipart_msg_rfc822) messages = self.db.issue.get('1', 'messages') messages.sort() msg = self.db.msg.getnode (messages[-1]) self.assertEqual(len(msg.files), 2) t = 'some text in inner email\n========================\n' content = {0 : t, 1 : '<html>\n' + t + '</html>\n'} for n, id in enumerate (msg.files): f = self.db.file.getnode (id) self.assertEqual(f.name, 'unnamed') if n in content : self.assertEqual(f.content, content [n]) self.assertEqual(msg.content, 'First part: Text') def testSimpleFollowup(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... This is a second followup ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: This is a second followup ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowup(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... [assignedto=mary; nosy=+john] This is a followup ''') l = self.db.issue.get('1', 'nosy') l.sort() self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id, self.john_id]) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, mary@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, john@test.test, mary@test.test From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- assignedto: -> mary nosy: +john, mary status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNoSubjectChange(self): self.db.config.MAILGW_SUBJECT_UPDATES_TITLE = 'no' self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Wrzlbrmft... [assignedto=mary; nosy=+john] This is a followup ''') l = self.db.issue.get('1', 'nosy') l.sort() self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id, self.john_id]) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, mary@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, john@test.test, mary@test.test From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- assignedto: -> mary nosy: +john, mary status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') self.assertEqual(self.db.issue.get('1','title'), 'Testing...') def testFollowupExplicitSubjectChange(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Wrzlbrmft... [assignedto=mary; nosy=+john; title=new title] This is a followup ''') l = self.db.issue.get('1', 'nosy') l.sort() self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id, self.john_id]) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, mary@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] new title To: chef@bork.bork.bork, john@test.test, mary@test.test From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- assignedto: -> mary nosy: +john, mary status: unread -> chatting title: Testing... -> new title _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testNosyGeneration(self): self.db.issue.create(title='test') # create a nosy message msg = self.db.msg.create(content='This is a test', author=self.richard_id, messageid='<dummy_test_message_id>') self.db.journaltag = 'richard' l = self.db.issue.create(title='test', messages=[msg], nosy=[self.chef_id, self.mary_id, self.john_id]) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, mary@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue2] test To: chef@bork.bork.bork, john@test.test, mary@test.test From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: unread Content-Transfer-Encoding: quoted-printable New submission from richard <richard@test.test>: This is a test ---------- messages: 1 nosy: Chef, john, mary, richard status: unread title: test _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue2> _______________________________________________________________________ ''') def testPropertyChangeOnly(self): self.doNewIssue() oldvalues = self.db.getnode('issue', '1').copy() oldvalues['assignedto'] = None # reconstruct old behaviour: This would reuse the # database-handle from the doNewIssue above which has committed # as user "Chef". So we close and reopen the db as that user. #self.db.close() actually don't close 'cos this empties memorydb self.db = self.instance.open('Chef') self.db.issue.set('1', assignedto=self.chef_id) self.db.commit() self.db.issue.nosymessage('1', None, oldvalues) new_mail = "" for line in self._get_mail().split("\n"): if "Message-Id: " in line: continue if "Date: " in line: continue new_mail += line+"\n" self.compareMessages(new_mail, """ FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: unread X-Roundup-Version: 1.3.3 In-Reply-To: <dummy_test_message_id> MIME-Version: 1.0 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> Content-Transfer-Encoding: quoted-printable Change by Bork, Chef <chef@bork.bork.bork>: ---------- assignedto: -> Chef _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ """) # # FOLLOWUP TITLE MATCH # def testFollowupTitleMatch(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> Subject: Re: Testing... [assignedto=mary; nosy=+john] This is a followup ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, mary@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, john@test.test, mary@test.test From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- assignedto: -> mary nosy: +john, mary status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupTitleMatchMultiRe(self): nodeid1 = self.doNewIssue() nodeid2 = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> Subject: Re: Testing... [assignedto=mary; nosy=+john] This is a followup ''') nodeid3 = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup2_dummy_id> Subject: Ang: Re: Testing... This is a followup ''') self.assertEqual(nodeid1, nodeid2) self.assertEqual(nodeid1, nodeid3) def testFollowupTitleMatchNever(self): nodeid = self.doNewIssue() self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never' self.assertNotEqual(self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> Subject: Re: Testing... This is a followup '''), nodeid) def testFollowupTitleMatchNeverInterval(self): nodeid = self.doNewIssue() # force failure of the interval time.sleep(2) self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01' self.assertNotEqual(self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> Subject: Re: Testing... This is a followup '''), nodeid) def testFollowupTitleMatchInterval(self): nodeid = self.doNewIssue() self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d' self.assertEqual(self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> Subject: Re: Testing... This is a followup '''), nodeid) simple_followup = '''Content-Type: text/plain; charset="iso-8859-1" From: john@test.test To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... This is a followup ''' def testFollowupNosyAuthor(self): self.doNewIssue() self.db.config.ADD_AUTHOR_TO_NOSY = 'yes' self._handle_mail(self.simple_followup) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: John Doe <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable John Doe <john@test.test> added the comment: This is a followup ---------- nosy: +john status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNosyRecipients(self): self.doNewIssue() self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes' self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard@test.test To: issue_tracker@your.tracker.email.domain.example Cc: john@test.test Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... This is a followup ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- nosy: +john status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNosyAuthorAndCopy(self): self.doNewIssue() self.db.config.ADD_AUTHOR_TO_NOSY = 'yes' self.db.config.MESSAGES_TO_AUTHOR = 'yes' self._handle_mail(self.simple_followup) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, john@test.test, richard@test.test From: John Doe <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable John Doe <john@test.test> added the comment: This is a followup ---------- nosy: +john status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNosyAuthorNosyCopy(self): self.doNewIssue() self.db.config.ADD_AUTHOR_TO_NOSY = 'yes' self.db.config.MESSAGES_TO_AUTHOR = 'nosy' self._handle_mail(self.simple_followup) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, john@test.test, richard@test.test From: John Doe <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable John Doe <john@test.test> added the comment: This is a followup ---------- nosy: +john status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNoNosyAuthor(self): self.doNewIssue() self.instance.config.ADD_AUTHOR_TO_NOSY = 'no' self._handle_mail(self.simple_followup) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: John Doe <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable John Doe <john@test.test> added the comment: This is a followup ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNoNosyAuthorNoCopy(self): self.doNewIssue() self.instance.config.ADD_AUTHOR_TO_NOSY = 'no' self.instance.config.MESSAGES_TO_AUTHOR = 'nosy' self._handle_mail(self.simple_followup) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: John Doe <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable John Doe <john@test.test> added the comment: This is a followup ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') # this is a pathological case where the author is *not* on the nosy # list but gets the message; test documents existing behaviour def testFollowupNoNosyAuthorButCopy(self): self.doNewIssue() self.instance.config.ADD_AUTHOR_TO_NOSY = 'no' self.instance.config.MESSAGES_TO_AUTHOR = 'yes' self._handle_mail(self.simple_followup) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, john@test.test, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, john@test.test, richard@test.test From: John Doe <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable John Doe <john@test.test> added the comment: This is a followup ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupNoNosyRecipients(self): self.doNewIssue() self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no' self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard@test.test To: issue_tracker@your.tracker.email.domain.example Cc: john@test.test Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... This is a followup ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testFollowupEmptyMessage(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... [assignedto=mary; nosy=+john] ''') l = self.db.issue.get('1', 'nosy') l.sort() self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id, self.john_id]) # should be no file created (ie. no message) assert not os.path.exists(SENDMAILDEBUG) def testFollowupEmptyMessageNoSubject(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] [assignedto=mary; nosy=+john] ''') l = self.db.issue.get('1', 'nosy') l.sort() self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id, self.john_id]) # should be no file created (ie. no message) assert not os.path.exists(SENDMAILDEBUG) def testNosyRemove(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... [nosy=-richard] ''') l = self.db.issue.get('1', 'nosy') l.sort() self.assertEqual(l, [self.chef_id]) # NO NOSY MESSAGE SHOULD BE SENT! assert not os.path.exists(SENDMAILDEBUG) def testNewUserAuthor(self): self.db.commit() l = self.db.user.list() l.sort() message = '''Content-Type: text/plain; charset="iso-8859-1" From: fubar <fubar@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing... This is a test submission of a new issue. ''' self.db.security.role['anonymous'].permissions=[] anonid = self.db.user.lookup('anonymous') self.db.user.set(anonid, roles='Anonymous') try: self._handle_mail(message) except Unauthorized, value: body_diff = self.compareMessages(str(value), """ You are not a registered user. Unknown address: fubar@bork.bork.bork """) assert not body_diff, body_diff else: raise AssertionError, "Unathorized not raised when handling mail" # Add Web Access role to anonymous, and try again to make sure # we get a "please register at:" message this time. p = [ self.db.security.getPermission('Register', 'user'), self.db.security.getPermission('Web Access', None), ] self.db.security.role['anonymous'].permissions=p try: self._handle_mail(message) except Unauthorized, value: body_diff = self.compareMessages(str(value), """ You are not a registered user. Please register at: http://tracker.example/cgi-bin/roundup.cgi/bugs/user?@template=register ...before sending mail to the tracker. Unknown address: fubar@bork.bork.bork """) assert not body_diff, body_diff else: raise AssertionError, "Unauthorized not raised when handling mail" # Make sure list of users is the same as before. m = self.db.user.list() m.sort() self.assertEqual(l, m) # now with the permission p = [ self.db.security.getPermission('Register', 'user'), self.db.security.getPermission('Email Access', None), ] self.db.security.role['anonymous'].permissions=p self._handle_mail(message) m = self.db.user.list() m.sort() self.assertNotEqual(l, m) def testNewUserAuthorEncodedName(self): l = set(self.db.user.list()) # From: name has Euro symbol in it message = '''Content-Type: text/plain; charset="iso-8859-1" From: =?utf8?b?SOKCrGxsbw==?= <fubar@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing... This is a test submission of a new issue. ''' self._allowAnonymousSubmit() self._handle_mail(message) m = set(self.db.user.list()) new = list(m - l)[0] name = self.db.user.get(new, 'realname') self.assertEquals(name, 'H€llo') def testNewUserAuthorMixedEncodedName(self): l = set(self.db.user.list()) # From: name has Euro symbol in it message = '''Content-Type: text/plain; charset="iso-8859-1" From: Firstname =?utf-8?b?w6TDtsOf?= Last <fubar@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Test =?utf-8?b?w4TDlsOc?= umlauts X1 X2 This is a test submission of a new issue. ''' self._allowAnonymousSubmit() self._handle_mail(message) title = self.db.issue.get('1', 'title') self.assertEquals(title, 'Test \xc3\x84\xc3\x96\xc3\x9c umlauts X1 X2') m = set(self.db.user.list()) new = list(m - l)[0] name = self.db.user.get(new, 'realname') self.assertEquals(name, 'Firstname \xc3\xa4\xc3\xb6\xc3\x9f Last') def testNewUserAuthorMixedEncodedNameSpacing(self): l = set(self.db.user.list()) # From: name has Euro symbol in it message = '''Content-Type: text/plain; charset="iso-8859-1" From: (=?utf-8?b?w6TDtsOf?==?utf-8?b?w6TDtsOf?=) <fubar@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Test (=?utf-8?b?w4TDlsOc?=) umlauts X1 This is a test submission of a new issue. ''' self._allowAnonymousSubmit() self._handle_mail(message) title = self.db.issue.get('1', 'title') self.assertEquals(title, 'Test (\xc3\x84\xc3\x96\xc3\x9c) umlauts X1') m = set(self.db.user.list()) new = list(m - l)[0] name = self.db.user.get(new, 'realname') self.assertEquals(name, '(\xc3\xa4\xc3\xb6\xc3\x9f\xc3\xa4\xc3\xb6\xc3\x9f)') def testUnknownUser(self): l = set(self.db.user.list()) message = '''Content-Type: text/plain; charset="iso-8859-1" From: Nonexisting User <nonexisting@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing nonexisting user... This is a test submission of a new issue. ''' # trap_exc=1: we want a bounce message: ret = self._handle_mail(message, trap_exc=1) self.compareMessages(self._get_mail(), '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example> TO: nonexisting@bork.bork.bork From nobody Tue Jul 14 12:04:11 2009 Content-Type: multipart/mixed; boundary="===============0639262320==" MIME-Version: 1.0 Subject: Failed issue tracker submission To: nonexisting@bork.bork.bork From: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example> Date: Tue, 14 Jul 2009 12:04:11 +0000 Precedence: bulk X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Version: 1.4.8 MIME-Version: 1.0 --===============0639262320== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit You are not a registered user. Please register at: http://tracker.example/cgi-bin/roundup.cgi/bugs/user?@template=register ...before sending mail to the tracker. Unknown address: nonexisting@bork.bork.bork --===============0639262320== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="iso-8859-1" From: Nonexisting User <nonexisting@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing nonexisting user... This is a test submission of a new issue. --===============0639262320==-- ''') def testEnc01(self): self.db.user.set(self.mary_id, realname='\xe4\xf6\xfc\xc4\xd6\xdc\xdf, Mary'.decode ('latin-1').encode('utf-8')) self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable A message with encoding (encoded oe =F6) ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: =?utf-8?b?w6TDtsO8w4TDlsOcw58sIE1hcnk=?= <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F, Mary <mary@test.test> added the= comment: A message with encoding (encoded oe =C3=B6) ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testEncNonUTF8(self): self.doNewIssue() self.instance.config.EMAIL_CHARSET = 'iso-8859-1' self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable A message with encoding (encoded oe =F6) ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="iso-8859-1" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: A message with encoding (encoded oe =F6) ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testMultipartEnc01(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01" This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable A message with first part encoded (encoded oe =F6) ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork, richard@test.test From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable Contrary, Mary <mary@test.test> added the comment: A message with first part encoded (encoded oe =C3=B6) ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testContentDisposition(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [issue1] Testing... Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" Content-Disposition: inline --bCsyhTFzCvuiizWE Content-Type: text/plain; charset=us-ascii Content-Disposition: inline test attachment binary --bCsyhTFzCvuiizWE Content-Type: application/octet-stream Content-Disposition: attachment; filename="main.dvi" Content-Transfer-Encoding: base64 SnVzdCBhIHRlc3QgAQo= --bCsyhTFzCvuiizWE-- ''') messages = self.db.issue.get('1', 'messages') messages.sort() file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0]) self.assertEqual(file.name, 'main.dvi') self.assertEqual(file.content, 'Just a test \001\n') def testFollowupStupidQuoting(self): self.doNewIssue() self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: Re: "[issue1] Testing... " This is a followup ''') self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: chef@bork.bork.bork From: richard <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable richard <richard@test.test> added the comment: This is a followup ---------- status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') firstquotingtest = '''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: Re: [issue1] Testing... Blah blah wrote: > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj > This is a followup ''' def testEmailQuoting(self): self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no' self.innerTestQuoting(self.firstquotingtest, '''This is a followup ''', 'This is a followup') def testEmailQuotingRemove(self): self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes' self.innerTestQuoting(self.firstquotingtest, '''Blah blah wrote: > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj > This is a followup ''', 'This is a followup') secondquotingtest = '''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: Re: [issue1] Testing... On Tue, Feb 23, 2010 at 8:46 AM, Someone <report@bugs.python.org> wrote: > aa > aa AA: AA AA AA TEXT BEFORE QUOTE > bb > bb > BB BB BB BB > cc > > cc > > > cc > > cc > > cc > CC -- added signature ''' def testEmailQuoting2(self): self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no' self.innerTestQuoting(self.secondquotingtest, '''AA: AA AA AA TEXT BEFORE QUOTE BB BB BB BB CC ''', 'AA:') def testEmailQuotingRemove2(self): self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes' self.innerTestQuoting(self.secondquotingtest, '\n'.join(self.secondquotingtest.split('\n')[8:-3]), 'AA:') thirdquotingtest = '''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: Re: [issue1] Testing... On Mon, Jan 02, 2012 at 06:14:27PM +0000, Someone wrote: > > aa > > aa > aa > aa AA0 AA > bb > bb > bb BB > cc > cc > cc > cc > cc > cc CC CC CC CC CC CC CC CC CC CC NAME -- sig sig sig sig ''' # This fails because the sig isn't removed (we currently remove the # sig only if the delimiter is the first line in a section) @expectedFailure def testEmailQuotingRemove3(self): self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes' self.innerTestQuoting(self.thirdquotingtest, '\n'.join(self.thirdquotingtest.split('\n')[8:-6]), 'AA0') def innerTestQuoting(self, msgtext, expect, summary=None): nodeid = self.doNewIssue() messages = self.db.issue.get(nodeid, 'messages') self._handle_mail(msgtext) # figure the new message id newmessages = self.db.issue.get(nodeid, 'messages') for msg in messages: newmessages.remove(msg) messageid = newmessages[0] self.compareMessages(self.db.msg.get(messageid, 'content'), expect) if summary: self.assertEqual (summary, self.db.msg.get(messageid, 'summary')) def testUserLookup(self): i = self.db.user.create(username='user1', address='user1@foo.com') self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i) self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i) i = self.db.user.create(username='user2', address='USER2@foo.com') self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i) self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i) def testUserAlternateLookup(self): i = self.db.user.create(username='user1', address='user1@foo.com', alternate_addresses='user1@bar.com') self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i) self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i) def testUserAlternateSubstringNomatch(self): i = self.db.user.create(username='user1', address='user1@foo.com', alternate_addresses='x-user1@bar.com') self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), 0) self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), 0) def testUserCreate(self): i = uidFromAddress(self.db, ('', 'user@foo.com'), 1) self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i) def testRFC2822(self): ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks" unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9' unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?=' self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header) self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded) def testRegistrationConfirmation(self): otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL" self.db.getOTKManager().set(otk, username='johannes') self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: Re: Complete your registration to Roundup issue tracker -- key %s This is a test confirmation of registration. ''' % otk) self.db.user.lookup('johannes') def testFollowupOnNonIssue(self): self.db.keyword.create(name='Foo') self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: [keyword1] Testing... [name=Bar] ''') self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar') def testResentFrom(self): nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> Resent-From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: [issue] Testing... This is a test submission of a new issue. ''') assert not os.path.exists(SENDMAILDEBUG) l = self.db.issue.get(nodeid, 'nosy') l.sort() self.assertEqual(l, [self.richard_id, self.mary_id]) return nodeid def testDejaVu(self): self.assertRaises(IgnoreLoop, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> X-Roundup-Loop: hello To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: Re: [issue] Testing... Hi, I've been mis-configured to loop messages back to myself. ''') def testItsBulkStupid(self): self.assertRaises(IgnoreBulk, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> Precedence: bulk To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: Re: [issue] Testing... Hi, I'm on holidays, and this is a dumb auto-responder. ''') def testAutoReplyEmailsAreIgnored(self): self.assertRaises(IgnoreBulk, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Message-Id: <dummy_test_message_id> Subject: Re: [issue] Out of office AutoReply: Back next week Hi, I am back in the office next week ''') def testNoSubject(self): self.assertRaises(MailUsageError, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') # # TEST FOR INVALID DESIGNATOR HANDLING # def testInvalidDesignator(self): self.assertRaises(MailUsageError, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [frobulated] testing Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') self.assertRaises(MailUsageError, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [issue12345] testing Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') def testInvalidClassLoose(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [frobulated] testing Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), '[frobulated] testing') def testInvalidClassLooseReply(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: Re: [frobulated] testing Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), '[frobulated] testing') def testInvalidClassLoose(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [issue1234] testing Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), '[issue1234] testing') def testClassLooseOK(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose' self.db.keyword.create(name='Foo') nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [keyword1] Testing... [name=Bar] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar') def testClassStrictInvalid(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict' self.instance.config.MAILGW_DEFAULT_CLASS = '' message = '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: Testing... Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''' self.assertRaises(MailUsageError, self._handle_mail, message) def testClassStrictValid(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict' self.instance.config.MAILGW_DEFAULT_CLASS = '' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [issue] Testing... Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...') # # TEST FOR INVALID COMMANDS HANDLING # def testInvalidCommands(self): self.assertRaises(MailUsageError, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: testing [frobulated] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') def testInvalidCommandPassthrough(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: testing [frobulated] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing [frobulated]') def testInvalidCommandPassthroughLoose(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: testing [frobulated] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing [frobulated]') def testInvalidCommandPassthroughLooseOK(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: testing [assignedto=mary] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing') self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id) def testCommandDelimiters(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: testing {assignedto=mary} Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing') self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id) def testPrefixDelimiters(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}' self.db.keyword.create(name='Foo') self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: richard <richard@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: {keyword1} Testing... {name=Bar} ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar') def testCommandDelimitersIgnore(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}' nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: testing [assignedto=mary] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing [assignedto=mary]') self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None) def testReplytoMatch(self): self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose' nodeid = self.doNewIssue() nodeid2 = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id2> In-Reply-To: <dummy_test_message_id> Subject: Testing... Followup message. ''') nodeid3 = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id3> In-Reply-To: <dummy_test_message_id2> Subject: Testing... Yet another message in the same thread/issue. ''') self.assertEqual(nodeid, nodeid2) self.assertEqual(nodeid, nodeid3) def testHelpSubject(self): message = '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id2> In-Reply-To: <dummy_test_message_id> Subject: hElp ''' self.assertRaises(MailUsageHelp, self._handle_mail, message) def testMaillistSubject(self): self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]' self.db.keyword.create(name='Foo') self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar') def testUnknownPrefixSubject(self): self.db.keyword.create(name='Foo') self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar] Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''') assert not os.path.exists(SENDMAILDEBUG) self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar') def testOneCharSubject(self): message = '''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Subject: b Cc: richard@test.test Reply-To: chef@bork.bork.bork Message-Id: <dummy_test_message_id> ''' try: self._handle_mail(message) except MailUsageError: self.fail('MailUsageError raised') def testIssueidLast(self): nodeid1 = self.doNewIssue() nodeid2 = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: mary <mary@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <followup_dummy_id> In-Reply-To: <dummy_test_message_id> Subject: New title [issue1] This is a second followup ''') assert nodeid1 == nodeid2 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...") def testSecurityMessagePermissionContent(self): id = self.doNewIssue() issue = self.db.issue.getnode (id) self.db.security.addRole(name='Nomsg') self.db.security.addPermissionToRole('Nomsg', 'Email Access') for cl in 'issue', 'file', 'keyword': for p in 'View', 'Edit', 'Create': self.db.security.addPermissionToRole('Nomsg', p, cl) self.db.user.set(self.mary_id, roles='Nomsg') nodeid = self._handle_mail('''Content-Type: text/plain; charset="iso-8859-1" From: Chef <chef@bork.bork.bork> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id_2> Subject: [issue%(id)s] Testing... [nosy=+mary] Just a test reply '''%locals()) assert os.path.exists(SENDMAILDEBUG) self.compareMessages(self._get_mail(), '''FROM: roundup-admin@your.tracker.email.domain.example TO: chef@bork.bork.bork, richard@test.test Content-Type: text/plain; charset="utf-8" Subject: [issue1] Testing... To: richard@test.test From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example> Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> MIME-Version: 1.0 Message-Id: <dummy_test_message_id_2> In-Reply-To: <dummy_test_message_id> X-Roundup-Name: Roundup issue tracker X-Roundup-Loop: hello X-Roundup-Issue-Status: chatting Content-Transfer-Encoding: quoted-printable Bork, Chef <chef@bork.bork.bork> added the comment: Just a test reply ---------- nosy: +mary status: unread -> chatting _______________________________________________________________________ Roundup issue tracker <issue_tracker@your.tracker.email.domain.example> <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1> _______________________________________________________________________ ''') def testOutlookAttachment(self): message = '''X-MimeOLE: Produced By Microsoft Exchange V6.5 Content-class: urn:content-classes:message MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----_=_NextPart_001_01CACA65.40A51CBC" Subject: Example of a failed outlook attachment e-mail Date: Tue, 23 Mar 2010 01:43:44 -0700 Message-ID: <CA37F17219784343816CA6613D2E339205E7D0F9@nrcwstexb1.nrc.ca> X-MS-Has-Attach: yes X-MS-TNEF-Correlator: Thread-Topic: Example of a failed outlook attachment e-mail Thread-Index: AcrKJo/t3pUBBwTpSwWNE3LE67UBDQ== From: "Hugh" <richard@test.test> To: <richard@test.test> X-OriginalArrivalTime: 23 Mar 2010 08:45:57.0350 (UTC) FILETIME=[41893860:01CACA65] This is a multi-part message in MIME format. ------_=_NextPart_001_01CACA65.40A51CBC Content-Type: multipart/alternative; boundary="----_=_NextPart_002_01CACA65.40A51CBC" ------_=_NextPart_002_01CACA65.40A51CBC Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Richard, I suppose this isn't the exact message that was sent but is a resend of one of my trial messages that failed. For your benefit I changed the subject line and am adding these words to the message body. Should still be as problematic, but if you like I can resend an exact copy of a failed message changing nothing except putting your address instead of our tracker. Thanks very much for taking time to look into this. Much appreciated. <<battery backup>>=20 ------_=_NextPart_002_01CACA65.40A51CBC Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; = charset=3Dus-ascii"> <META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version = 6.5.7654.12"> <TITLE>Example of a failed outlook attachment e-mail</TITLE> </HEAD> <BODY> <!-- Converted from text/rtf format --> <BR> <P><FONT SIZE=3D2 FACE=3D"Arial">Hi Richard,</FONT> </P> <P><FONT SIZE=3D2 FACE=3D"Arial">I suppose this isn't the exact message = that was sent but is a resend of one of my trial messages that = failed. For your benefit I changed the subject line and am adding = these words to the message body. Should still be as problematic, = but if you like I can resend an exact copy of a failed message changing = nothing except putting your address instead of our tracker.</FONT></P> <P><FONT SIZE=3D2 FACE=3D"Arial">Thanks very much for taking time to = look into this. Much appreciated.</FONT> </P> <BR> <P><FONT FACE=3D"Arial" SIZE=3D2 COLOR=3D"#000000"> <<battery = backup>> </FONT> </P> </BODY> </HTML> ------_=_NextPart_002_01CACA65.40A51CBC-- ------_=_NextPart_001_01CACA65.40A51CBC Content-Type: message/rfc822 Content-Transfer-Encoding: 7bit X-MimeOLE: Produced By Microsoft Exchange V6.5 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----_=_NextPart_003_01CAC15A.29717800" X-OriginalArrivalTime: 11 Mar 2010 20:33:51.0249 (UTC) FILETIME=[28FEE010:01CAC15A] Content-class: urn:content-classes:message Subject: battery backup Date: Thu, 11 Mar 2010 13:33:43 -0700 Message-ID: <p06240809c7bf02f9624c@[128.114.22.203]> X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: battery backup Thread-Index: AcrBWimtulTrSvBdQ2CcfZ8lyQdxmQ== From: "Jerry" <jerry@test.test> To: "Hugh" <hugh@test.test> This is a multi-part message in MIME format. ------_=_NextPart_003_01CAC15A.29717800 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Dear Hugh, A car batter has an energy capacity of ~ 500Wh. A UPS=20 battery is worse than this. if we need to provied 100kW for 30 minutes that will take 100 car=20 batteries. This seems like an awful lot of batteries. Of course I like your idea of making the time 1 minute, so we get to=20 a more modest number of batteries Jerry ------_=_NextPart_003_01CAC15A.29717800 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; = charset=3Diso-8859-1"> <META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version = 6.5.7654.12"> <TITLE>battery backup</TITLE> </HEAD> <BODY> <!-- Converted from text/plain format --> <P><FONT SIZE=3D2>Dear Hugh,</FONT> <BR> <FONT SIZE=3D2>A car = batter has an energy capacity of ~ 500Wh. A UPS </FONT> <BR><FONT SIZE=3D2>battery is worse than this.</FONT> </P> <P><FONT SIZE=3D2>if we need to provied 100kW for 30 minutes that will = take 100 car </FONT> <BR><FONT SIZE=3D2>batteries. This seems like an awful lot of = batteries.</FONT> </P> <P><FONT SIZE=3D2>Of course I like your idea of making the time 1 = minute, so we get to </FONT> <BR><FONT SIZE=3D2>a more modest number of batteries</FONT> </P> <P><FONT SIZE=3D2>Jerry</FONT> </P> </BODY> </HTML> ------_=_NextPart_003_01CAC15A.29717800-- ------_=_NextPart_001_01CACA65.40A51CBC-- ''' nodeid = self._handle_mail(message) assert not os.path.exists(SENDMAILDEBUG) msgid = self.db.issue.get(nodeid, 'messages')[0] self.assert_(self.db.msg.get(msgid, 'content').startswith('Hi Richard')) self.assertEqual(self.db.msg.get(msgid, 'files'), ['1', '2']) fileid = self.db.msg.get(msgid, 'files')[0] self.assertEqual(self.db.file.get(fileid, 'type'), 'text/html') fileid = self.db.msg.get(msgid, 'files')[1] self.assertEqual(self.db.file.get(fileid, 'type'), 'message/rfc822') def testForwardedMessageAttachment(self): message = '''Return-Path: <rgg@test.test> Received: from localhost(127.0.0.1), claiming to be "[115.130.26.69]" via SMTP by localhost, id smtpdAAApLaWrq; Tue Apr 13 23:10:05 2010 Message-ID: <4BC4F9C7.50409@test.test> Date: Wed, 14 Apr 2010 09:09:59 +1000 From: Rupert Goldie <rgg@test.test> User-Agent: Thunderbird 2.0.0.24 (Windows/20100228) MIME-Version: 1.0 To: ekit issues <issues@test.test> Subject: [Fwd: PHP ERROR (fb)] post limit reached Content-Type: multipart/mixed; boundary="------------000807090608060304010403" This is a multi-part message in MIME format. --------------000807090608060304010403 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Catch this exception and log it without emailing. --------------000807090608060304010403 Content-Type: message/rfc822; name="PHP ERROR (fb).eml" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="PHP ERROR (fb).eml" Return-Path: <ektravj@test.test> X-Sieve: CMU Sieve 2.2 via SMTP by crown.off.ekorp.com, id smtpdAAA1JaW1o; Tue Apr 13 23:01:04 2010 X-Virus-Scanned: by amavisd-new at ekit.com To: facebook-errors@test.test From: ektravj@test.test Subject: PHP ERROR (fb) Message-Id: <20100413230100.D601D27E84@mail2.elax3.ekorp.com> Date: Tue, 13 Apr 2010 23:01:00 +0000 (UTC) [13-Apr-2010 22:49:02] PHP Fatal error: Uncaught exception 'Exception' with message 'Facebook Error Message: Feed action request limit reached' in /app/01/www/virtual/fb.ekit.com/htdocs/includes/functions.php:280 Stack trace: #0 /app/01/www/virtual/fb.ekit.com/htdocs/gateway/ekit/feed/index.php(178): fb_exceptions(Object(FacebookRestClientException)) #1 {main} thrown in /app/01/www/virtual/fb.ekit.com/htdocs/includes/functions.php on line 280 --------------000807090608060304010403-- ''' nodeid = self._handle_mail(message) assert not os.path.exists(SENDMAILDEBUG) msgid = self.db.issue.get(nodeid, 'messages')[0] self.assertEqual(self.db.msg.get(msgid, 'content'), 'Catch this exception and log it without emailing.') self.assertEqual(self.db.msg.get(msgid, 'files'), ['1']) fileid = self.db.msg.get(msgid, 'files')[0] self.assertEqual(self.db.file.get(fileid, 'type'), 'message/rfc822') pgp_test_key = """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) lQOYBE6NqtsBCADG3UUMYxjwUOpDDVvr0Y8qkvKsgdF79en1zfHtRYlmZc+EJxg8 53CCFGReQWJwOjyP3/SLJwJqfiPR7MAYAqJsm/4U2lxF7sIlEnlrRpFuvB625KOQ oedCkI4nLa+4QAXHxVX2qLx7es3r2JAoitZLX7ZtUB7qGSRh98DmdAgCY3CFN7iZ w6xpvIU+LNbsHSo1sf8VP6z7NHQFacgrVvLyRJ4C5lTPU42iM5E6HKxYFExNV3Rn +2G0bsuiifHV6nJQD73onjwcC6tU97W779dllHlhG3SSP0KlnwmCCvPMlQvROk0A rLyzKWcUpZwK1aLRYByjFMH9WYXRkhf08bkDABEBAAEAB/9dcmSb6YUyiBNM5t4m 9hZcXykBvw79PRVvmBLy+BYUtArLgsN0+xx3Q7XWRMtJCVSkFw0GxpHwEM4sOyAZ KEPC3ZqLmgB6LDO2z/OWYVa9vlCAiPgDYtEVCnCCIInN/ue4dBZtDeVj8NUK2n0D UBpa2OMUgu3D+4SJNK7EnAmXdOaP6yfe6SXwcQfti8UoSFMJRkQkbY1rm/6iPfON t2RBAc7jW4eRzdciWCfvJfMSj9cqxTBQWz5vVadeY9Bm/IKw1HiKNBrJratq2v+D VGr0EkE9oOa5zbgZt2CFvknE4YhGmv81xFdK5GXr8L7nluZrePMblWbkI2ICTbV0 RKLhBADYLvyDFX3cCoFzWmCl5L32G6LLfTt0yU0eUHcAzXd7QjOZN289HWYEmdVi kpxQPDxhWz+m8qt0HJGFl2+BKpZJBaT/L5AcqTBODxarxCSBTIVhCjD/46XvLY0h b2ZnG8HSLyFdRj07vk+qTvcF58qUuYFSLIF2t2imTCR/PwR/LwQA632vn2/7KIHj DR0O+G9eccTtAfX4TN4Q4Ua3WByClLZu/LSAenCLZ1CHVABEH6dwwjEARLeNUdLi Xy5KKlpr2vkoh96fnw0r2yg7dlBXq4yQKjJBXwNaKpuvqgzd8en0zJGLXxzt0NT3 H+QNIP2WZMJSDQcDh3HhQrH0IeNdDm0D/iyJgSMXvqjm+KhYIa3xiloQsCRlDNm+ XC7Eo5hsjvBaIKba6o9oL9oEiSVUFryPWKWIpi0P7/F5voJL6KFSZTor3x3o9CcC qHyqMHfNL23EAVJulySfPYLC7S3QB+tCBLXmKxb/YXCSLVi/UDzVgvWN6KIknZg2 6uDLUzPbzDGjOZ20K1JvdW5kdXAgVGVzdGtleSA8cm91bmR1cC1hZG1pbkBleGFt cGxlLmNvbT6JATgEEwECACIFAk6NqtsCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B AheAAAoJEFrc/VYxw4dBG7oIAMCU9sRjK0dS7z/IGJ8KcCOQNN674AooJLn+J9Ew BT6/WxMY13nm/iK0uX2sOGnnXdg1PJ15IvD8zB5wXLbe25t6oRl5G58vmeKEyjc8 QTB43/c8EsqY1ob7EVcuhrJCSS/JM8ApzQyXrh2QNmS+mBCJcx74MeipE6mNVT9j VscizixdFjqvJLkbW1kGac3Wj+c3ICNUIp0lbwb+Ve2rXlU+iXHEDqaVJDMEppme gDiZl+bKYrqljhZkH9Slv55uqqXUSg1SmTm/2orHUdAmDc6Y6azKNqQEqD2B0JyT jTJQJVMl5Oln63aZDCTxHkoqn8q06OjLJRD4on7jlanZEladA5gETo2q2wEIALEF poVkZrnqme2M8FObrQyVB+ZYT2mox56WLyInbxVFDg20qqIvQfVE0P69Yuf1OXkj q7bNI03Jvo+uzxpztOKPDo7tnbQ7bXbOmq3n4wUoN29NMrYNg6tF1ubEv1WwYUMw 7LfF4BLMETXpT0JElV1+awfP9rrGiyWkH4enG612HT+1OoA0R0nNH0kslD6OhdoR VDqkyiCmdY9x176EhzhL3vCoN6ywRVTfFbAJiMv9UDzxs0SStmVOK/l5XLfWQO6f 9boAHihpnxEfPIJhsD+FpVKVf3g85qWAjh2BfuzdW79vjLBdTHJQxg4HdhliWbXg PjjrVEgWEFVc+NDlNb0AEQEAAQAH/A1a6sbniI8q3DVoIP19zN7FI5UaQSuB2Jrl +Q+vlUQv3dvk2cwQmqj2vyRo2gcRS3u7LYpGDGLNqfshv22JyzId2YWo9vE7sTTP E4EJRz8CsLlMmVsoxoVBE0cnvXOpMef6z0ZyFEdMGVmi4iA9bQi3r+V6qBehQQA0 U034VTCPN4yvWyq6TWsABesOx48nkQ5TlduIq2ZGNCR8Vd1fe6vGM7YXyQWxy5ke guqmph73H2bOB6hSuUnyBFKtinrF9MbCGA0PqheUVqy0p7og6x/pEoAVkKBJ9Ki+ ePuQtBl5h9e3SbiN+r7aa6T0Ygx/7igl4eWPfvJYIXYXc4aKiwEEANEa5rBoN7Ta ED+R47Rg9w/EW3VDQ6R3Szy1rvIKjC6JlDyKlGgTeWEFjDeTwCB4xU7YtxVpt6bk b7RBtDkRck2+DwnscutA7Uxn267UxzNUd1IxhUccRFRfRS7OEnmlVmaLUnOeHHwe OrZyRSiNVnh0QABEJnwNjX4m139v6YD9BADYuM5XCawI63pYa3/l7UX9H5EH95OZ G9Hw7pXQ/YJYerSxRx+2q0+koRcdoby1TVaRrdDC+kOm3PI7e66S5rnaZ1FZeYQP nVYzyGqNnsvncs24kYBL8DYaDDfdm7vfzSEqia0VNqZ4TMbwJLk5f5Ys4WOF791G LPJgrAPG1jgDwQQAovKbw0u6blIUKsUYOLsviaLCyFC9DwaHqIZwjy8omnh7MaKE 7+MXxJpfcVqFifj3CmqMdSmTfkgbKQPAI46Q1OKWvkvUxEvi7WATo4taEXupRFL5 jnL8c4h46z8UpMX2CMwWU0k1Et/zlBoYy7gNON7tF2/uuN18zWFBlD72HuM9HIkB HwQYAQIACQUCTo2q2wIbDAAKCRBa3P1WMcOHQYI+CACDXJf1e695LpcsrVxKgiQr 9fTbNJYB+tjbnd9vas92Gz1wZcQV9RjLkYQeEbOpWQud/1UeLRsFECMj7kbgAEqz 7fIO4SeN8hFEvvZ+lI0AoBi4XvuUcCm5kvAodvmF8M9kQiUzF1gm+R9QQeJFDLpW 8Gg7J3V3qM+N0FuXrypYcsEv7n/RJ1n+lhTW5hFzKBlNL4WrAhY/QsXEbmdsa478 tzuHlETtjMm4g4DgppUdlCMegcpjjC9zKsN5xFOQmNMTO/6rPFUqk3k3T6I0LV4O zm4xNC+wwAA69ibnbrY1NR019et7RYW+qBudGbpJB1ABzkf/NsaCj6aTaubt7PZP =3uFZ -----END PGP PRIVATE KEY BLOCK----- """ john_doe_key = """ -----BEGIN PGP PRIVATE KEY BLOCK----- Version: GnuPG v1.4.10 (GNU/Linux) lQHYBE6NwvABBACxg7QqV2qHywwM3wae6HAHJVEo7EeYA6Lv0pZlW3Aw4CCCnpgJ jA7CekGFcmGmoCaN9ezuVAPTgUlK4yt8a7P6cT0vw1q341Om9IEKAu59RpNZN/H9 6GfZ95bU51W/hdTFysH1DRwbCR3MowvLeA6Pk4cZlPsYHD0SD3De2i1BewARAQAB AAP+IRi4L6jKwPS3k3LFrj0SHhL0Fdgv5QTQjTxLNCyfN02iYhglqqoFWncm3jWc RU/YwGEYwrrBV97kBmVihzkhfgFRsxynE9PMGKKEAuRcAl21RPJDFA6Dlnp6M2No rR6eoAhrlZ8+KsK9JaXSMalzO/Yh4u3mOinq3f3XL96wAEkCAMAxeZMF5pnXARNR Y7u2clhNNnLuf+BzpENCFMaWzWPyTcvbf4xNK7ZHPxFVZpX5/qAPJ8rnTaOTHxnN 5PgqbO8CAOxyrTw/muakTJLg+FXdn8BgxZGJXMT7KmkU9SReefjo7c1WlnZxKIAy 6vLIG8WMGpdfCFDve0YLr/GGyDtOjDUB/RN3gn6qnAJThBnVk2wESZVx41fihbIF ACCKc9heFskzwurtvvp+bunM3quwrSH1hWvxiWJlDmGSn8zQFypGChifgLQZSm9o biBEb2UgPGpvaG5AdGVzdC50ZXN0Poi4BBMBAgAiBQJOjcLwAhsDBgsJCAcDAgYV CAIJCgsEFgIDAQIeAQIXgAAKCRC/z7qg+FujnPWiA/9T5SOGraRNIVVIyvJvYwkG OTAfQ0K3QMlLoQMPmaEbx9Q+isF15M9sOMcl1XGO4UNWuCPIIN8z/y/OLgAB0ZuL GlnAPPOOZ+MlaUXiMYo8oi416QZrMDf2H/Nkc10csiXm+zMl8RqeIQBEeljNyJ+t MG1EWn/PHTwFTd/VePuQdJ0B2AROjcLwAQQApw+72jKy0/wqg5SAtnVSkA1F3Jna /OG+ufz5dX57jkMFRvFoksWIWqHmiCjdE5QV8j+XTnjElhLsmrgjl7aAFveb30R6 ImmcpKMN31vAp4RZlnyYbYUCY4IXFuz3n1CaUL+mRx5yNJykrZNfpWNf2pwozkZq lcDI69ymIW5acXUAEQEAAQAD/R7Jdf98l1scngMYo228ikYUxBqm2eX/fiQNXDWM ZR2u+TJ9O53MvFejfXX7Pd6lTDQUBwDFncjgXO0YYSrMzabhqpqoKLqOIpZmBuWC Hh1lvcFoIYoDR2LkiJ9EPBUEVUBDsUO8ajkILEE3G+DDpCaf9Vo82lCVyhDESqyt v4lxAgDOLpoq1Whv5Ejr6FifTWytCiQjH2P1SmePlQmy6oEJRUYA1t4zYrzCJUX8 VAvPjh9JXilP6mhDbyQArWllewV9AgDPbVOf75ktRwfhje26tZsukqWYJCc1XvoH 3PTzA7vH1HZZq7dvxa87PiSnkOLEsIAsI+4jpeMxpPlQRxUvHf1ZAf9rK3v3HMJ/ 2xVzwK24Oaj+g2O7D/fdqtLFGe5S5JobnTyp9xArDAhaZ/AKfDMYjUIKMP+bdNAf y8fQUtuawFltm1GInwQYAQIACQUCTo3C8AIbDAAKCRC/z7qg+FujnDzYA/9EU6Pv Ci1+DCtxjnq7IOvOjqExhFNGvN9Dw17Tl8HcyW3if9v5RxeSWYKl0DhzVdzMQgH/ 78q4F4W1q2IkB7SCpXizHLIc3eh8iZkbWZE+CGPvTpqyF03Yi16qhxpAbkGs2Yhq jTx5oJ4CL5fybBOZLg+BTlK4HIee6xEcbNoq+A== =ZKBW -----END PGP PRIVATE KEY BLOCK----- """ ownertrust = """ 723762CD5A5FECB76DC72DF85ADCFD5631C38741:6: 2940C247A1FBAD508A1AF24BBFCFBAA0F85BA39C:6: """ class MailgwPGPTestCase(MailgwTestAbstractBase): pgphome = gpgmelib.pgphome def setUp(self): MailgwTestAbstractBase.setUp(self) self.db.security.addRole(name = 'pgp', description = 'PGP Role') self.instance.config['PGP_HOMEDIR'] = self.pgphome self.instance.config['PGP_ROLES'] = 'pgp' self.instance.config['PGP_ENABLE'] = True self.instance.config['MAIL_DOMAIN'] = 'example.com' self.instance.config['ADMIN_EMAIL'] = 'roundup-admin@example.com' self.db.user.set(self.john_id, roles='User,pgp') gpgmelib.setUpPGP() def tearDown(self): MailgwTestAbstractBase.tearDown(self) gpgmelib.tearDownPGP() def testPGPUnsignedMessage(self): self.assertRaises(MailUsageError, self._handle_mail, '''Content-Type: text/plain; charset="iso-8859-1" From: John Doe <john@test.test> To: issue_tracker@your.tracker.email.domain.example Message-Id: <dummy_test_message_id> Subject: [issue] Testing non-signed message... This is no pgp signed message. ''') signed_msg = '''Content-Disposition: inline From: John Doe <john@test.test> To: issue_tracker@your.tracker.email.domain.example Subject: [issue] Testing signed message... Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="cWoXeonUoKmBZSoM" --cWoXeonUoKmBZSoM Content-Type: text/plain; charset=us-ascii Content-Disposition: inline This is a pgp signed message. --cWoXeonUoKmBZSoM Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iJwEAQECAAYFAk6N4A4ACgkQv8+6oPhbo5x5nAP/d7R7SxTvLoVESI+1r7eDXp1J LvBVU2EF3YFYKBHMLcWmjG92fNjnHX6NENTEhTeBynba5IPEwUfITC+7PmgPmQkA VXnFZnwraHxsYgyFsVFN1kkTSbwRUlWl9+nTEsr0yBLTpZN0QSIDcwu+i/xVcg+t ZQ4K6R3m3AOw7BLdvZs= =wpYk -----END PGP SIGNATURE----- --cWoXeonUoKmBZSoM-- ''' def testPGPSignedMessage(self): nodeid = self._handle_mail(self.signed_msg) m = self.db.issue.get(nodeid, 'messages')[0] self.assertEqual(self.db.msg.get(m, 'content'), 'This is a pgp signed message.') def testPGPSignedMessageFail(self): # require both, signing and encryption self.instance.config['PGP_REQUIRE_INCOMING'] = 'both' self.assertRaises(MailUsageError, self._handle_mail, self.signed_msg) encrypted_msg = '''Content-Disposition: inline From: John Doe <john@test.test> To: roundup-admin@example.com Subject: [issue] Testing encrypted message... Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="d6Gm4EdcadzBjdND" --d6Gm4EdcadzBjdND Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --d6Gm4EdcadzBjdND Content-Type: application/octet-stream Content-Disposition: inline; filename="msg.asc" -----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.10 (GNU/Linux) hQEMAzfeQttq+Q2YAQf9FxCtZVgC7jAy6UkeAJ1imCpnh9DgKA5w40OFtrY4mVAp cL7kCkvGvJCW7uQZrmSgIiYaZGLI3GS42XutORC6E6PzBEW0fJUMIXYmoSd0OFeY 3H2+854qu37W/uCOWM9OnPFIH8g8q8DgYy88i0goM+Ot9Q96yFfJ7QymanOZJgVa MNC+oKDiIZKiE3PCwtGr+8CHZN/9J6O4FeJijBlr09C5LXc+Nif5T0R0nt17MAns 9g2UvGxW8U24NAS1mOg868U05hquLPIcFz9jGZGknJu7HBpOkQ9GjKqkzN8pgZVN VbN8IdDqi0QtRKE44jtWQlyNlESMjv6GtC2V9F6qKNK8AfHtBexDhyv4G9cPFFNO afQ6e4dPi89RYIQyydtwiqao8fj6jlAy2Z1cbr7YxwBG7BeUZv9yis7ShaAIo78S 82MrCYpSjfHNwKiSfC5yITw22Uv4wWgixVdAsaSdtBqEKXJPG9LNey18ArsBjSM1 P81iDOWUp/uyIe5ZfvNI38BBxEYslPTUlDk2GB8J2Vun7IWHoj9a4tY3IotC9jBr 5Qnigzqrt7cJZX6OrN0c+wnOjXbMGYXmgSs4jeM= =XX5Q -----END PGP MESSAGE----- --d6Gm4EdcadzBjdND-- ''' def testPGPEncryptedUnsignedMessageError(self): self.assertRaises(MailUsageError, self._handle_mail, self.encrypted_msg) def testPGPEncryptedUnsignedMessage(self): # no error if we don't require a signature: self.instance.config['PGP_REQUIRE_INCOMING'] = 'encrypted' nodeid = self._handle_mail (self.encrypted_msg) m = self.db.issue.get(nodeid, 'messages')[0] self.assertEqual(self.db.msg.get(m, 'content'), 'This is the text to be encrypted') def testPGPEncryptedUnsignedMessageFromNonPGPUser(self): msg = self.encrypted_msg.replace('John Doe <john@test.test>', '"Contrary, Mary" <mary@test.test>') nodeid = self._handle_mail (msg) m = self.db.issue.get(nodeid, 'messages')[0] self.assertEqual(self.db.msg.get(m, 'content'), 'This is the text to be encrypted') self.assertEqual(self.db.msg.get(m, 'author'), self.mary_id) # check that a bounce-message that is triggered *after* # decrypting is properly encrypted: def testPGPEncryptedUnsignedMessageCheckBounce(self): # allow non-signed msg self.instance.config['PGP_REQUIRE_INCOMING'] = 'encrypted' # don't allow creation of message, trigger error *after* decrypt self.db.user.set(self.john_id, roles='pgp') self.db.security.addPermissionToRole('pgp', 'Email Access') self.db.security.addPermissionToRole('pgp', 'Create', 'issue') # trap_exc=1: we want a bounce message: self._handle_mail(self.encrypted_msg, trap_exc=1) m = self._get_mail() fp = FeedParser() fp.feed(m) parts = fp.close().get_payload() self.assertEqual(len(parts),2) self.assertEqual(parts[0].get_payload().strip(), 'Version: 1') crypt = pyme.core.Data(parts[1].get_payload()) plain = pyme.core.Data() ctx = pyme.core.Context() res = ctx.op_decrypt(crypt, plain) self.assertEqual(res, None) plain.seek(0,0) fp = FeedParser() fp.feed(plain.read()) parts = fp.close().get_payload() self.assertEqual(len(parts),2) self.assertEqual(parts[0].get_payload().strip(), 'You are not permitted to create messages.') self.assertEqual(parts[1].get_payload().strip(), '''Content-Type: text/plain; charset=us-ascii Content-Disposition: inline This is the text to be encrypted''') def testPGPEncryptedSignedMessage(self): # require both, signing and encryption self.instance.config['PGP_REQUIRE_INCOMING'] = 'both' nodeid = self._handle_mail('''Content-Disposition: inline From: John Doe <john@test.test> To: roundup-admin@example.com Subject: Testing encrypted and signed message MIME-Version: 1.0 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="ReaqsoxgOBHFXBhH" --ReaqsoxgOBHFXBhH Content-Type: application/pgp-encrypted Content-Disposition: attachment Version: 1 --ReaqsoxgOBHFXBhH Content-Type: application/octet-stream Content-Disposition: inline; filename="msg.asc" -----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.10 (GNU/Linux) hQEMAzfeQttq+Q2YAQf+NaC3r8qBURQqxHH9IAP4vg0QAP2yj3n0v6guo1lRf5BA EUfTQ3jc3chxLvzTgoUIuMOvhlNroqR1lgLwhfSTCyuKWDZa+aVNiSgsB2MD44Xd mAkKKmnmOGLmfbICbPQZxl4xNhCMTHiAy1xQE6mTj/+pEAq5XxjJUwn/gJ3O1Wmd NyWtJY2N+TRbxUVB2WhG1j9J1D2sjhG26TciE8JeuLDZzaiVNOW9YlX2Lw5KtlkR Hkgw6Xme06G0XXZUcm9JuBU/7oFP/tSrC1tBsnVlq1pZYf6AygIBdXWb9gD/WmXh 7Eu/xCKrw4RFnXnTgmBz/NHRfVDkfdSscZqexnG1D9LAwQHSuVf8sxDPNesv0W+8 e49loVjvU+Y0BCFQAbWSW4iOEUYZpW/ITRE4+wIqMXZbAraeBV0KPZ4hAa3qSmf+ oZBRcbzssL163Odx/OHRuK2J2CHC654+crrlTBnxd/RUKgRbSUKwrZzB2G6OPcGv wfiqXsY+XvSZtTbWuvUJxePh8vhhhjpuo1JtlrYc3hZ9OYgoCoV1JiLl5c60U5Es oUT9GDl1Qsgb4dF4TJ1IBj+riYiocYpJxPhxzsy6liSLNy2OA6VEjG0FGk53+Ok9 7UzOA+WaHJHSXafZzrdP1TWJUFlOMA+dOgTKpH69eL1+IRfywOjEwp1UNSbLnJpc D0QQLwIFttplKvYkn0DZByJCVnIlGkl4s5LM5rnc8iecX8Jad0iRIlPV6CVM+Nso WdARUfyJfXAmz8uk4f2sVfeMu1gdMySdjvxwlgHDJdBPIG51r2b8L/NCTiC57YjF zGhS06FLl3V1xx6gBlpqQHjut3efrAGpXGBVpnTJMOcgYAk= =jt/n -----END PGP MESSAGE----- --ReaqsoxgOBHFXBhH-- ''') m = self.db.issue.get(nodeid, 'messages')[0] self.assertEqual(self.db.msg.get(m, 'content'), 'This is the text of a signed and encrypted email.') def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(MailgwTestCase)) if pyme is not None: suite.addTest(unittest.makeSuite(MailgwPGPTestCase)) else: print "Skipping PGP tests" return suite if __name__ == '__main__': runner = unittest.TextTestRunner() unittest.main(testRunner=runner) # vim: set filetype=python sts=4 sw=4 et si :
