[Mailman-Developers] New option for mailman-cvs: reply-to munging per user

Marc MERLIN marc_news@vasoftware.com
Mon, 11 Mar 2002 01:18:54 -0800


--Y7xTucakfITjPcLV
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Ok, so my plan was to make listwide reply-to munging go away (well, it would
still be there, but hopefully not needed in most cases/installations).

Two things were needed for that:
- no dupe patch written by Ben and already in mailman cvs thanks to Barry
- for really whiney users  who just don't want to use reply  to all to reply
  to a list  post and who are not  going to leave you alone  (kind of defies
  logic, but this is  a topic where logic does not apply),  I spent the last
  evenings writing a new setting: reply-to munging per user and per list

Per Barry's recommendation, I wrote this by  adding a flag for each user and
duping each  list message (munged  and non  munged version) and  sending the
right version to each user.
Since this adds some processing, I added an optimization to bypass this code
if no one on the list requests munging.

Munging per user is both a setting that is system wide, and if it's allowed,
it can be allowed listwide (system wide defaults to yes, list wide to no).
I've also  made normal listwide reply-to  munging a system wide  option that
can be turned off.

Note that this code is functional, but still has a couple of rough edges
1) I didn't give is  as much testing as I would have  liked (I just finished
   it and I need to get a little sleep before I go to work :-D)
2) It is missing the code to  disable split munge/no munge processing if the
   last munge user goes back to nomunge
   Actually,    I   just    thought    about   doing    this   by    setting
   mixed_reply_to_munging_users  back to  0 if  after scanning  the list  at
   sending time, we find  out that one of the two posts  isn't being sent to
   anyone.
   (And I'll also have to deal with the pathological case where all the list
   users set themselves to munging)
3) It still has some debugging code in there

I'm simply posting this right now because  I'd like to get feedback from you
and Barry on the implementation and  python details before I send a polished
patch to Barry for his consideration.

Marc
-- 
Microsoft is to operating systems & security ....
                                      .... what McDonalds is to gourmet cooking
  
Home page: http://marc.merlins.org/   |   Finger marc_f@merlins.org for PGP key

--Y7xTucakfITjPcLV
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="replyto.diff"

Binary files mailman-cvs.freeze/Mailman/Cgi/.options.py.swp and mailman-cvs.freeze.replyto/Mailman/Cgi/.options.py.swp differ
diff -urN mailman-cvs.freeze/Mailman/Cgi/admin.py mailman-cvs.freeze.replyto/Mailman/Cgi/admin.py
--- mailman-cvs.freeze/Mailman/Cgi/admin.py	Mon Mar 11 00:37:03 2002
+++ mailman-cvs.freeze.replyto/Mailman/Cgi/admin.py	Mon Mar 11 00:04:21 2002
@@ -47,7 +47,7 @@
 i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
 
 NL = '\n'
-OPTCOLUMNS = 11
+OPTCOLUMNS = 12
 
 
 
@@ -869,7 +869,7 @@
                                           _('mod'), _('hide'),
                                           _('nomail<br>[reason]'),
                                           _('ack'), _('not metoo'),
-                                          _('nodupes'),
+					  _('nodupes'), _('replyto'),
                                           _('digest'), _('plain'),
                                           _('language'))])
     rowindex = usertable.GetCurrentRowIndex()
@@ -909,7 +909,7 @@
             checked = 0
         box = CheckBox('%s_mod' % addr, value, checked)
         cells.append(Center(box).Format())
-        for opt in ('hide', 'nomail', 'ack', 'notmetoo', 'nodupes'):
+	for opt in ('hide', 'nomail', 'ack', 'notmetoo', 'nodupes', 'replyto'):
             extra = ''
             if opt == 'nomail':
                 status = mlist.getDeliveryStatus(addr)
@@ -989,6 +989,8 @@
         _('''<b>nodupes</b> -- Does the member want to avoid duplicates of the
         same message?'''))
     legend.AddItem(
+        _('''<b>replyto</b> -- Does the member want to have reply-to munged to the list address? (note that it will not be active until per_user_reply_to_allowed is enabled)'''))
+    legend.AddItem(
         _('''<b>digest</b> -- Does the member get messages in digests?
         (otherwise, individual messages)'''))
     legend.AddItem(
@@ -1337,7 +1339,8 @@
                     mlist.setDeliveryStatus(user, MemberAdaptor.BYADMIN)
             else:
                 mlist.setDeliveryStatus(user, MemberAdaptor.ENABLED)
-            for opt in ('hide', 'ack', 'notmetoo', 'nodupes', 'plain'):
+	    for opt in ('hide', 'ack', 'notmetoo', 'nodupes', 'replyto', 
+								    'plain'):
                 opt_code = option_info[opt]
                 if cgidata.has_key('%s_%s' % (user, opt)):
                     mlist.setMemberOption(user, opt_code, 1)
diff -urN mailman-cvs.freeze/Mailman/Cgi/options.py mailman-cvs.freeze.replyto/Mailman/Cgi/options.py
--- mailman-cvs.freeze/Mailman/Cgi/options.py	Tue Mar  5 22:24:49 2002
+++ mailman-cvs.freeze.replyto/Mailman/Cgi/options.py	Mon Mar 11 00:22:11 2002
@@ -425,6 +425,7 @@
                            ('remind',      mm_cfg.SuppressPasswordReminder),
                            ('rcvtopic',    mm_cfg.ReceiveNonmatchingTopics),
                            ('nodupes',     mm_cfg.DontReceiveDuplicates),
+                           ('replyto',     mm_cfg.AddListReplyTo),
                            ):
             try:
                 newval = int(cgidata.getvalue(item))
@@ -497,8 +498,7 @@
         finally:
             mlist.Unlock()
         
-        # The enable/disable option and the password remind option may have
-        # their global flags sets.
+        # Several options support having their global flags sets.
         global_enable = None
         if cgidata.getvalue('deliver-globally'):
             # Yes, this is inefficient, but the list is so small it shouldn't
@@ -605,6 +605,18 @@
         mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 1, user))
     replacements['<mm-receive-duplicates-button>'] = (
         mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 0, user))
+    # Let's not tempt the user with an option we're not giving him :) 
+    # (yes, this a _very_ sleazy hack, I know :-D) -- Marc
+    if mlist.per_user_reply_to_allowed:
+	replacements['<mm-munge-replyto-hide1>'] = ( '' )
+	replacements['<mm-munge-replyto-hide2>'] = ( '' )
+    else:
+	replacements['<mm-munge-replyto-hide1>'] = ( '<!---' )
+	replacements['<mm-munge-replyto-hide2>'] = ( '--->' )
+    replacements['<mm-munge-replyto-button>'] = (
+	mlist.FormatOptionButton(mm_cfg.AddListReplyTo, 1, user))
+    replacements['<mm-dont-munge-replyto-button>'] = (
+	mlist.FormatOptionButton(mm_cfg.AddListReplyTo, 0, user))
     replacements['<mm-unsubscribe-button>'] = (
         mlist.FormatButton('unsub', _('Unsubscribe')) + '<br>' +
         CheckBox('unsubconfirm', 1, checked=0).Format() +
diff -urN mailman-cvs.freeze/Mailman/Defaults.py.in mailman-cvs.freeze.replyto/Mailman/Defaults.py.in
--- mailman-cvs.freeze/Mailman/Defaults.py.in	Fri Mar  8 21:05:23 2002
+++ mailman-cvs.freeze.replyto/Mailman/Defaults.py.in	Sun Mar 10 18:47:30 2002
@@ -754,6 +754,33 @@
 from: .*@uplinkpro.com
 """
 
+
+# Reply-To munging should really not exist. Each user can tell mailman not
+# to send them list copies when people group reply (nodupes feature), but the
+# other reason is that some users really insist on not using reply to all, and
+# absolutely want to use their reply function to reply to the list.
+# If teaching them to use their mail client properly with the aid of a baseball
+# bat is not an option, instead of forcing reply-to munging on the whole list
+# (DEFAULT_REPLY_GOES_TO_LIST), and screwing all the users who don't want it,
+# you can allow a per user reply-to setting.
+# As soon as a list member selects this, it will cause each message to be
+# duplicated in your spool (one copy with reply-to, and one copy without), and
+# it will also force a scan of the list userlist to see which user gets which
+# message. You may notice a slowdown on lists with several thousand users.
+# List admins will be allowed to turn this on and off on a per list basis,
+# but this variable takes precedence over the listmaster(s) setting
+# Set to 1 to enable
+SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING = 1
+
+# Now, you can choose the default value for new lists (should remain '0' unless
+# you have to accomodate users who beg for the misfeature, and list server can
+# accomodate the additional load)
+DEFAULT_ALLOW_PER_USER_REPLYTO_MUNGING = 0
+
+# You can turn off the various Reply-To munging mistfeatures on a sitewide basis
+# here (the above two options should allow everyone to live without them)
+SITEWIDE_ALLOW_PER_LIST_REPLY_TO_MUNGING = 1
+
 # Mailman can be configured to "munge" Reply-To: headers for any passing
 # messages.  One the one hand, there are a lot of good reasons not to munge
 # Reply-To: but on the other, people really seem to want this feature.  See
@@ -767,7 +794,7 @@
 # Before munging Reply-To: Mailman can be configured to strip any existing
 # Reply-To: header first, or simply extend any existing Reply-To: with one
 # based on the above setting.  This is a boolean variable.
-DEFAULT_FIRST_STRIP_REPLY_TO = 1
+DEFAULT_FIRST_STRIP_REPLY_TO = 0
 
 # SUBSCRIBE POLICY
 # 0 - open list (only when ALLOW_OPEN_SUBSCRIBE is set to 1) **
@@ -1005,6 +1032,7 @@
 ReceiveNonmatchingTopics = 64
 Moderate = 128
 DontReceiveDuplicates = 256
+AddListReplyTo	    = 512
 
 # Authentication contexts.
 #
Binary files mailman-cvs.freeze/Mailman/Gui/.General.py.swp and mailman-cvs.freeze.replyto/Mailman/Gui/.General.py.swp differ
diff -urN mailman-cvs.freeze/Mailman/Gui/General.py mailman-cvs.freeze.replyto/Mailman/Gui/General.py
--- mailman-cvs.freeze/Mailman/Gui/General.py	Tue Mar  5 22:24:49 2002
+++ mailman-cvs.freeze.replyto/Mailman/Gui/General.py	Sun Mar 10 22:40:07 2002
@@ -57,7 +57,8 @@
         optvals = [mlist.new_member_options & bitfields[o] for o in OPTIONS]
         opttext = [bitdescrs[o] for o in OPTIONS]
 
-        rtn = [
+        rtn = [ ]
+	rtn.extend ( ( 
             _('''Fundamental list characteristics, including descriptive
             info and basic behaviors.'''),
 
@@ -147,9 +148,38 @@
              posted to the list, to distinguish mailing list messages in in
              mailbox summaries.  Brevity is premium here, it's ok to shorten
              long mailing list names to something more concise, as long as it
-             still identifies the mailing list.""")),
+             still identifies the mailing list.""")) 
+		) )
 
-            _('''<tt>Reply-To:</tt> header munging'''),
+        if (mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING or
+	    mm_cfg.SITEWIDE_ALLOW_PER_LIST_REPLY_TO_MUNGING ):
+	    rtn.append ( _('''<tt>Reply-To:</tt> header munging''') )
+
+
+        if (mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING ):
+	    rtn.append (
+
+            ('per_user_reply_to_allowed', mm_cfg.Radio, (_('No'), _('Yes')), 0,
+             _('''Allow users to individually set a Reply-To to the list?<BR>
+	     Note: this will create additional load, read details.'''),
+	     _("""This option allows individual users to ask the list to
+	     munge posts just for them.<BR>
+             As soon as a list member selects this, it will cause each message
+             to be duplicated in your spool (one copy with reply-to, and one
+             copy without), and it will also force a scan of the list userlist
+             to see which user gets which message. You may notice a slowdown on
+             lists with several thousand users and in this case it may be
+	     inadvisable to allow this<BR>
+	     You may also want all your users to learn to use reply to all for
+             list replies  and force  this setting off  as a  result. On the
+             flipside, it is better to enable this setting and allow a few
+	     users to munge their posts than to turn on reply-to munging for
+	     the whole list and prevent all the users from doing simple replies
+	     to sender"""))
+		)
+
+        if (mm_cfg.SITEWIDE_ALLOW_PER_LIST_REPLY_TO_MUNGING ):
+	    rtn.extend ( (
 
             ('first_strip_reply_to', mm_cfg.Radio, (_('No'), _('Yes')), 0,
              _('''Before adding a list-specific <tt>Reply-To:</tt> header,
@@ -225,7 +255,9 @@
 
              <p>Note that if the original message contains a
              <tt>Reply-To:</tt> header, it will not be changed.""")),
+		) )
 
+	rtn.extend ( (
             _('Umbrella list settings'),
 
             ('umbrella_list', mm_cfg.Radio, (_('No'), _('Yes')), 0,
@@ -350,8 +382,7 @@
              the mail host's exchanger address, if any.  This setting can be
              useful for selecting among alternative names of a host that has
              multiple addresses.""")),
-
-          ]
+		) )
 
         if mm_cfg.ALLOW_RFC2369_OVERRIDES:
             rtn.append(
diff -urN mailman-cvs.freeze/Mailman/HTMLFormatter.py mailman-cvs.freeze.replyto/Mailman/HTMLFormatter.py
--- mailman-cvs.freeze/Mailman/HTMLFormatter.py	Tue Mar  5 22:24:46 2002
+++ mailman-cvs.freeze.replyto/Mailman/HTMLFormatter.py	Sun Mar 10 18:27:27 2002
@@ -117,6 +117,7 @@
                 mm_cfg.SuppressPasswordReminder : 'remind',
                 mm_cfg.ReceiveNonmatchingTopics : 'rcvtopic',
                 mm_cfg.DontReceiveDuplicates    : 'nodupes',
+                mm_cfg.AddListReplyTo		: 'replyto',
                 }[option]
         return '<input type=radio name="%s" value="%d"%s>' % (
             name, value, checked)
diff -urN mailman-cvs.freeze/Mailman/Handlers/CookHeaders.py mailman-cvs.freeze.replyto/Mailman/Handlers/CookHeaders.py
--- mailman-cvs.freeze/Mailman/Handlers/CookHeaders.py	Fri Mar  8 21:05:25 2002
+++ mailman-cvs.freeze.replyto/Mailman/Handlers/CookHeaders.py	Mon Mar 11 00:27:35 2002
@@ -87,7 +87,10 @@
     # augment it.  RFC 2822 allows max one Reply-To: header so collapse them
     # if we're adding a value, otherwise don't touch it.  (Should we collapse
     # in all cases?)
-    if not fasttrack:
+    # Turning off Reply-To munging on a sitewide basis doesn't reset the list
+    # option (it just makes it go away from the interface), so we need to
+    # disable the behavior here -- Marc
+    if not fasttrack and mm_cfg.SITEWIDE_ALLOW_PER_LIST_REPLY_TO_MUNGING:
         # Set Reply-To: header to point back to this list
         replyto = []
         if mlist.reply_goes_to_list == 1:
diff -urN mailman-cvs.freeze/Mailman/Handlers/SMTPDirect.py mailman-cvs.freeze.replyto/Mailman/Handlers/SMTPDirect.py
--- mailman-cvs.freeze/Mailman/Handlers/SMTPDirect.py	Fri Mar  8 21:05:28 2002
+++ mailman-cvs.freeze.replyto/Mailman/Handlers/SMTPDirect.py	Mon Mar 11 00:31:06 2002
@@ -81,6 +81,28 @@
     if not recips:
         # Nobody to deliver to!
         return
+
+    # If the list has a reply-to/non reply-to split, the message gets queued
+    # twice, once with a Reply-To and once without. We need to weed out the
+    # members that don't match the current post configuration
+    # Let's only do this if we have to, if it's currently allowed by the list
+    # owner, and if it's allowed sitewide -- Marc
+    #print "Split rp status is: "+`mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING`+"/"+`mlist.per_user_reply_to_allowed`+"/"+`mlist.mixed_reply_to_munging_users`
+    if mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING and \
+	mlist.per_user_reply_to_allowed and  mlist.mixed_reply_to_munging_users:
+	mungedpost=msgdata.get('replytoadded')
+	#print "Dealing with post with reply-to status "+`mungedpost`
+	for r in recips[:]:
+	    #print "testing member "+r
+	    if (mungedpost and \
+	        not mlist.getMemberOption(r, mm_cfg.AddListReplyTo)) \
+	    or \
+	       (not mungedpost and \
+		    mlist.getMemberOption(r, mm_cfg.AddListReplyTo)):
+		#print "Removing member "+r+" for post status "+`mungedpost`
+		recips.remove(r)
+	#print "New receipient list is "+`recips`
+    
     # Calculate the non-VERP envelope sender.
     if mlist:
         envsender = mlist.getListAddress('bounces')
diff -urN mailman-cvs.freeze/Mailman/Handlers/ToOutgoing.py mailman-cvs.freeze.replyto/Mailman/Handlers/ToOutgoing.py
--- mailman-cvs.freeze/Mailman/Handlers/ToOutgoing.py	Sat Mar  9 19:25:01 2002
+++ mailman-cvs.freeze.replyto/Mailman/Handlers/ToOutgoing.py	Mon Mar 11 01:04:43 2002
@@ -24,6 +24,7 @@
 from Mailman import mm_cfg
 from Mailman.Queue.sbcache import get_switchboard
 
+COMMASPACE = ', '
 
 
 def process(mlist, msg, msgdata):
@@ -45,6 +46,29 @@
     else:
         # VERP every `inteval' number of times
         msgdata['verp'] = not int(mlist.post_id) % interval
+
     # And now drop the message in qfiles/out
     outq = get_switchboard(mm_cfg.OUTQUEUE_DIR)
+    msgdata['replytoadded']=0
+    #print "\n\nB: "+`msg`
+    #print "B: "+`msgdata`
+    # FIXME: Original message reply-to doesn't make it up to here -- Marc
     outq.enqueue(msg, msgdata, listname=mlist.internal_name())
+
+    if mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING and \
+	mlist.per_user_reply_to_allowed and  mlist.mixed_reply_to_munging_users:
+	msgdata['replytoadded']=1
+        # RFC 2822 allows Reply-To to be a list of addresses. Should a mail
+        # client not be happy with that, the user then has the option of not
+        # doing header munging in the first place and learning how to use the
+        # proper reply function of his mailer :-) -- Marc
+	replyto = []
+	replyto.append(mlist.GetListEmail())
+	if msg['reply-to']:
+	    replyto.append(msg['reply-to'])
+	    del msg['reply-to']
+	msg['Reply-To']=COMMASPACE.join(replyto)
+
+	#print "\n\nA: "+`msg`
+	#print "A: "+`msgdata`
+	outq.enqueue(msg, msgdata, listname=mlist.internal_name())
diff -urN mailman-cvs.freeze/Mailman/MailCommandHandler.py mailman-cvs.freeze.replyto/Mailman/MailCommandHandler.py
--- mailman-cvs.freeze/Mailman/MailCommandHandler.py	Tue Mar  5 22:24:48 2002
+++ mailman-cvs.freeze.replyto/Mailman/MailCommandHandler.py	Mon Mar 11 00:28:37 2002
@@ -84,6 +84,24 @@
 which have you as an explicit recipient (i.e. if you're both a member of the
 list and in either the To: or Cc: headers).""")
 
+REPLYTO = _("""
+While there are few good reasons to do this, you can ask to have list posts
+contain a reply-to pointing back to the list. It's mainly here if you really
+can't break the habit to use the reply to sender function of your mail client
+to reply to list posts. You should use the reply to all/reply to list function
+of your mail client to answer list posts (mailman is smart enough not to send
+duplicates if you reply to the list and the poster), and you can use your normal
+reply to sender function to reply just to the original post author.
+
+If this option is allowed by the list and the site owners, turning it on will
+cause list posts to contain a Reply-To: header pointing back to the list so that
+you can answer list posts with the reply function of your mail client.
+Please make note that you will then be unable to reply to the author of a
+message without typing his Email address and that many lists will not allow you
+to have a Reply-To the list, so you may be better off not changing the meaning
+of the reply function and getting used to using reply to all for lists posts
+""")
+
 option_desc = {'hide'     : HIDE,
                'nomail'   : NOMAIL,
                'ack'      : ACK,
@@ -91,6 +109,7 @@
                'digest'   : DIGEST,
                'plain'    : PLAIN,
                'nodupes'  : NODUPES,
+               'replyto'  : REPLYTO,
                }
 
 # jcrey: and then the real one
@@ -102,11 +121,20 @@
                'notmetoo': mm_cfg.DontReceiveOwnPosts,
                'digest'  : 0,
                'plain'   : mm_cfg.DisableMime,
-               'nodupes' : mm_cfg.DontReceiveDuplicates
+               'nodupes' : mm_cfg.DontReceiveDuplicates,
+               'replyto' : mm_cfg.AddListReplyTo,
                }
 
 # ordered list
-options = ('hide', 'nomail', 'ack', 'notmetoo', 'digest', 'plain', 'nodupes')
+options = ['hide', 'nomail', 'ack', 'notmetoo', 'digest', 'plain', 'nodupes']
+
+# We don't know which list the user may be on or is trying to get on, so
+# we can't check for mlist.per_user_reply_to_allowed, but we can definitely
+# check for mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING
+# The idea is not to potentially tempt the user with a feature that may not
+# be available :) -- Marc
+if mm_cfg.SITEWIDE_ALLOW_PER_USER_REPLYTO_MUNGING:
+    options.append('replyto')
 
 # strip just the outer layer of quotes
 quotecre = re.compile(r'["\'`](?P<cmd>.*)["\'`]')
diff -urN mailman-cvs.freeze/Mailman/MailList.py mailman-cvs.freeze.replyto/Mailman/MailList.py
--- mailman-cvs.freeze/Mailman/MailList.py	Tue Mar  5 22:24:48 2002
+++ mailman-cvs.freeze.replyto/Mailman/MailList.py	Sun Mar 10 16:41:56 2002
@@ -259,6 +259,13 @@
         self.usernames = {}
         self.passwords = {}
         self.new_member_options = mm_cfg.DEFAULT_NEW_MEMBER_OPTIONS
+	# if you have a least one user who wants personalized munging, each
+	# message gets dropped twice in the queue, once munged, once not.
+	# Because this requires resources, and scanning the userlist to see
+	# who gets each message requires resources too, we don't do this unless
+	# we have to (we keep track of whether we have mixed users on the list)
+	# -- Marc
+	self.mixed_reply_to_munging_users = 0
 
         # This stuff is configurable
         self.respond_to_post_requests = 1
@@ -270,6 +277,8 @@
                             % mm_cfg.DEFAULT_URL_HOST
         self.owner = [admin]
         self.moderator = []
+	self.per_user_reply_to_allowed = \
+			    mm_cfg.DEFAULT_ALLOW_PER_USER_REPLYTO_MUNGING
         self.reply_goes_to_list = mm_cfg.DEFAULT_REPLY_GOES_TO_LIST
         self.reply_to_address = ''
         self.first_strip_reply_to = mm_cfg.DEFAULT_FIRST_STRIP_REPLY_TO
diff -urN mailman-cvs.freeze/Mailman/OldStyleMemberships.py mailman-cvs.freeze.replyto/Mailman/OldStyleMemberships.py
--- mailman-cvs.freeze/Mailman/OldStyleMemberships.py	Tue Mar  5 22:24:48 2002
+++ mailman-cvs.freeze.replyto/Mailman/OldStyleMemberships.py	Mon Mar 11 00:09:20 2002
@@ -300,6 +300,19 @@
             # We don't need to touch user_options because the digest state
             # isn't kept as a bitfield flag.
             return
+
+	# We need to do special processing on reply-to in case the switch
+	# causes the first munging user to appear or the last to go away
+	# -- Marc
+        if flag == mm_cfg.AddListReplyTo:
+            if value:
+		self.__mlist.mixed_reply_to_munging_users=1
+            else:
+		# FIXME, scan list membership and see if all reply-to people
+		# are gone (this should probably be in a function) -- Marc
+		#self.__mlist.mixed_reply_to_munging_users=0
+		pass
+	    
         # This is a bit kludgey because the semantics are that if the user has
         # no options set (i.e. the value would be 0), then they have no entry
         # in the user_options dict.  We use setdefault() here, and then del
diff -urN mailman-cvs.freeze/Mailman/Version.py mailman-cvs.freeze.replyto/Mailman/Version.py
--- mailman-cvs.freeze/Mailman/Version.py	Thu Mar  7 20:32:39 2002
+++ mailman-cvs.freeze.replyto/Mailman/Version.py	Sun Mar 10 16:41:56 2002
@@ -36,7 +36,7 @@
                (REL_LEVEL << 4)  | (REL_SERIAL << 0))
 
 # config.pck schema version number
-DATA_FILE_VERSION = 64
+DATA_FILE_VERSION = 65
 
 # qfile/*.db schema version number
 QFILE_SCHEMA_VERSION = 3
diff -urN mailman-cvs.freeze/Mailman/versions.py mailman-cvs.freeze.replyto/Mailman/versions.py
--- mailman-cvs.freeze/Mailman/versions.py	Sat Mar  9 19:25:00 2002
+++ mailman-cvs.freeze.replyto/Mailman/versions.py	Sun Mar 10 17:08:25 2002
@@ -286,6 +286,8 @@
     add_only_if_missing('one_last_digest', {})
     add_only_if_missing('usernames', {})
     add_only_if_missing('personalize', 0)
+    add_only_if_missing('per_user_reply_to_allowed', \
+			 mm_cfg.DEFAULT_ALLOW_PER_USER_REPLYTO_MUNGING)
     add_only_if_missing('first_strip_reply_to',
                         mm_cfg.DEFAULT_FIRST_STRIP_REPLY_TO)
     add_only_if_missing('unsubscribe_policy',
diff -urN mailman-cvs.freeze/templates/en/help.txt mailman-cvs.freeze.replyto/templates/en/help.txt
--- mailman-cvs.freeze/templates/en/help.txt	Tue Mar  5 22:24:56 2002
+++ mailman-cvs.freeze.replyto/templates/en/help.txt	Sun Mar 10 16:41:56 2002
@@ -85,6 +85,20 @@
             Cc: fields already or are included in multiple lists in
             one message.
 
+	replyto:
+            There are few good reasons to do this. It's mainly here if you
+            really can't break the habit to use the reply to sender function of
+            your mail client to reply to list posts. You should use the reply
+            to all/reply to list function of your mail client (mailman is smart
+            enough not to send duplicates if you reply to the list and the
+            poster) to answer list posts, and reply to sender should be to
+	    reply just to the original post author.
+            When turned on however (if allowed by the list and the site owners),
+            you can ask to have list posts contain a reply-to pointing back to
+            the list so that you can answer list posts with the reply function
+            of your mail client.
+	    Please make note that this is a bad habit and that many lists will
+	    not allow you to reply to the list without replying to all
 
     options
         Show the current values of your list options.
diff -urN mailman-cvs.freeze/templates/en/options.html mailman-cvs.freeze.replyto/templates/en/options.html
--- mailman-cvs.freeze/templates/en/options.html	Tue Mar  5 22:24:56 2002
+++ mailman-cvs.freeze.replyto/templates/en/options.html	Sun Mar 10 18:18:41 2002
@@ -300,6 +300,36 @@
         <mm-global-nodupes-button><i>Set globally</i>
         </td></tr>
 
+    <mm-munge-replyto-hide1>
+    <tr><td bgcolor="#cccccc">
+        <strong>Set Reply-To back to the list?</strong><p>
+
+                There are few good reasons to do this. It's mainly here if  
+                you really can't break the habit to use the reply to sender 
+                function of your mail client to reply to list posts. You    
+                should use the reply to all/reply to list function of your  
+                mail client to answer list posts (mailman is smart enough not to
+                send duplicates if you reply to the list and the poster), and
+                you can use your normal reply to sender function to reply just
+                to the original post author.<P>
+		
+                If this option is allowed by the list and the site
+                owners, turning it on will cause list posts to contain a
+                <tt>Reply-To:</tt> header pointing back to the list so that
+                you can answer list posts with the reply function of your mail
+                client.<BR>
+                Please make note that you will then be unable to reply to the
+		author of a message without typing his Email address and that
+		many lists will not allow you to have a Reply-To the list, so
+		you may be better off not changing the meaning of the reply
+		function and getting used to using reply to all for lists posts
+
+        </td><td bgcolor="#cccccc">
+	<mm-dont-munge-replyto-button>No
+	<mm-munge-replyto-button>Yes
+        </td></tr>
+    <mm-munge-replyto-hide2>
+
     <tr><TD colspan="2">
         <center><MM-options-Submit-button></center>
         </td></tr>

--Y7xTucakfITjPcLV--