[Mailman-Developers] Admin-controlled rejection text...
Brad Knowles
brad at stop.mail-abuse.org
Thu Jan 20 15:56:18 CET 2005
Folks,
I've been doing a bit of hacking on Mailman. The issue is that
if you set member_moderation_action to be Reject instead of Hold, you
can supply a nice little bit of text in member_moderation_notice, or
you can let the system supply a standard text for you.
My problem is that I want to leave member_moderation_action set
to Hold, and set the generic_nonmember_action to be Reject, but still
supply my own text.
Let's look at how these two are handled differently. First,
member_moderation_action, has the following lines in
Mailman/Handlers/Moderate.py, starting at line 59:
if mlist.getMemberOption(sender, mm_cfg.Moderate):
# Note that for member_moderation_action, 0==Hold, 1=Reject,
# 2==Discard
if mlist.member_moderation_action == 0:
# Hold. BAW: WIBNI we could add the member_moderation_notice
# to the notice sent back to the sender?
msgdata['sender'] = sender
Hold.hold_for_approval(mlist, msg, msgdata,
ModeratedMemberPost)
elif mlist.member_moderation_action == 1:
# Reject
text = mlist.member_moderation_notice
if text:
text = Utils.wrap(text)
else:
# Use the default RejectMessage notice string
text = None
raise Errors.RejectMessage, text
elif mlist.member_moderation_action == 2:
# Discard. BAW: Again, it would be nice if we could send a
# discard notice to the sender
raise Errors.DiscardMessage
else:
assert 0, 'bad member_moderation_action'
# Should we do anything explict to mark this message as getting past
# this point? No, because further pipeline handlers will need to do
# their own thing.
Okay, I don't know Python, but I can kinda follow that. Notice
how the value of "text" is modified depending on whether or not
member_moderation_notice is empty or not, and how this code directly
raises the error instead of calling a subroutine.
Now, let's consider what happens with generic_nonmember_action.
We have the following lines in Mailman/Handlers/Moderate.py, starting
at line 101:
# Okay, so the sender wasn't specified explicitly by any of the non-member
# moderation configuration variables. Handle by way of generic non-member
# action.
assert 0 <= mlist.generic_nonmember_action <= 4
if mlist.generic_nonmember_action == 0:
# Accept
return
elif mlist.generic_nonmember_action == 1:
Hold.hold_for_approval(mlist, msg, msgdata, Hold.NonMemberPost)
elif mlist.generic_nonmember_action == 2:
do_reject(mlist)
elif mlist.generic_nonmember_action == 3:
do_discard(mlist, msg)
Note how this does very little other than decide which subroutine
to call, then call it. No check is made for
member_moderation_notice, nor is any specific rejection text
supplied. Let's take a look at do_reject(), starting at line 136:
def do_reject(mlist):
listowner = mlist.GetOwnerEmail()
raise Errors.RejectMessage, Utils.wrap(_("""\
You are not allowed to post to this mailing list, and your message has been
automatically rejected. If you think that your messages are being rejected in
error, contact the mailing list owner at %(listowner)s."""))
This creates a hard-coded message with a %()s substitution, and
sends that out.
Now, am I missing something here, or should we not be calling
do_reject() in each of these cases and having just the one canonical
"raise Errors.RejectMessage", and passing this routine a string to be
used as the rejection notice, or allowing it to decide to fill one in
for us in the case that we provide "None"?
Okay, so I modified do_reject to at least check the value of
member_moderation_notice and to use that text, if it is non-empty.
Here's what I've now got:
def do_reject(mlist):
listowner = mlist.GetOwnerEmail()
text = mlist.member_moderation_notice
if text:
text = Utils.wrap(text)
else:
# Use the default RejectMessage notice string
text = Utils.wrap(_("""\
You are not allowed to post to this mailing list, and your message has been
automatically rejected. If you think that your messages are being rejected in
error, contact the mailing list owner at %(listowner)s."""))
# Reject this sucker
raise Errors.RejectMessage, text
This works. Well, mostly. I'd be submitting this as a patch and
working on getting this put into production, if it worked completely.
I know that what we should really have is a separate
generic_nonmember_notice and have the routine check that instead, but
I would be willing to take this as a small but significant
improvement in the meanwhile.
Problem is, while we can provide a %()s substitution ourselves in
the text we feed to Utils.wrap, I can't do the same thing from
member_moderation_notice. Instead, it simply outputs the literal
string, and gives me "<" and ">" as opposed to the real
less-than/greater-than symbols that I want to use around the URLs.
I'm stumped. I don't even know what to search for in the
archives of the mailman-users and mailman-developers lists.
Can anyone here lend me a clue?
--
Brad Knowles, <brad at stop.mail-abuse.org>
"Those who would give up essential Liberty, to purchase a little
temporary Safety, deserve neither Liberty nor Safety."
-- Benjamin Franklin (1706-1790), reply of the Pennsylvania
Assembly to the Governor, November 11, 1755
SAGE member since 1995. See <http://www.sage.org/> for more info.
More information about the Mailman-Developers
mailing list