On 7/2/2013 2:37 PM, Mark Sapiro wrote:
If you raise some exception other than the Mailman.Errors exceptions
DiscardMessage, HoldMessage or RejectMessage, it will be the same as if
you didn't catch the exception, i.e., the exception will be logged in
the 'error' log with a traceback and the message will be shunted.
I can see that you don't really want that because if your ban file is
unreadable or you can't stat it for some reason, you'd be shunting every
message for a reason that has really nothing to do with processing the
message. So, I think you do want to catch the exception, log it and
return as that is the only way to continue processing messages.
Just watch your 'error' log as you'll get an entry per message if
something is wrong.
Thank you for the help. Hopefully a last question. In the
do_discard_globalban function, how can I send the discard message to
mailman list? Or should I? As it stands now, each list owner/admin
would be getting the message for their list. I am thinking that as the
site administrator and maintainer of the global ban list, I should also
get the message.
In the updated code, I did change the populating of the banlist in the
Read_GlobalBan_File function. Now, it strips and lowercases the
addresses before it checks if the address is in the banlist. Before, it
checked then populated a stripped, lowercase version. This could have
resulted in duplicates if the address in the banlist but the address
checked had a different case profile.
Thanks,
Chris
------------------------ Updated Global Ban list Custom Handler
--------------------
#!/usr/bin/env python
#
"""This is a custom handler that will check all the sender addresses of
a message against a global ban list. If any of the sender addresses are
on the global ban list, the message will get logged and discarded.
"""
import sys
import os
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import Message
from Mailman import Errors
from Mailman.i18n import _
from Mailman.Logging.Syslog import syslog
# Global variables
# Initialize the banlist
banlist = []
# Keep the Global Ban lists modification time
# set to -1 to indicate ban file hasn't been read
ban_mtime = -1
# Define ban_file
# mm_cfg.GLOBALBANLIST_FILENAME is defined in mm_cfg and should
# be the full path to the file.
ban_file = mm_cfg.GLOBALBANLIST_FILENAME
def process(mlist, msg, msgdata):
# Upstream pipeline handler marked message approved -
# respect the decision or message has 'Approved: <pwd>' header
if msgdata.get('approved'):
return
# ban_file gets its value from mm_cfg.GLOBALBANLIST_FILENAME. If
# mm_cfg.GLOBALBANLIST_FILENAME is not defined, then neither is
# ban_file, so simply return.
if not ban_file:
return
# Read in the global ban list of email addresses
if Ban_File_Changed(ban_file, ban_mtime):
# Global Ban list has changed (or ban_mtime = -1),
# read in the changes
if not Read_GlobalBan_File(ban_file):
# Problems reading the GlobalBan list
return
# Check if banlist has anything, if not, no need to go further
if not banlist:
return
# Go through possible senders. Check if any of them are
# on the global ban list
for sender in msg.get_senders():
if sender.lower() in banlist:
break
else:
# None of the sender addresses were in the global ban
# list so return and continue with the next pipeline
# handler
return
# A sender was found on the global ban list. Log it and
# discard the message notifying the list owner
if sender:
# Log banned sender to the vette log
syslog('vette', '%s is banned by the global ban list', sender)
# Perform message discard
do_discard_globalban(mlist, msg, sender)
else:
assert 0, 'Bad sender in GlobalBan.py'
# Stat the ban file to get the modification time and compare it to the
# last time the file was changed. If a changed occured, update
# ban_mtime to current change time
def Ban_File_Changed(ban_file, ban_mtime):
try:
statinfo = os.stat(ban_file)
except IOError, e:
# cannot stat the global ban list for whatever reason
# log it and continue with the next pipeline handler
syslog('error',
"Can't stat %s: %s" % (ban_file, e)
)
return False
except:
# unspecified error
# log it and continue with the next pipeline handler
syslog('error',
'ERROR: %s: %s' % (sys.exc_info()[0], sys.exc_info()[1])
)
return False
# if ban_mtime = -1, statinfo.st_mtime should always be greater, this
# is a special case for when the code is first loaded and run
if statinfo.st_mtime > ban_mtime:
# ban_file has changed or it's the special case
ban_mtime = statinfo.st_mtime
return True
# no change in ban file
return False
# Read the Global Ban file and populate the banlist.
def Read_GlobalBan_File(ban_file):
try:
with open(ban_file) as f:
for addr in f:
# strip and lowercase addr
addr = addr.lower().strip()
# if addr is not in banlist, add it - to avoid
duplicates, should not add blank addresses
if (addr) and (addr not in banlist):
banlist.append(addr)
except IOError, e:
# cannot open the global ban list for whatever reason
# log it and continue with the next pipeline handler
syslog('error',
"Can't open %s: %s" % (ban_file, e)
)
return False
except:
# unspecified error
# log it and continue with the next pipeline handler
syslog('error',
'ERROR: %s: %s' % (sys.exc_info()[0], sys.exc_info()[1])
)
return False
# success
return True
# copied almost verbatim from Mailman/Handlers/Moderate.py
def do_discard_globalban(mlist, msg, sender):
# forward auto-discards to list owners?
if mlist.forward_auto_discards:
lang = mlist.preferred_language
nmsg = Message.UserNotification(mlist.GetOwnerEmail(),
mlist.GetBouncesEmail(),
_('Global Ban List Auto-discard
notification'),
lang=lang)
nmsg.set_type('multipart/mixed')
text = MIMEText(Utils.wrap(_("""\
The sender - %(sender)s - of the attached message is on the Global Ban
list. Therefore, the message
has been automatically discarded.""")),
_charset=Utils.GetCharSet(lang))
nmsg.attach(text)
nmsg.attach(MIMEMessage(msg))
nmsg.send(mlist)
# Discard the message
raise Errors.DiscardMessage
------------------------------------------------------
Mailman-Users mailing list Mailman-Users@python.org
http://mail.python.org/mailman/listinfo/mailman-users
Mailman FAQ: http://wiki.list.org/x/AgA3
Security Policy: http://wiki.list.org/x/QIA9
Searchable Archives: http://www.mail-archive.com/mailman-users%40python.org/
Unsubscribe:
http://mail.python.org/mailman/options/mailman-users/archive%40jab.org