comparison roundup/mailgw.py @ 1945:7e4058dfb29b

ignore incoming email with "Precedence: bulk" (patch [SF#843489])
author Richard Jones <richard@users.sourceforge.net>
date Thu, 04 Dec 2003 23:34:25 +0000
parents 20cfd25cffda
children ca2dca3db172
comparison
equal deleted inserted replaced
1944:23fd363ece42 1945:7e4058dfb29b
71 set() method to add the message to the item's spool; in the second case we 71 set() method to add the message to the item's spool; in the second case we
72 are calling the create() method to create a new node). If an auditor raises 72 are calling the create() method to create a new node). If an auditor raises
73 an exception, the original message is bounced back to the sender with the 73 an exception, the original message is bounced back to the sender with the
74 explanatory message given in the exception. 74 explanatory message given in the exception.
75 75
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 $
77 """ 77 """
78 78
79 import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri 79 import string, re, os, mimetools, cStringIO, smtplib, socket, binascii, quopri
80 import time, random, sys 80 import time, random, sys
81 import traceback, MimeWriter, rfc822 81 import traceback, MimeWriter, rfc822
90 90
91 class MailUsageError(ValueError): 91 class MailUsageError(ValueError):
92 pass 92 pass
93 93
94 class MailUsageHelp(Exception): 94 class MailUsageHelp(Exception):
95 pass 95 """ We need to send the help message to the user. """
96
97 class MailLoop(Exception):
98 """ We've seen this message before... """
99 pass 96 pass
100 97
101 class Unauthorized(Exception): 98 class Unauthorized(Exception):
102 """ Access denied """ 99 """ 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
103 111
104 def initialiseSecurity(security): 112 def initialiseSecurity(security):
105 ''' Create some Permissions and Roles on the security object 113 ''' Create some Permissions and Roles on the security object
106 114
107 This function is directly invoked by security.Security.__init__() 115 This function is directly invoked by security.Security.__init__()
298 # in some rare cases, a particularly stuffed-up e-mail will make 306 # in some rare cases, a particularly stuffed-up e-mail will make
299 # its way into here... try to handle it gracefully 307 # its way into here... try to handle it gracefully
300 sendto = message.getaddrlist('resent-from') 308 sendto = message.getaddrlist('resent-from')
301 if not sendto: 309 if not sendto:
302 sendto = message.getaddrlist('from') 310 sendto = message.getaddrlist('from')
303 if sendto: 311 if not 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:
350 # very bad-looking message - we don't even know who sent it 312 # very bad-looking message - we don't even know who sent it
351 # XXX we should use a log file here... 313 # XXX we should use a log file here...
352 sendto = [self.instance.config.ADMIN_EMAIL] 314 sendto = [self.instance.config.ADMIN_EMAIL]
353 m = ['Subject: badly formed message from mail gateway'] 315 m = ['Subject: badly formed message from mail gateway']
354 m.append('') 316 m.append('')
356 m.append('line, indicating that it is corrupt. Please check your') 318 m.append('line, indicating that it is corrupt. Please check your')
357 m.append('mail gateway source. Failed message is attached.') 319 m.append('mail gateway source. Failed message is attached.')
358 m.append('') 320 m.append('')
359 self.mailer.bounce_message(message, sendto, m, 321 self.mailer.bounce_message(message, sendto, m,
360 subject='Badly formed message from mail gateway') 322 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)
361 373
362 def get_part_data_decoded(self,part): 374 def get_part_data_decoded(self,part):
363 encoding = part.getencoding() 375 encoding = part.getencoding()
364 data = None 376 data = None
365 if encoding == 'base64': 377 if encoding == 'base64':
395 407
396 Parse the message as per the module docstring. 408 Parse the message as per the module docstring.
397 ''' 409 '''
398 # detect loops 410 # detect loops
399 if message.getheader('x-roundup-loop', ''): 411 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
401 417
402 # XXX Don't enable. This doesn't work yet. 418 # XXX Don't enable. This doesn't work yet.
403 # "[^A-z.]tracker\+(?P<classname>[^\d\s]+)(?P<nodeid>\d+)\@some.dom.ain[^A-z.]" 419 # "[^A-z.]tracker\+(?P<classname>[^\d\s]+)(?P<nodeid>\d+)\@some.dom.ain[^A-z.]"
404 # handle delivery to addresses like:tracker+issue25@some.dom.ain 420 # handle delivery to addresses like:tracker+issue25@some.dom.ain
405 # use the embedded issue number as our issue 421 # use the embedded issue number as our issue

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