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

Reply via email to