On 7/2/2013 12:17 PM, Mark Sapiro wrote:
On 07/02/2013 11:38 AM, Chris Nulk wrote:
I did forget about some of my other questions. I plan on writing
another custom handler for a list-specific issue. Where would I look if
I wanted to intercept messages related to subscribing, unsubscribing,
and options processing?
These are messages to the -request, -join, -subscribe, -leave and
-unsubscribe addresses and are all processed by CommandRunner. Only
IncomingRunner processes a pipeline of handlers. There is no comparable
processing or custom handler option for CommandRunner. You would have to
modify Mailman/Queue/CommandRunner.py itself.
Hmmm. I have a few lists where unsubscribes are not allowed (not my
decision). On one of them, a persistent member keeps trying to
unsubscribe. I wanted to setup an automated response and discard mechanism.
How would I tell the difference between a
subscribe message and an unsubscribe message? Also, is there a
difference if the person does the subscribing or unsubscribing via the
web? Can I trap those?
The web functions are handled by modules in Mailman/Cgi. They don't
involve qrunners at all.
I have made enough mods to Mailman. Don't want make any more if I don't
have to so I will just keep discarding the unsubscribe requests.
Below is the latest update incorporating your suggestions.
See some inline comments.
def process(mlist, msg, msgdata):
# Upstream pipeline handler marked message approved -
Or message contained an Approved: <password> header.
Yep.
# respect the decision
if msgdata.get('approved'):
return
# ban_file gets its value from mm_cfg.GLOBALBANLIST_FILENAME. If
# mm_cfg.GLOBALBANLIST_FILENAME is not defined 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_mlist):
ban_mtime, not ban_mlist.
Yeah, I fixed it after I sent the message.
# Global Ban list has changed (or ban_mlist = -1),
ban_mtime.
Same here.
# read in the changes
rc = Read_GlobalBan_File(ban_file)
if not rc:
# Problems reading the GlobalBan list
return
Or just
if not Read_GlobalBan_File(ban_file):
return
I actually had more code here. As I reduced the code, I tightened the
code. Missed this one.
# 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
Do you really want to do this? The Mailman philosophy is all caught and
handled exceptions should be explicit. An unanticipated exception will
be caught at the top qrunner level which will log the error with
traceback in the 'error' log and shunt the message rather than
continuing processing with a message that triggered an unanticipated
exception.
Instead of returning, should I raise an exception? For the IOError or
any error, whether or not the file can be read or perform a stat isn't a
big deal. I would rather log the error, clear the exception and keep
going. If there is a problem in this function, returning False just
means the ban_file hasn't changed so I will still be running sender
addresses against a potentially older banlist.
# 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:
# if addr is not in banlist, add it - to avoid duplicates
if addr not in banlist:
banlist.append(addr.lower().strip())
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
See comment above about generic exceptions.
The same applies here also. If there is a problem, the banlist doesn't
get updated.
I would rather not have the code produce a traceback for a file system
error. If for some reason, the file became unreadable, then the error
would kill Mailman repeatedly since this custom handler is going into
the global pipeline.
Can I get rid of the exception handling while still logging those errors?
Thanks,
Chris
------------------------------------------------------
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