X-Git-Url: http://git.polytechnique.org/?a=blobdiff_plain;f=bin%2Fnewsletter.bounces.processor.py;h=8fc3c1a75531ef5edf3f4c0b74b6b3c5b1b98a72;hb=c76545c351fae4e2298624ff9ee5bf854dc5a5b6;hp=e3972d6f610626d176c23dee742e20a0e4f4d74c;hpb=58e64caf91765a173eed194050b72ddbb1cefb1a;p=platal.git diff --git a/bin/newsletter.bounces.processor.py b/bin/newsletter.bounces.processor.py index e3972d6..8fc3c1a 100755 --- a/bin/newsletter.bounces.processor.py +++ b/bin/newsletter.bounces.processor.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2.5 # -*- coding: utf-8 -*- #*************************************************************************** -#* Copyright (C) 2004-2008 polytechnique.org * +#* Copyright (C) 2003-2010 Polytechnique.org * #* http://opensource.polytechnique.org/ * #* * #* This program is free software; you can redistribute it and/or modify * @@ -20,8 +20,6 @@ #* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * #*************************************************************************** -# Copyright (c) 2008 Aymeric Augustin - """ Process as automatically as possible bounces from the newsletter @@ -127,16 +125,18 @@ def findAddressInBounce(bounce): 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': @@ -176,15 +176,24 @@ class DirectBouncesFilter(MboxFilter): 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): @@ -211,7 +220,8 @@ class SpamFilter(MboxFilter): 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 @@ -232,7 +242,8 @@ class UnsureFilter(MboxFilter): 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 @@ -251,13 +262,14 @@ class CheckNonSpamFilter(MboxFilter): 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.' @@ -272,10 +284,14 @@ class OutOfOfficeFilter(MboxFilter): 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)) @@ -301,21 +317,9 @@ class DeliveryStatusNotificationFilter(MboxFilter): 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)