summaryrefslogtreecommitdiff
path: root/Mailman/Bouncers/Postfix.py
diff options
context:
space:
mode:
authorbwarsaw1999-12-09 22:22:50 +0000
committerbwarsaw1999-12-09 22:22:50 +0000
commitd9b7dff61c0a1eebb1bd798d5e0700bec7c8a02a (patch)
tree9704a6e73178cf3783a85190717e100aa58b6799 /Mailman/Bouncers/Postfix.py
parent96e6800b2ecd53f1d5cedc46425fee8589838a1f (diff)
downloadmailman-d9b7dff61c0a1eebb1bd798d5e0700bec7c8a02a.tar.gz
mailman-d9b7dff61c0a1eebb1bd798d5e0700bec7c8a02a.tar.zst
mailman-d9b7dff61c0a1eebb1bd798d5e0700bec7c8a02a.zip
Diffstat (limited to 'Mailman/Bouncers/Postfix.py')
-rw-r--r--Mailman/Bouncers/Postfix.py80
1 files changed, 80 insertions, 0 deletions
diff --git a/Mailman/Bouncers/Postfix.py b/Mailman/Bouncers/Postfix.py
new file mode 100644
index 000000000..68f68e6c1
--- /dev/null
+++ b/Mailman/Bouncers/Postfix.py
@@ -0,0 +1,80 @@
+# Copyright (C) 1998 by the Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""Parse bounce messages generated by Postfix."""
+
+
+import string
+import re
+import multifile
+import mimetools
+
+from Mailman.pythonlib.StringIO import StringIO
+
+
+
+def process(mlist, msg):
+ if msg.gettype() <> 'multipart/mixed':
+ return None
+ boundary = msg.getparam('boundary')
+ msg.fp.seek(0)
+ mfile = multifile.MultiFile(msg.fp)
+ mfile.push(boundary)
+ # find the subpart with message/delivery-status information
+ while 1:
+ try:
+ more = mfile.next()
+ except multifile.Error:
+ # looked like a multipart, but really wasn't
+ return None
+ if not more:
+ # we didn't find it
+ return None
+ s = StringIO(mfile.read())
+ msg2 = mimetools.Message(s)
+ if msg2.gettype() == 'text/plain':
+ desc = msg2.get('content-description')
+ if string.lower(desc) == 'notification':
+ return findaddr(msg2.fp)
+ # probably not a Postfix bounce
+ return None
+
+
+
+# are these heuristics correct or guaranteed?
+pcre = re.compile(r'\t\t\tthe postfix program$', re.IGNORECASE)
+acre = re.compile(r'<(?P<addr>[^>]*)>:')
+
+def findaddr(fp):
+ # simple state machine
+ # 0 == nothing found
+ # 1 == salutation found
+ state = 0
+ while 1:
+ line = fp.readline()
+ if not line:
+ return None
+ # preserve leading whitespace
+ line = string.rstrip(line)
+ # yes use match to match at beginning of string
+ if state == 0 and pcre.match(line):
+ state = 1
+ elif state == 1 and line:
+ mo = acre.search(line)
+ if mo:
+ return [mo.group('addr')]
+ # hmm, probably not a postfix bounce
+ return None