#!/usr/bin/env python2.5
# -*- coding: utf-8 -*-
#***************************************************************************
-#* Copyright (C) 2004-2008 polytechnique.org *
+#* Copyright (C) 2003-2011 Polytechnique.org *
#* http://opensource.polytechnique.org/ *
#* *
#* This program is free software; you can redistribute it and/or modify *
#* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
#***************************************************************************
-# Copyright (c) 2008 Aymeric Augustin
-
"""
Process as automatically as possible bounces from the newsletter
print '! Not a valid bounce (expected multipart/report, found %s).' % bounce.get_content_type()
return None
# Extract the second component of the multipart/report
- if len(bounce.get_payload()) < 2:
- print '! Not a valid bounce (expected at least 2 parts, found %d).' % len(bounce)
+ num_payloads = len(bounce.get_payload())
+ if num_payloads < 2:
+ print '! Not a valid bounce (expected at least 2 parts, found %d).' % num_payloads
return None
status = bounce.get_payload(1)
if status.get_content_type() != 'message/delivery-status':
print '! Not a valid bounce (expected message/delivery-status, found %s).' % bounce.get_content_type()
return None
# The per-message-fields don't matter here, get only the per-recipient-fields
- if len(status.get_payload()) < 2:
- print '! Not a valid bounce (expected at least 2 parts, found %d).' % len(status)
+ num_payloads = len(status.get_payload())
+ if num_payloads < 2:
+ print '! Not a valid bounce (expected at least 2 parts, found %d).' % num_payloads
return None
content = status.get_payload(1)
if content.get_content_type() != 'text/plain':
if message['X-Spam-Flag'] is None:
# During finalization, we will verifiy that all messages were processed
self.seen += 1
+ # Special case: ignore mailman notifications for the mailing-list
+ # on which the NL is forwarded
+ if message['From'] == 'polytechnique.org_newsletter-externes-bounces@listes.polytechnique.org':
+ print '! Dropping a notification from mailman for newsletter-externes@polytechnique.org, this should be OK.'
+ self.seen -= 1
+ return True
# Additionnal checks, just to be sure
- if message['From'] != 'MAILER-DAEMON@polytechnique.org (Mail Delivery System)' \
+ elif message['From'] != 'MAILER-DAEMON@polytechnique.org (Mail Delivery System)' \
or message['Subject'] != 'Undelivered Mail Returned to Sender':
- return False
- email = findAddressInBounce(message)
- if email is not None:
- self.emails.append(email)
- self.mbox.add(message)
- return True
+ print '! Not an usual direct bounce (From="%s", Subject="%s").' % (message['From'], message['Subject'])
+ else:
+ email = findAddressInBounce(message)
+ if email is not None:
+ self.emails.append(email)
+ self.mbox.add(message)
+ return True
+ else:
+ print '! No email found in direct bounce, this is really bad.'
return False
def finalize(self):
self.mbox.clear()
def process(self, message):
- if message['X-Spam-Flag'].startswith('Yes, tests=bogofilter'):
+ if message['X-Spam-Flag'] is not None \
+ and message['X-Spam-Flag'].startswith('Yes, tests=bogofilter'):
self.mbox.add(message)
return True
return False
self.mbox.clear()
def process(self, message):
- if message['X-Spam-Flag'].startswith('Unsure, tests=bogofilter'):
+ if message['X-Spam-Flag'] is not None \
+ and message['X-Spam-Flag'].startswith('Unsure, tests=bogofilter'):
self.mbox.add(message)
return True
return False
self.seen = 0
def process(self, message):
- if not message['X-Spam-Flag'].startswith('No, tests=bogofilter'):
+ if message['X-Spam-Flag'] is None \
+ or not message['X-Spam-Flag'].startswith('No, tests=bogofilter'):
self.seen += 1
return False
def finalize(self):
if self.seen > 0:
- print 'Encountered %d messages that were neither spam, nor unsure, nor non-spams.' % self.counter
+ print 'Encountered %d messages that were neither spam, nor unsure, nor non-spams.' % self.seen
print 'Please investigate.'
else:
print 'All messages were either spam, or unsure, or non-spams. Good.'
self.mbox.clear()
subject_re = [
r'^Absen(t|ce)',
- r'^Out of office',
- r'est absent',
+ r'(est|is) absent',
+ r'^Out of (the )?office',
r'is out of (the )?office',
- u'^RĂ©ponse automatique d\'absence du bureau', # unicode!
+ r'I am out of town',
+ r'automatique d\'absence',
+ r'Notification d\'absence'
+ u'RĂ©ponse automatique :', #unicode!
+ r'AutoReply',
]
self.subject_regexes = map(re.compile, subject_re, [re.I | re.U] * len(subject_re))
self.mbox_file = '%s.dsn' % mbox_file
self.mbox = mailbox.mbox(self.mbox_file)
self.mbox.clear()
- subject_re = [
- r'^DELIVERY FAILURE: ',
- r'^Delivery Notification: Delivery has failed$',
- r'^Delivery Status Notification ?\(Failure\)$',
- r'^Mail delivery failed',
- r'^(Mail revenu en erreur / )?Undelivered Mail Returned to Sender$',
- r'^Returned mail: see transcript for details$',
- r'^Undeliverable( mail)?:',
- r'^Undelivered Mail Returned to Sender$',
- ]
- self.subject_regexes = map(re.compile, subject_re, [re.I | re.U] * len(subject_re))
def process(self, message):
- subject = findSubject(message)
- if subject is not None and any(regex.search(subject) for regex in self.subject_regexes):
+ if message.get_content_type() == 'multipart/report':
email = findAddressInBounce(message)
if email is not None:
self.emails.append(email)