-# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -548,7 +548,10 @@
# footer or scrubbing attachments or even reply-to munging can break these
# signatures. It is generally felt that these signatures have value, even if
# broken and even if the outgoing message is resigned. However, some sites
-# may wish to remove these headers by setting this to Yes.
+# may wish to remove these headers. Possible values and meanings are:
+# No, 0, False -> do not remove headers.
+# 1 -> remove headers only if the list's author_is_list setting is Yes.
+# Yes, 2, True -> always remove headers.
REMOVE_DKIM_HEADERS = No
# All `normal' messages which are delivered to the entire list membership go
@@ -1065,6 +1068,10 @@
# Send goodbye messages to unsubscribed members?
DEFAULT_SEND_GOODBYE_MSG = Yes
+# Rewrite the From: header of posts replacing the posters address with
+# that of the list. Also see REMOVE_DKIM_HEADERS above.
+DEFAULT_AUTHOR_IS_LIST = No
+
# Wipe sender information, and make it look like the list-admin
# address sends all messages
DEFAULT_ANONYMOUS_LIST = No
=== modified file 'Mailman/Gui/General.py'
--- Mailman/Gui/General.py 2011-10-04 21:53:13 +0000
+++ Mailman/Gui/General.py 2013-07-19 00:14:55 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 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
@@ -154,6 +154,14 @@ (listname %%05d) -> (listname 00123) """)),
+ ('author_is_list', mm_cfg.Radio, (_('No'), _('Yes')), 0,
+ _("""Replace the sender with the list address to conform with
+ policies like ADSP and DMARC. It replaces the poster's address
+ in the From: header with the list address and adds the poster to
+ the Reply-To: header, but the anonymous_list and Reply-To: header
+ munging settings below take priority. If setting this to Yes,
+ it is advised to set the MTA to DKIM sign all emails.""")),
+ ('anonymous_list', mm_cfg.Radio, (_('No'), _('Yes')), 0, _("""Hide the sender of a message, replacing it with the list address (Removes From, Sender and Reply-To fields)""")),
=== modified file 'Mailman/Handlers/Cleanse.py'
--- Mailman/Handlers/Cleanse.py 2010-04-09 20:17:07 +0000
+++ Mailman/Handlers/Cleanse.py 2013-07-19 00:18:16 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2010 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -19,7 +19,7 @@
from Mailman.Utils import unique_message_id
from Mailman.Logging.Syslog import syslog
@@ -38,6 +38,26 @@
del msg['x-approve']
# Also remove this header since it can contain a password
del msg['urgent']
+ # Do we change the from so the list takes ownership of the email
+ # This really belongs in CookHeaders.
+ if mlist.author_is_list:
+ realname, email = parseaddr(msg['from'])
+ replies = getaddresses(msg.get('reply-to', ''))
+ reply_addrs = [x[1].lower() for x in replies]
+ if reply_addrs:
+ if email.lower() not in reply_addrs:
+ rt = msg['reply-to'] + ', ' + msg['from']
+ else:
+ rt = msg['reply-to']
+ else:
+ rt = msg['from']
+ del msg['reply-to']
+ msg['Reply-To'] = rt
+ del msg['from']
+ msg['From'] = formataddr(('%s via %s' % (realname, mlist.real_name),
+ mlist.GetListEmail()))
+ del msg['sender']
+ #MAS mlist.include_sender_header = 0
# We remove other headers from anonymous lists
if mlist.anonymous_list: syslog('post', 'post to %s from %s anonymized',
=== modified file 'Mailman/Handlers/CleanseDKIM.py'
--- Mailman/Handlers/CleanseDKIM.py 2007-11-04 22:41:26 +0000
+++ Mailman/Handlers/CleanseDKIM.py 2013-07-19 00:19:21 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2007 by the Free Software Foundation, Inc.
+# Copyright (C) 2006-2013 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
@@ -29,8 +29,11 @@
def process(mlist, msg, msgdata):
- if mm_cfg.REMOVE_DKIM_HEADERS:
- del msg['domainkey-signature']
- del msg['dkim-signature']
- del msg['authentication-results']
+ if not mm_cfg.REMOVE_DKIM_HEADERS:
+ return
+ if mm_cfg.REMOVE_DKIM_HEADERS == 1 and not mlist.author_is_list:
+ return
+ del msg['domainkey-signature']
+ del msg['dkim-signature']
+ del msg['authentication-results']
=== modified file 'Mailman/Handlers/CookHeaders.py'
--- Mailman/Handlers/CookHeaders.py 2012-06-20 23:32:30 +0000
+++ Mailman/Handlers/CookHeaders.py 2013-07-19 00:12:18 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -157,9 +157,10 @@
# Cc header. BAW: should we force it into a Reply-To header in the
# above code?
# Also skip Cc if this is an anonymous list as list posting address
- # is already in From and Reply-To in this case.
+ # is already in From and Reply-To in this case and similarly for
+ # an 'author is list' list.
if mlist.personalize == 2 and mlist.reply_goes_to_list <> 1 \
- and not mlist.anonymous_list:
+ and not mlist.anonymous_list and not mlist.author_is_list:
# Watch out for existing Cc headers, merge, and remove dups. Note
# that RFC 2822 says only zero or one Cc header is allowed.
new = []
=== modified file 'Mailman/MailList.py'
--- Mailman/MailList.py 2012-06-20 23:32:30 +0000
+++ Mailman/MailList.py 2013-07-19 00:22:32 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -347,6 +347,7 @@ self.bounce_matching_headers = \ mm_cfg.DEFAULT_BOUNCE_MATCHING_HEADERS self.header_filter_rules = []
+ self.author_is_list = mm_cfg.DEFAULT_AUTHOR_IS_LIST self.anonymous_list = mm_cfg.DEFAULT_ANONYMOUS_LIST internalname = self.internal_name() self.real_name = internalname[0].upper() + internalname[1:]
=== modified file 'Mailman/Version.py'
--- Mailman/Version.py 2013-07-14 09:10:07 +0000
+++ Mailman/Version.py 2013-07-19 00:23:44 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -37,7 +37,7 @@ (REL_LEVEL << 4) | (REL_SERIAL << 0))
# config.pck schema version number
-DATA_FILE_VERSION = 100
+DATA_FILE_VERSION = 101
# qfile/*.db schema version number
QFILE_SCHEMA_VERSION = 3
=== modified file 'Mailman/versions.py'
--- Mailman/versions.py 2012-06-20 23:32:30 +0000
+++ Mailman/versions.py 2013-07-19 00:27:40 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -418,6 +418,8 @@ mm_cfg.DEFAULT_REGULAR_INCLUDE_LISTS)
add_only_if_missing('regular_exclude_ignore', mm_cfg.DEFAULT_REGULAR_EXCLUDE_IGNORE)
+ add_only_if_missing('author_is_list',
+ mm_cfg.DEFAULT_AUTHOR_IS_LIST)
=== modified file 'contrib/import_majordomo_into_mailman.pl'
--- contrib/import_majordomo_into_mailman.pl 2013-03-23 23:39:10 +0000
+++ contrib/import_majordomo_into_mailman.pl 2013-07-19 00:33:12 +0000
@@ -909,6 +909,7 @@ 'administrivia' => 'True',
'advertised' => 1, 'anonymous_list' => 'False',
+ 'author_is_list' => 'False',
# NOTE: some may wish to map some Majordomo setting, such as index_access
# to Mailman's archive. As is, all archiving is turned off for imported
# lists.
My comment is above (via email) The attached diff got stripped so I'm pasting it here in hopes it will survive:
=== modified file 'Mailman/ Defaults. py.in' Defaults. py.in 2013-05-20 15:19:19 +0000 Defaults. py.in 2013-07-19 00:16:57 +0000
--- Mailman/
+++ Mailman/
@@ -1,6 +1,6 @@
# -*- python -*-
-# Copyright (C) 1998-2012 by the Free Software Foundation, Inc. DKIM_HEADERS = No
+# Copyright (C) 1998-2013 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
@@ -548,7 +548,10 @@
# footer or scrubbing attachments or even reply-to munging can break these
# signatures. It is generally felt that these signatures have value, even if
# broken and even if the outgoing message is resigned. However, some sites
-# may wish to remove these headers by setting this to Yes.
+# may wish to remove these headers. Possible values and meanings are:
+# No, 0, False -> do not remove headers.
+# 1 -> remove headers only if the list's author_is_list setting is Yes.
+# Yes, 2, True -> always remove headers.
REMOVE_
# All `normal' messages which are delivered to the entire list membership go SEND_GOODBYE_ MSG = Yes
@@ -1065,6 +1068,10 @@
# Send goodbye messages to unsubscribed members?
DEFAULT_
+# Rewrite the From: header of posts replacing the posters address with AUTHOR_ IS_LIST = No ANONYMOUS_ LIST = No
+# that of the list. Also see REMOVE_DKIM_HEADERS above.
+DEFAULT_
+
# Wipe sender information, and make it look like the list-admin
# address sends all messages
DEFAULT_
=== modified file 'Mailman/ Gui/General. py' Gui/General. py 2011-10-04 21:53:13 +0000 Gui/General. py 2013-07-19 00:14:55 +0000
(listname %%05d) -> (listname 00123)
""")),
--- Mailman/
+++ Mailman/
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 2001-2013 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
@@ -154,6 +154,14 @@
+ ('author_is_list', mm_cfg.Radio, (_('No'), _('Yes')), 0,
( 'anonymous_ list', mm_cfg.Radio, (_('No'), _('Yes')), 0,
_("""Hide the sender of a message, replacing it with the list
address (Removes From, Sender and Reply-To fields)""")),
+ _("""Replace the sender with the list address to conform with
+ policies like ADSP and DMARC. It replaces the poster's address
+ in the From: header with the list address and adds the poster to
+ the Reply-To: header, but the anonymous_list and Reply-To: header
+ munging settings below take priority. If setting this to Yes,
+ it is advised to set the MTA to DKIM sign all emails.""")),
+
=== modified file 'Mailman/ Handlers/ Cleanse. py' Handlers/ Cleanse. py 2010-04-09 20:17:07 +0000 Handlers/ Cleanse. py 2013-07-19 00:18:16 +0000
--- Mailman/
+++ Mailman/
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2010 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -19,7 +19,7 @@
import re
-from email.Utils import formataddr
+from email.Utils import formataddr, getaddresses, parseaddr
from Mailman.Utils import unique_message_id Logging. Syslog import syslog is_list: msg['from' ]) msg.get( 'reply- to', '')) ail())) sender_ header = 0 _list:
syslog( 'post', 'post to %s from %s anonymized',
from Mailman.
@@ -38,6 +38,26 @@
del msg['x-approve']
# Also remove this header since it can contain a password
del msg['urgent']
+ # Do we change the from so the list takes ownership of the email
+ # This really belongs in CookHeaders.
+ if mlist.author_
+ realname, email = parseaddr(
+ replies = getaddresses(
+ reply_addrs = [x[1].lower() for x in replies]
+ if reply_addrs:
+ if email.lower() not in reply_addrs:
+ rt = msg['reply-to'] + ', ' + msg['from']
+ else:
+ rt = msg['reply-to']
+ else:
+ rt = msg['from']
+ del msg['reply-to']
+ msg['Reply-To'] = rt
+ del msg['from']
+ msg['From'] = formataddr(('%s via %s' % (realname, mlist.real_name),
+ mlist.GetListEm
+ del msg['sender']
+ #MAS mlist.include_
# We remove other headers from anonymous lists
if mlist.anonymous
=== modified file 'Mailman/ Handlers/ CleanseDKIM. py' Handlers/ CleanseDKIM. py 2007-11-04 22:41:26 +0000 Handlers/ CleanseDKIM. py 2013-07-19 00:19:21 +0000
--- Mailman/
+++ Mailman/
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2007 by the Free Software Foundation, Inc.
+# Copyright (C) 2006-2013 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
@@ -29,8 +29,11 @@
def process(mlist, msg, msgdata): REMOVE_ DKIM_HEADERS: signature' ] signature' ] tion-results' ] REMOVE_ DKIM_HEADERS: REMOVE_ DKIM_HEADERS == 1 and not mlist.author_ is_list: signature' ] signature' ] tion-results' ]
- if mm_cfg.
- del msg['domainkey-
- del msg['dkim-
- del msg['authentica
+ if not mm_cfg.
+ return
+ if mm_cfg.
+ return
+ del msg['domainkey-
+ del msg['dkim-
+ del msg['authentica
=== modified file 'Mailman/ Handlers/ CookHeaders. py' Handlers/ CookHeaders. py 2012-06-20 23:32:30 +0000 Handlers/ CookHeaders. py 2013-07-19 00:12:18 +0000 goes_to_ list <> 1 \ _list: _list and not mlist.author_ is_list:
--- Mailman/
+++ Mailman/
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -157,9 +157,10 @@
# Cc header. BAW: should we force it into a Reply-To header in the
# above code?
# Also skip Cc if this is an anonymous list as list posting address
- # is already in From and Reply-To in this case.
+ # is already in From and Reply-To in this case and similarly for
+ # an 'author is list' list.
if mlist.personalize == 2 and mlist.reply_
- and not mlist.anonymous
+ and not mlist.anonymous
# Watch out for existing Cc headers, merge, and remove dups. Note
# that RFC 2822 says only zero or one Cc header is allowed.
new = []
=== modified file 'Mailman/ MailList. py'
self. bounce_ matching_ headers = \
mm_cfg. DEFAULT_ BOUNCE_ MATCHING_ HEADERS
self. header_ filter_ rules = [] DEFAULT_ AUTHOR_ IS_LIST
self. anonymous_ list = mm_cfg. DEFAULT_ ANONYMOUS_ LIST
internalname = self.internal_ name()
self. real_name = internalname[ 0].upper( ) + internalname[1:]
--- Mailman/MailList.py 2012-06-20 23:32:30 +0000
+++ Mailman/MailList.py 2013-07-19 00:22:32 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2012 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -347,6 +347,7 @@
+ self.author_is_list = mm_cfg.
=== modified file 'Mailman/ Version. py'
(REL_ LEVEL << 4) | (REL_SERIAL << 0))
--- Mailman/Version.py 2013-07-14 09:10:07 +0000
+++ Mailman/Version.py 2013-07-19 00:23:44 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -37,7 +37,7 @@
# config.pck schema version number
-DATA_FILE_VERSION = 100
+DATA_FILE_VERSION = 101
# qfile/*.db schema version number SCHEMA_ VERSION = 3
QFILE_
=== modified file 'Mailman/ versions. py'
mm_ cfg.DEFAULT_ REGULAR_ INCLUDE_ LISTS) only_if_ missing( 'regular_ exclude_ ignore' ,
mm_ cfg.DEFAULT_ REGULAR_ EXCLUDE_ IGNORE) if_missing( 'author_ is_list' , DEFAULT_ AUTHOR_ IS_LIST)
--- Mailman/versions.py 2012-06-20 23:32:30 +0000
+++ Mailman/versions.py 2013-07-19 00:27:40 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2013 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
@@ -418,6 +418,8 @@
add_
+ add_only_
+ mm_cfg.
=== modified file 'contrib/ import_ majordomo_ into_mailman. pl' import_ majordomo_ into_mailman. pl 2013-03-23 23:39:10 +0000 import_ majordomo_ into_mailman. pl 2013-07-19 00:33:12 +0000
'administrivia' => 'True',
'anonymous_ list' => 'False',
--- contrib/
+++ contrib/
@@ -909,6 +909,7 @@
'advertised' => 1,
+ 'author_is_list' => 'False',
# NOTE: some may wish to map some Majordomo setting, such as index_access
# to Mailman's archive. As is, all archiving is turned off for imported
# lists.
=== modified file 'contrib/ majordomo2mailm an.pl' majordomo2mailm an.pl 2003-01-02 05:25:50 +0000 majordomo2mailm an.pl 2013-07-19 00:38:04 +0000 num_recipients' , "10", _posters' , "[]", matching_ headers' , "\"\"\"\n\"\"\"\n", _list', "0", able', "1",
--- contrib/
+++ contrib/
@@ -480,6 +480,7 @@
'max_
'forbidden
'bounce_
+ 'author_is_list', "0",
'anonymous
'nondigest
'digestable', "1",