summaryrefslogtreecommitdiff
path: root/Mailman/docs/avoid-duplicates.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/docs/avoid-duplicates.txt')
-rw-r--r--Mailman/docs/avoid-duplicates.txt183
1 files changed, 183 insertions, 0 deletions
diff --git a/Mailman/docs/avoid-duplicates.txt b/Mailman/docs/avoid-duplicates.txt
new file mode 100644
index 000000000..6a58382fd
--- /dev/null
+++ b/Mailman/docs/avoid-duplicates.txt
@@ -0,0 +1,183 @@
+Avoid duplicates
+================
+
+The AvoidDuplicates handler module implements several strategies to try to
+reduce the reception of duplicate messages. It does this by removing certain
+recipients from the list of recipients that earlier handler modules
+(e.g. CalcRecips) calculates.
+
+ >>> from email import message_from_string
+ >>> from Mailman.Message import Message
+ >>> from Mailman.Handlers.AvoidDuplicates import process
+ >>> from Mailman.configuration import config
+ >>> from Mailman.database import flush
+ >>> mlist = config.list_manager.create('_xtest@example.com')
+ >>> flush()
+
+Create some members we're going to use.
+
+ >>> from Mailman.constants import MemberRole
+ >>> address_a = config.user_manager.create_address('aperson@example.com')
+ >>> address_b = config.user_manager.create_address('bperson@example.com')
+ >>> member_a = address_a.subscribe(mlist, MemberRole.member)
+ >>> member_b = address_b.subscribe(mlist, MemberRole.member)
+ >>> flush()
+ >>> # This is the message metadata dictionary as it would be produced by
+ >>> # the CalcRecips handler.
+ >>> recips = dict(recips=['aperson@example.com', 'bperson@example.com'])
+
+
+Short circuiting
+----------------
+
+The module short-circuits if there are no recipients.
+
+ >>> msg = message_from_string("""\
+ ... From: aperson@example.com
+ ... Subject: A message of great import
+ ...
+ ... Something
+ ... """, Message)
+ >>> msgdata = {}
+ >>> process(mlist, msg, msgdata)
+ >>> msgdata
+ {}
+ >>> print msg.as_string()
+ From: aperson@example.com
+ Subject: A message of great import
+ <BLANKLINE>
+ Something
+ <BLANKLINE>
+
+
+Suppressing the list copy
+-------------------------
+
+Members can elect not to receive a list copy of any message on which they are
+explicitly named as a recipient. This is done by setting their
+receive_list_copy preference to False. However, if they aren't mentioned in
+one of the recipient headers (i.e. To, CC, Resent-To, or Resent-CC), then they
+will get a list copy.
+
+ >>> member_a.preferences.receive_list_copy = False
+ >>> flush()
+ >>> msg = message_from_string("""\
+ ... From: Claire Person <cperson@example.com>
+ ...
+ ... Something of great import.
+ ... """, Message)
+ >>> msgdata = recips.copy()
+ >>> process(mlist, msg, msgdata)
+ >>> sorted(msgdata['recips'])
+ ['aperson@example.com', 'bperson@example.com']
+ >>> print msg.as_string()
+ From: Claire Person <cperson@example.com>
+ <BLANKLINE>
+ Something of great import.
+ <BLANKLINE>
+
+If they're mentioned on the CC line, they won't get a list copy.
+
+ >>> msg = message_from_string("""\
+ ... From: Claire Person <cperson@example.com>
+ ... CC: aperson@example.com
+ ...
+ ... Something of great import.
+ ... """, Message)
+ >>> msgdata = recips.copy()
+ >>> process(mlist, msg, msgdata)
+ >>> sorted(msgdata['recips'])
+ ['bperson@example.com']
+ >>> print msg.as_string()
+ From: Claire Person <cperson@example.com>
+ CC: aperson@example.com
+ <BLANKLINE>
+ Something of great import.
+ <BLANKLINE>
+
+But if they're mentioned on the CC line and have receive_list_copy set to True
+(the default), then they still get a list copy.
+
+ >>> msg = message_from_string("""\
+ ... From: Claire Person <cperson@example.com>
+ ... CC: bperson@example.com
+ ...
+ ... Something of great import.
+ ... """, Message)
+ >>> msgdata = recips.copy()
+ >>> process(mlist, msg, msgdata)
+ >>> sorted(msgdata['recips'])
+ ['aperson@example.com', 'bperson@example.com']
+ >>> print msg.as_string()
+ From: Claire Person <cperson@example.com>
+ CC: bperson@example.com
+ <BLANKLINE>
+ Something of great import.
+ <BLANKLINE>
+
+Other headers checked for recipients include the To...
+
+ >>> msg = message_from_string("""\
+ ... From: Claire Person <cperson@example.com>
+ ... To: aperson@example.com
+ ...
+ ... Something of great import.
+ ... """, Message)
+ >>> msgdata = recips.copy()
+ >>> process(mlist, msg, msgdata)
+ >>> sorted(msgdata['recips'])
+ ['bperson@example.com']
+ >>> print msg.as_string()
+ From: Claire Person <cperson@example.com>
+ To: aperson@example.com
+ <BLANKLINE>
+ Something of great import.
+ <BLANKLINE>
+
+...Resent-To...
+
+ >>> msg = message_from_string("""\
+ ... From: Claire Person <cperson@example.com>
+ ... Resent-To: aperson@example.com
+ ...
+ ... Something of great import.
+ ... """, Message)
+ >>> msgdata = recips.copy()
+ >>> process(mlist, msg, msgdata)
+ >>> sorted(msgdata['recips'])
+ ['bperson@example.com']
+ >>> print msg.as_string()
+ From: Claire Person <cperson@example.com>
+ Resent-To: aperson@example.com
+ <BLANKLINE>
+ Something of great import.
+ <BLANKLINE>
+
+...and Resent-CC headers.
+
+ >>> msg = message_from_string("""\
+ ... From: Claire Person <cperson@example.com>
+ ... Resent-Cc: aperson@example.com
+ ...
+ ... Something of great import.
+ ... """, Message)
+ >>> msgdata = recips.copy()
+ >>> process(mlist, msg, msgdata)
+ >>> sorted(msgdata['recips'])
+ ['bperson@example.com']
+ >>> print msg.as_string()
+ From: Claire Person <cperson@example.com>
+ Resent-Cc: aperson@example.com
+ <BLANKLINE>
+ Something of great import.
+ <BLANKLINE>
+
+
+Clean up
+--------
+
+ >>> for mlist in config.list_manager.mailing_lists:
+ ... config.list_manager.delete(mlist)
+ >>> flush()
+ >>> list(config.list_manager.mailing_lists)
+ []