[Mailman-Users] multiple footers accumulating on messages asdiscussion progresses - how to eliminate all but the last mailman footer?

Mark Sapiro mark at msapiro.net
Fri Apr 20 01:40:27 CEST 2012

David <dave at fiteyes.com> wrote:

>I'm not sure what you call the long tail of footers that accumulates on
>messages, but I would like to eliminate all prior footers (from the same
>list). When the new reply goes out, it should include only one footer. BTW,
>we're using full personalization and one link in the footer is like this:
>We could wrap the footer in a tag of some type if that would help. Any
>suggestions? I would think this is a common request, but I can't find any
>mention of it anywhere.

The short answer is train your users to not top-post and to quote

Given that that is impossible, doing this would be best accomplished
with a custom handler. See the FAQ at <http://wiki.list.org/x/l4A9>
for information on installing custom handlers.

You could implement a handler that does something along the lines of
the following. It's tricky because the footer may be quoted and we
don't know what the quote characters are. It's even trickier if the
list allows HTML alternatives, and trickier still because of
personalized replacements. A basic idea is:

def process(mlist, msg, msgdata):
    for part in msg.walk():
        if part.get_content_maintype == 'text':
            clean_footers(mlist, part)

def clean_footers(mlist, part):
    txt = part.get_payload(decode=True)
    newtxt = []
    changed = False
    for bodyline in txt.splitlines(keepends=True):
        for footline in mlist.msg_footer.splitlines():
            footline = footline.strip()
            if not footline:
        if bodyline.find(footline) >= 0:
            changed = True
    if changed:

What this will essentially do is remove from all text parts every line
that contains as a substring any non-empty line of the list's
msg_footer, but it doesn't handle replacements, and HTML makes it
tricky because there may be added HTML tags that would cause the
'find' to fail, and there may be non-footer text on the same HTML
source line as footer text.

To do replacements, instead of

        for footline in mlist.msg_footer.splitlines():

you'd need something like:

        d = SafeDict({})
        for user in msg.get_senders():
            if mlist.is_member(user):
                d['user_optionsurl'] = mlist.GetOptionsURL(user)
        d.update({'real_name'     : mlist.real_name,
                  'list_name'     : mlist.internal_name(),
                  # For backwards compatibility
                  '_internal_name': mlist.internal_name(),
                  'host_name'     : mlist.host_name,
                  'web_page_url'  : mlist.web_page_url,
                  'description'   : mlist.description,
                  'info'          : mlist.info,
                  'cgiext'        : mm_cfg.CGIEXT,
        footlines = mlist.msg_footer % d
        for footline in footlines:


from Mailman import mm_cfg
from Mailman.SafeDict import SafeDict

at the beginning of the module.

Mark Sapiro <mark at msapiro.net>        The highway is for gamblers,
San Francisco Bay Area, California    better use your sense - B. Dylan

More information about the Mailman-Users mailing list