summaryrefslogtreecommitdiff
path: root/src/mailman/bouncers/dsn.py
diff options
context:
space:
mode:
authorBarry Warsaw2011-07-15 18:48:32 -0400
committerBarry Warsaw2011-07-15 18:48:32 -0400
commit6a535715b6cd286df1bbbefe20b42a6ad0cc3390 (patch)
treec46c4da417f360bdf002f2511a55cd155a14026c /src/mailman/bouncers/dsn.py
parent651fe5ef452e6ae7cba741c819f9fcc994688753 (diff)
downloadmailman-6a535715b6cd286df1bbbefe20b42a6ad0cc3390.tar.gz
mailman-6a535715b6cd286df1bbbefe20b42a6ad0cc3390.tar.zst
mailman-6a535715b6cd286df1bbbefe20b42a6ad0cc3390.zip
Diffstat (limited to 'src/mailman/bouncers/dsn.py')
-rw-r--r--src/mailman/bouncers/dsn.py102
1 files changed, 0 insertions, 102 deletions
diff --git a/src/mailman/bouncers/dsn.py b/src/mailman/bouncers/dsn.py
deleted file mode 100644
index c9d7803ee..000000000
--- a/src/mailman/bouncers/dsn.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman 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 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman 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
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-"""Parse RFC 3464 (i.e. DSN) bounce formats.
-
-RFC 3464 obsoletes 1894 which was the old DSN standard. This module has not
-been audited for differences between the two.
-"""
-
-from __future__ import absolute_import, unicode_literals
-
-__metaclass__ = type
-__all__ = [
- 'DSN',
- ]
-
-
-from email.iterators import typed_subpart_iterator
-from email.utils import parseaddr
-from zope.interface import implements
-
-from mailman.interfaces.bounce import IBounceDetector, Stop
-
-
-
-class DSN:
- """Parse RFC 3464 (i.e. DSN) bounce formats."""
-
- implements(IBounceDetector)
-
- def process(self, msg):
- """See `IBounceDetector`."""
- # Iterate over each message/delivery-status subpart.
- failed_addresses = []
- delayed_addresses = []
- for part in typed_subpart_iterator(msg, 'message', 'delivery-status'):
- if not part.is_multipart():
- # Huh?
- continue
- # Each message/delivery-status contains a list of Message objects
- # which are the header blocks. Iterate over those too.
- for msgblock in part.get_payload():
- address_set = None
- # We try to dig out the Original-Recipient (which is optional)
- # and Final-Recipient (which is mandatory, but may not exactly
- # match an address on our list). Some MTA's also use
- # X-Actual-Recipient as a synonym for Original-Recipient, but
- # some apparently use that for other purposes :(
- #
- # Also grok out Action so we can do something with that too.
- action = msgblock.get('action', '').lower()
- # Some MTAs have been observed that put comments on the action.
- if action.startswith('delayed'):
- address_set = delayed_addresses
- elif action.startswith('fail'):
- address_set = failed_addresses
- else:
- # Some non-permanent failure, so ignore this block.
- continue
- params = []
- foundp = False
- for header in ('original-recipient', 'final-recipient'):
- for k, v in msgblock.get_params([], header):
- if k.lower() == 'rfc822':
- foundp = True
- else:
- params.append(k)
- if foundp:
- # Note that params should already be unquoted.
- address_set.extend(params)
- break
- else:
- # MAS: This is a kludge, but
- # SMTP-GATEWAY01.intra.home.dk has a final-recipient
- # with an angle-addr and no address-type parameter at
- # all. Non-compliant, but ...
- for param in params:
- if param.startswith('<') and param.endswith('>'):
- address_set.append(param[1:-1])
- # There may be both delayed and failed addresses. If there are any
- # failed addresses, return those, otherwise just stop processing.
- if len(failed_addresses) == 0:
- if len(delayed_addresses) == 0:
- return set()
- else:
- return Stop
- return set(parseaddr(address)[1] for address in failed_addresses
- if address is not None)