Skip to content

Commit d596e57

Browse files
author
Richard Jones
committed
ignore incoming email with "Precedence: bulk" (patch [SF#843489])
1 parent abeff61 commit d596e57

File tree

4 files changed

+104
-56
lines changed

4 files changed

+104
-56
lines changed

CHANGES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Feature:
1919
alphabetically (sf feature 790512).
2020
- added script for copying user(s) from tracker to tracker (sf patch
2121
828963)
22+
- ignore incoming email with "Precedence: bulk" (sf patch 843489)
2223

2324
Fixed:
2425
- mysql documentation fixed to note requirement of 4.0+ and InnoDB

doc/index.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Titus Brown,
5858
Roch'e Compaan,
5959
Paul F. Dubois,
6060
Jeff Epler,
61+
Tom Epperly,
6162
Hernan Martinez Foffani,
6263
Ajit George,
6364
Frank Gibbons,

roundup/mailgw.py

Lines changed: 69 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class node. Any parts of other types are each stored in separate files
7373
an exception, the original message is bounced back to the sender with the
7474
explanatory message given in the exception.
7575
76-
$Id: mailgw.py,v 1.138 2003-11-13 03:41:38 richard Exp $
76+
$Id: mailgw.py,v 1.139 2003-12-04 23:34:25 richard Exp $
7777
"""
7878

7979
import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
@@ -92,14 +92,22 @@ class MailUsageError(ValueError):
9292
pass
9393

9494
class MailUsageHelp(Exception):
95-
pass
96-
97-
class MailLoop(Exception):
98-
""" We've seen this message before... """
95+
""" We need to send the help message to the user. """
9996
pass
10097

10198
class Unauthorized(Exception):
10299
""" Access denied """
100+
pass
101+
102+
class IgnoreMessage(Exception):
103+
""" A general class of message that we should ignore. """
104+
pass
105+
class IgnoreBulk(IgnoreMessage):
106+
""" This is email from a mailing list or from a vacation program. """
107+
pass
108+
class IgnoreLoop(IgnoreMessage):
109+
""" We've seen this message before... """
110+
pass
103111

104112
def initialiseSecurity(security):
105113
''' Create some Permissions and Roles on the security object
@@ -300,53 +308,7 @@ def handle_Message(self, message):
300308
sendto = message.getaddrlist('resent-from')
301309
if not sendto:
302310
sendto = message.getaddrlist('from')
303-
if sendto:
304-
if not self.trapExceptions:
305-
return self.handle_message(message)
306-
try:
307-
return self.handle_message(message)
308-
except MailUsageHelp:
309-
# bounce the message back to the sender with the usage message
310-
fulldoc = '\n'.join(string.split(__doc__, '\n')[2:])
311-
sendto = [sendto[0][1]]
312-
m = ['']
313-
m.append('\n\nMail Gateway Help\n=================')
314-
m.append(fulldoc)
315-
self.mailer.bounce_message(message, sendto, m,
316-
subject="Mail Gateway Help")
317-
except MailUsageError, value:
318-
# bounce the message back to the sender with the usage message
319-
fulldoc = '\n'.join(string.split(__doc__, '\n')[2:])
320-
sendto = [sendto[0][1]]
321-
m = ['']
322-
m.append(str(value))
323-
m.append('\n\nMail Gateway Help\n=================')
324-
m.append(fulldoc)
325-
self.mailer.bounce_message(message, sendto, m)
326-
except Unauthorized, value:
327-
# just inform the user that he is not authorized
328-
sendto = [sendto[0][1]]
329-
m = ['']
330-
m.append(str(value))
331-
self.mailer.bounce_message(message, sendto, m)
332-
except MailLoop:
333-
# XXX we should use a log file here...
334-
return
335-
except:
336-
# bounce the message back to the sender with the error message
337-
# XXX we should use a log file here...
338-
sendto = [sendto[0][1], self.instance.config.ADMIN_EMAIL]
339-
m = ['']
340-
m.append('An unexpected error occurred during the processing')
341-
m.append('of your message. The tracker administrator is being')
342-
m.append('notified.\n')
343-
m.append('---- traceback of failure ----')
344-
s = cStringIO.StringIO()
345-
import traceback
346-
traceback.print_exc(None, s)
347-
m.append(s.getvalue())
348-
self.mailer.bounce_message(message, sendto, m)
349-
else:
311+
if not sendto:
350312
# very bad-looking message - we don't even know who sent it
351313
# XXX we should use a log file here...
352314
sendto = [self.instance.config.ADMIN_EMAIL]
@@ -358,6 +320,56 @@ def handle_Message(self, message):
358320
m.append('')
359321
self.mailer.bounce_message(message, sendto, m,
360322
subject='Badly formed message from mail gateway')
323+
return
324+
325+
# try normal message-handling
326+
if not self.trapExceptions:
327+
return self.handle_message(message)
328+
try:
329+
return self.handle_message(message)
330+
except MailUsageHelp:
331+
# bounce the message back to the sender with the usage message
332+
fulldoc = '\n'.join(string.split(__doc__, '\n')[2:])
333+
sendto = [sendto[0][1]]
334+
m = ['']
335+
m.append('\n\nMail Gateway Help\n=================')
336+
m.append(fulldoc)
337+
self.mailer.bounce_message(message, sendto, m,
338+
subject="Mail Gateway Help")
339+
except MailUsageError, value:
340+
# bounce the message back to the sender with the usage message
341+
fulldoc = '\n'.join(string.split(__doc__, '\n')[2:])
342+
sendto = [sendto[0][1]]
343+
m = ['']
344+
m.append(str(value))
345+
m.append('\n\nMail Gateway Help\n=================')
346+
m.append(fulldoc)
347+
self.mailer.bounce_message(message, sendto, m)
348+
except Unauthorized, value:
349+
# just inform the user that he is not authorized
350+
sendto = [sendto[0][1]]
351+
m = ['']
352+
m.append(str(value))
353+
self.mailer.bounce_message(message, sendto, m)
354+
except IgnoreMessage:
355+
# XXX we should use a log file here...
356+
# do not take any action
357+
# this exception is thrown when email should be ignored
358+
return
359+
except:
360+
# bounce the message back to the sender with the error message
361+
# XXX we should use a log file here...
362+
sendto = [sendto[0][1], self.instance.config.ADMIN_EMAIL]
363+
m = ['']
364+
m.append('An unexpected error occurred during the processing')
365+
m.append('of your message. The tracker administrator is being')
366+
m.append('notified.\n')
367+
m.append('---- traceback of failure ----')
368+
s = cStringIO.StringIO()
369+
import traceback
370+
traceback.print_exc(None, s)
371+
m.append(s.getvalue())
372+
self.mailer.bounce_message(message, sendto, m)
361373

362374
def get_part_data_decoded(self,part):
363375
encoding = part.getencoding()
@@ -397,7 +409,11 @@ def handle_message(self, message):
397409
'''
398410
# detect loops
399411
if message.getheader('x-roundup-loop', ''):
400-
raise MailLoop
412+
raise IgnoreLoop
413+
414+
# detect Precedence: Bulk
415+
if (message.getheader('precedence', '') == 'bulk'):
416+
raise IgnoreBulk
401417

402418
# XXX Don't enable. This doesn't work yet.
403419
# "[^A-z.]tracker\+(?P<classname>[^\d\s]+)(?P<nodeid>\d+)\@some.dom.ain[^A-z.]"

test/test_mailgw.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# but WITHOUT ANY WARRANTY; without even the implied warranty of
99
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1010
#
11-
# $Id: test_mailgw.py,v 1.62 2003-11-13 03:41:38 richard Exp $
11+
# $Id: test_mailgw.py,v 1.63 2003-12-04 23:34:25 richard Exp $
1212

1313
import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822
1414

@@ -18,7 +18,8 @@
1818
os.environ['SENDMAILDEBUG'] = 'mail-test.log'
1919
SENDMAILDEBUG = os.environ['SENDMAILDEBUG']
2020

21-
from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, parseContent
21+
from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \
22+
parseContent, IgnoreLoop, IgnoreBulk
2223
from roundup import init, instance, rfc2822
2324

2425

@@ -961,7 +962,36 @@ def testResentFrom(self):
961962
l.sort()
962963
self.assertEqual(l, [self.richard_id, self.mary_id])
963964
return nodeid
964-
965+
966+
967+
def testDejaVu(self):
968+
self.assertRaises(IgnoreLoop, self._send_mail,
969+
'''Content-Type: text/plain;
970+
charset="iso-8859-1"
971+
From: Chef <[email protected]>
972+
X-Roundup-Loop: hello
973+
974+
Cc: richard@test
975+
Message-Id: <dummy_test_message_id>
976+
Subject: Re: [issue] Testing...
977+
978+
Hi, I've been mis-configured to loop messages back to myself.
979+
''')
980+
981+
def testItsBulkStupid(self):
982+
self.assertRaises(IgnoreBulk, self._send_mail,
983+
'''Content-Type: text/plain;
984+
charset="iso-8859-1"
985+
From: Chef <[email protected]>
986+
Precedence: bulk
987+
988+
Cc: richard@test
989+
Message-Id: <dummy_test_message_id>
990+
Subject: Re: [issue] Testing...
991+
992+
Hi, I'm on holidays, and this is a dumb auto-responder.
993+
''')
994+
965995
def test_suite():
966996
suite = unittest.TestSuite()
967997
suite.addTest(unittest.makeSuite(MailgwTestCase))

0 commit comments

Comments
 (0)