summaryrefslogtreecommitdiff
path: root/src/mailman/mta/verp.py
diff options
context:
space:
mode:
authorBarry Warsaw2009-11-01 12:20:10 -0500
committerBarry Warsaw2009-11-01 12:20:10 -0500
commitc05caff08e5229e7f16ca02aaa4eed78a74a4999 (patch)
treea766f54fe981992ac2921d3b446c36949d15e2ff /src/mailman/mta/verp.py
parent4f2ca4cb900ab891ebbbec56bd30b737304a3da7 (diff)
downloadmailman-c05caff08e5229e7f16ca02aaa4eed78a74a4999.tar.gz
mailman-c05caff08e5229e7f16ca02aaa4eed78a74a4999.tar.zst
mailman-c05caff08e5229e7f16ca02aaa4eed78a74a4999.zip
Diffstat (limited to 'src/mailman/mta/verp.py')
-rw-r--r--src/mailman/mta/verp.py84
1 files changed, 84 insertions, 0 deletions
diff --git a/src/mailman/mta/verp.py b/src/mailman/mta/verp.py
new file mode 100644
index 000000000..be44afd10
--- /dev/null
+++ b/src/mailman/mta/verp.py
@@ -0,0 +1,84 @@
+# Copyright (C) 2009 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/>.
+
+"""VERP (i.e. personalized) message delivery."""
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'VERPDelivery',
+ ]
+
+
+import copy
+import logging
+
+from mailman.config import config
+from mailman.email.utils import split_email
+from mailman.mta.base import BaseDelivery
+from mailman.utilities.string import expand
+
+
+DOT = '.'
+log = logging.getLogger('mailman.smtp')
+
+
+
+class VERPDelivery(BaseDelivery):
+ """Deliver a unique message to the MSA for each recipient."""
+
+ def deliver(self, mlist, msg, msgdata):
+ """See `IMailTransportAgentDelivery`.
+
+ Craft a unique message for every recipient. Encode the recipient's
+ delivery address in the return envelope so there can be no ambiguity
+ in bounce processing.
+ """
+ recipients = msgdata.get('recipients')
+ if not recipients:
+ # Could be None, could be an empty sequence.
+ return
+ sender = self._get_sender(mlist, msg, msgdata)
+ sender_mailbox, sender_domain = split_email(sender)
+ for recipient in recipients:
+ # Make a copy of the original messages and operator on it, since
+ # we're going to munge it repeatedly for each recipient.
+ message_copy = copy.deepcopy(msg)
+ # Encode the recipient's address for VERP.
+ recipient_mailbox, recipient_domain = split_email(recipient)
+ if recipient_domain is None:
+ # The recipient address is not fully-qualified. We can't
+ # deliver it to this person, nor can we craft a valid verp
+ # header. I don't think there's much we can do except ignore
+ # this recipient.
+ log.info('Skipping VERP delivery to unqual recip: %s', recip)
+ continue
+ verp_sender = '{0}@{1}'.format(
+ expand(config.mta.verp_format, dict(
+ bounces=sender_mailbox,
+ local=recipient_mailbox,
+ domain=DOT.join(recipient_domain))),
+ DOT.join(sender_domain))
+ # We can flag the mail as a duplicate for each member, if they've
+ # already received this message, as calculated by Message-ID. See
+ # AvoidDuplicates.py for details.
+ del message_copy['x-mailman-copy']
+ if recipient in msgdata.get('add-dup-header', {}):
+ message_copy['X-Mailman-Copy'] = 'yes'
+ self._deliver_to_recipients(mlist, msg, msgdata,
+ verp_sender, [recipient])