comparison test/test_mailgw.py @ 4541:62239a524beb

PGP support is again working (pyme API has changed significantly)... ...and we now have a regression test. We now take care that bounce-messages for incoming encrypted mails or mails where the policy dictates that outgoing traffic should be encrypted is actually pgp-encrypted. Note that the new pgp encrypt option for outgoing mails works only for bounces for now.
author Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net>
date Fri, 07 Oct 2011 14:21:57 +0000
parents bf67fed13ef9
children 46239c21a1eb
comparison
equal deleted inserted replaced
4540:bf67fed13ef9 4541:62239a524beb
12 # $Id: test_mailgw.py,v 1.96 2008-08-19 01:40:59 richard Exp $ 12 # $Id: test_mailgw.py,v 1.96 2008-08-19 01:40:59 richard Exp $
13 13
14 # TODO: test bcc 14 # TODO: test bcc
15 15
16 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822, time 16 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822, time
17 from email.parser import FeedParser
17 18
18 19
19 try: 20 try:
20 import pyme, pyme.core 21 import pyme, pyme.core
21 except ImportError: 22 except ImportError:
162 return self._handle_message(message) 163 return self._handle_message(message)
163 handler = MailGW(self.instance, args) 164 handler = MailGW(self.instance, args)
164 handler.db = self.db 165 handler.db = self.db
165 return handler 166 return handler
166 167
167 def _handle_mail(self, message, args=()): 168 def _handle_mail(self, message, args=(), trap_exc=0):
168 handler = self._create_mailgw(message, args) 169 handler = self._create_mailgw(message, args)
169 handler.trapExceptions = 0 170 handler.trapExceptions = trap_exc
170 return handler.main(StringIO(message)) 171 return handler.main(StringIO(message))
171 172
172 def _get_mail(self): 173 def _get_mail(self):
173 f = open(SENDMAILDEBUG) 174 f = open(SENDMAILDEBUG)
174 try: 175 try:
1873 Message-Id: <dummy_test_message_id> 1874 Message-Id: <dummy_test_message_id>
1874 Subject: [issue] Testing nonexisting user... 1875 Subject: [issue] Testing nonexisting user...
1875 1876
1876 This is a test submission of a new issue. 1877 This is a test submission of a new issue.
1877 ''' 1878 '''
1878 handler = self._create_mailgw(message) 1879 # trap_exc=1: we want a bounce message:
1879 # we want a bounce message: 1880 ret = self._handle_mail(message, trap_exc=1)
1880 handler.trapExceptions = 1
1881 ret = handler.main(StringIO(message))
1882 self.compareMessages(self._get_mail(), 1881 self.compareMessages(self._get_mail(),
1883 '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example> 1882 '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1884 TO: nonexisting@bork.bork.bork 1883 TO: nonexisting@bork.bork.bork
1885 From nobody Tue Jul 14 12:04:11 2009 1884 From nobody Tue Jul 14 12:04:11 2009
1886 Content-Type: multipart/mixed; boundary="===============0639262320==" 1885 Content-Type: multipart/mixed; boundary="===============0639262320=="
3065 3064
3066 class MailgwPGPTestCase(MailgwTestAbstractBase): 3065 class MailgwPGPTestCase(MailgwTestAbstractBase):
3067 pgphome = 'pgp-test-home' 3066 pgphome = 'pgp-test-home'
3068 def setUp(self): 3067 def setUp(self):
3069 MailgwTestAbstractBase.setUp(self) 3068 MailgwTestAbstractBase.setUp(self)
3070 self.db.security.addRole (name = 'pgp', description = 'PGP Role') 3069 self.db.security.addRole(name = 'pgp', description = 'PGP Role')
3071 self.instance.config['PGP_HOMEDIR'] = self.pgphome 3070 self.instance.config['PGP_HOMEDIR'] = self.pgphome
3072 self.instance.config['PGP_ROLES'] = 'pgp' 3071 self.instance.config['PGP_ROLES'] = 'pgp'
3073 self.instance.config['PGP_ENABLE'] = True 3072 self.instance.config['PGP_ENABLE'] = True
3073 self.instance.config['MAIL_DOMAIN'] = 'example.com'
3074 self.instance.config['ADMIN_EMAIL'] = 'roundup-admin@example.com'
3074 self.db.user.set(self.john_id, roles='User,pgp') 3075 self.db.user.set(self.john_id, roles='User,pgp')
3075 os.mkdir(self.pgphome) 3076 os.mkdir(self.pgphome)
3076 os.environ['GNUPGHOME'] = self.pgphome 3077 os.environ['GNUPGHOME'] = self.pgphome
3077 ctx = pyme.core.Context() 3078 ctx = pyme.core.Context()
3078 key = pyme.core.Data(pgp_test_key) 3079 key = pyme.core.Data(pgp_test_key)
3088 def tearDown(self): 3089 def tearDown(self):
3089 MailgwTestAbstractBase.tearDown(self) 3090 MailgwTestAbstractBase.tearDown(self)
3090 if os.path.exists(self.pgphome): 3091 if os.path.exists(self.pgphome):
3091 shutil.rmtree(self.pgphome) 3092 shutil.rmtree(self.pgphome)
3092 3093
3093 def testUnsignedMessage(self): 3094 def testPGPUnsignedMessage(self):
3094 self.assertRaises(MailUsageError, self._handle_mail, 3095 self.assertRaises(MailUsageError, self._handle_mail,
3095 '''Content-Type: text/plain; 3096 '''Content-Type: text/plain;
3096 charset="iso-8859-1" 3097 charset="iso-8859-1"
3097 From: John Doe <john@test.test> 3098 From: John Doe <john@test.test>
3098 To: issue_tracker@your.tracker.email.domain.example 3099 To: issue_tracker@your.tracker.email.domain.example
3100 Subject: [issue] Testing non-signed message... 3101 Subject: [issue] Testing non-signed message...
3101 3102
3102 This is no pgp signed message. 3103 This is no pgp signed message.
3103 ''') 3104 ''')
3104 3105
3105 def testSignedMessage(self): 3106 signed_msg = '''Content-Disposition: inline
3106 nodeid = self._handle_mail('''Content-Disposition: inline
3107 From: John Doe <john@test.test> 3107 From: John Doe <john@test.test>
3108 To: issue_tracker@your.tracker.email.domain.example 3108 To: issue_tracker@your.tracker.email.domain.example
3109 Subject: [issue] Testing signed message... 3109 Subject: [issue] Testing signed message...
3110 Content-Type: multipart/signed; micalg=pgp-sha1; 3110 Content-Type: multipart/signed; micalg=pgp-sha1;
3111 protocol="application/pgp-signature"; boundary="cWoXeonUoKmBZSoM" 3111 protocol="application/pgp-signature"; boundary="cWoXeonUoKmBZSoM"
3131 ZQ4K6R3m3AOw7BLdvZs= 3131 ZQ4K6R3m3AOw7BLdvZs=
3132 =wpYk 3132 =wpYk
3133 -----END PGP SIGNATURE----- 3133 -----END PGP SIGNATURE-----
3134 3134
3135 --cWoXeonUoKmBZSoM-- 3135 --cWoXeonUoKmBZSoM--
3136 ''') 3136 '''
3137 m = self.db.issue.get (nodeid, 'messages') [0] 3137
3138 def testPGPSignedMessage(self):
3139 nodeid = self._handle_mail(self.signed_msg)
3140 m = self.db.issue.get(nodeid, 'messages')[0]
3138 self.assertEqual(self.db.msg.get(m, 'content'), 3141 self.assertEqual(self.db.msg.get(m, 'content'),
3139 'This is a pgp signed message.') 3142 'This is a pgp signed message.')
3143
3144 def testPGPSignedMessageFail(self):
3145 # require both, signing and encryption
3146 self.instance.config['PGP_REQUIRE_INCOMING'] = 'both'
3147 self.assertRaises(MailUsageError, self._handle_mail, self.signed_msg)
3148
3149 encrypted_msg = '''Content-Disposition: inline
3150 From: John Doe <john@test.test>
3151 To: roundup-admin@example.com
3152 Subject: [issue] Testing encrypted message...
3153 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
3154 boundary="d6Gm4EdcadzBjdND"
3155
3156 --d6Gm4EdcadzBjdND
3157 Content-Type: application/pgp-encrypted
3158 Content-Disposition: attachment
3159
3160 Version: 1
3161
3162 --d6Gm4EdcadzBjdND
3163 Content-Type: application/octet-stream
3164 Content-Disposition: inline; filename="msg.asc"
3165
3166 -----BEGIN PGP MESSAGE-----
3167 Version: GnuPG v1.4.10 (GNU/Linux)
3168
3169 hQEMAzfeQttq+Q2YAQf9FxCtZVgC7jAy6UkeAJ1imCpnh9DgKA5w40OFtrY4mVAp
3170 cL7kCkvGvJCW7uQZrmSgIiYaZGLI3GS42XutORC6E6PzBEW0fJUMIXYmoSd0OFeY
3171 3H2+854qu37W/uCOWM9OnPFIH8g8q8DgYy88i0goM+Ot9Q96yFfJ7QymanOZJgVa
3172 MNC+oKDiIZKiE3PCwtGr+8CHZN/9J6O4FeJijBlr09C5LXc+Nif5T0R0nt17MAns
3173 9g2UvGxW8U24NAS1mOg868U05hquLPIcFz9jGZGknJu7HBpOkQ9GjKqkzN8pgZVN
3174 VbN8IdDqi0QtRKE44jtWQlyNlESMjv6GtC2V9F6qKNK8AfHtBexDhyv4G9cPFFNO
3175 afQ6e4dPi89RYIQyydtwiqao8fj6jlAy2Z1cbr7YxwBG7BeUZv9yis7ShaAIo78S
3176 82MrCYpSjfHNwKiSfC5yITw22Uv4wWgixVdAsaSdtBqEKXJPG9LNey18ArsBjSM1
3177 P81iDOWUp/uyIe5ZfvNI38BBxEYslPTUlDk2GB8J2Vun7IWHoj9a4tY3IotC9jBr
3178 5Qnigzqrt7cJZX6OrN0c+wnOjXbMGYXmgSs4jeM=
3179 =XX5Q
3180 -----END PGP MESSAGE-----
3181
3182 --d6Gm4EdcadzBjdND--
3183 '''
3184 def testPGPEncryptedUnsignedMessageError(self):
3185 self.assertRaises(MailUsageError, self._handle_mail, self.encrypted_msg)
3186
3187 def testPGPEncryptedUnsignedMessage(self):
3188 # no error if we don't require a signature:
3189 self.instance.config['PGP_REQUIRE_INCOMING'] = 'encrypted'
3190 nodeid = self._handle_mail (self.encrypted_msg)
3191 m = self.db.issue.get(nodeid, 'messages')[0]
3192 self.assertEqual(self.db.msg.get(m, 'content'),
3193 'This is the text to be encrypted')
3194
3195 def testPGPEncryptedUnsignedMessageFromNonPGPUser(self):
3196 msg = self.encrypted_msg.replace('John Doe <john@test.test>',
3197 '"Contrary, Mary" <mary@test.test>')
3198 nodeid = self._handle_mail (msg)
3199 m = self.db.issue.get(nodeid, 'messages')[0]
3200 self.assertEqual(self.db.msg.get(m, 'content'),
3201 'This is the text to be encrypted')
3202 self.assertEqual(self.db.msg.get(m, 'author'), self.mary_id)
3203
3204 # check that a bounce-message that is triggered *after*
3205 # decrypting is properly encrypted:
3206 def testPGPEncryptedUnsignedMessageCheckBounce(self):
3207 # allow non-signed msg
3208 self.instance.config['PGP_REQUIRE_INCOMING'] = 'encrypted'
3209 # don't allow creation of message, trigger error *after* decrypt
3210 self.db.user.set(self.john_id, roles='pgp')
3211 self.db.security.addPermissionToRole('pgp', 'Email Access')
3212 self.db.security.addPermissionToRole('pgp', 'Create', 'issue')
3213 # trap_exc=1: we want a bounce message:
3214 self._handle_mail(self.encrypted_msg, trap_exc=1)
3215 m = self._get_mail()
3216 fp = FeedParser()
3217 fp.feed(m)
3218 parts = fp.close().get_payload()
3219 self.assertEqual(len(parts),2)
3220 self.assertEqual(parts[0].get_payload().strip(), 'Version: 1')
3221 crypt = pyme.core.Data(parts[1].get_payload())
3222 plain = pyme.core.Data()
3223 ctx = pyme.core.Context()
3224 res = ctx.op_decrypt(crypt, plain)
3225 self.assertEqual(res, None)
3226 plain.seek(0,0)
3227 fp = FeedParser()
3228 fp.feed(plain.read())
3229 parts = fp.close().get_payload()
3230 self.assertEqual(len(parts),2)
3231 self.assertEqual(parts[0].get_payload().strip(),
3232 'You are not permitted to create messages.')
3233 self.assertEqual(parts[1].get_payload().strip(),
3234 '''Content-Type: text/plain; charset=us-ascii
3235 Content-Disposition: inline
3236
3237 This is the text to be encrypted''')
3238
3239
3240 def testPGPEncryptedSignedMessage(self):
3241 # require both, signing and encryption
3242 self.instance.config['PGP_REQUIRE_INCOMING'] = 'both'
3243 nodeid = self._handle_mail('''Content-Disposition: inline
3244 From: John Doe <john@test.test>
3245 To: roundup-admin@example.com
3246 Subject: Testing encrypted and signed message
3247 MIME-Version: 1.0
3248 Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
3249 boundary="ReaqsoxgOBHFXBhH"
3250
3251 --ReaqsoxgOBHFXBhH
3252 Content-Type: application/pgp-encrypted
3253 Content-Disposition: attachment
3254
3255 Version: 1
3256
3257 --ReaqsoxgOBHFXBhH
3258 Content-Type: application/octet-stream
3259 Content-Disposition: inline; filename="msg.asc"
3260
3261 -----BEGIN PGP MESSAGE-----
3262 Version: GnuPG v1.4.10 (GNU/Linux)
3263
3264 hQEMAzfeQttq+Q2YAQf+NaC3r8qBURQqxHH9IAP4vg0QAP2yj3n0v6guo1lRf5BA
3265 EUfTQ3jc3chxLvzTgoUIuMOvhlNroqR1lgLwhfSTCyuKWDZa+aVNiSgsB2MD44Xd
3266 mAkKKmnmOGLmfbICbPQZxl4xNhCMTHiAy1xQE6mTj/+pEAq5XxjJUwn/gJ3O1Wmd
3267 NyWtJY2N+TRbxUVB2WhG1j9J1D2sjhG26TciE8JeuLDZzaiVNOW9YlX2Lw5KtlkR
3268 Hkgw6Xme06G0XXZUcm9JuBU/7oFP/tSrC1tBsnVlq1pZYf6AygIBdXWb9gD/WmXh
3269 7Eu/xCKrw4RFnXnTgmBz/NHRfVDkfdSscZqexnG1D9LAwQHSuVf8sxDPNesv0W+8
3270 e49loVjvU+Y0BCFQAbWSW4iOEUYZpW/ITRE4+wIqMXZbAraeBV0KPZ4hAa3qSmf+
3271 oZBRcbzssL163Odx/OHRuK2J2CHC654+crrlTBnxd/RUKgRbSUKwrZzB2G6OPcGv
3272 wfiqXsY+XvSZtTbWuvUJxePh8vhhhjpuo1JtlrYc3hZ9OYgoCoV1JiLl5c60U5Es
3273 oUT9GDl1Qsgb4dF4TJ1IBj+riYiocYpJxPhxzsy6liSLNy2OA6VEjG0FGk53+Ok9
3274 7UzOA+WaHJHSXafZzrdP1TWJUFlOMA+dOgTKpH69eL1+IRfywOjEwp1UNSbLnJpc
3275 D0QQLwIFttplKvYkn0DZByJCVnIlGkl4s5LM5rnc8iecX8Jad0iRIlPV6CVM+Nso
3276 WdARUfyJfXAmz8uk4f2sVfeMu1gdMySdjvxwlgHDJdBPIG51r2b8L/NCTiC57YjF
3277 zGhS06FLl3V1xx6gBlpqQHjut3efrAGpXGBVpnTJMOcgYAk=
3278 =jt/n
3279 -----END PGP MESSAGE-----
3280
3281 --ReaqsoxgOBHFXBhH--
3282 ''')
3283 m = self.db.issue.get(nodeid, 'messages')[0]
3284 self.assertEqual(self.db.msg.get(m, 'content'),
3285 'This is the text of a signed and encrypted email.')
3286
3140 3287
3141 def test_suite(): 3288 def test_suite():
3142 suite = unittest.TestSuite() 3289 suite = unittest.TestSuite()
3143 suite.addTest(unittest.makeSuite(MailgwTestCase)) 3290 suite.addTest(unittest.makeSuite(MailgwTestCase))
3144 if pyme is not None: 3291 if pyme is not None:

Roundup Issue Tracker: http://roundup-tracker.org/