File mailman-SuSE.patch of Package mailman.13240
--- Mailman/Cgi/admin.py
+++ Mailman/Cgi/admin.py
@@ -22,6 +22,7 @@
import sys
import os
+import string
import re
import cgi
import sha
@@ -215,6 +216,12 @@
# should have already been set.
hostname = Utils.get_domain()
legend = _('%(hostname)s mailing lists - Admin Links')
+
+ if not mm_cfg.LISTINFO_USE_CATEGORIES:
+ columns=2
+ else:
+ columns=3
+
# The html `document'
doc = Document()
doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
@@ -222,7 +229,7 @@
# The table that will hold everything
table = Table(border=0, width="100%")
table.AddRow([Center(Header(2, legend))])
- table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=columns,
bgcolor=mm_cfg.WEB_HEADER_COLOR)
# Skip any mailing list that isn't advertised.
advertised = []
@@ -231,20 +238,20 @@
for name in listnames:
mlist = MailList.MailList(name, lock=0)
- if mlist.advertised:
+ # enforce visibility for all lists
+ if mlist.advertised or not mlist.advertised:
+
if mm_cfg.VIRTUAL_HOST_OVERVIEW and \
mlist.web_page_url.find(hostname) == -1:
# List is for different identity of this host - skip it.
continue
else:
- advertised.append((mlist.GetScriptURL('admin'),
- mlist.real_name,
- mlist.description))
+ advertised.append(mlist)
# Greeting depends on whether there was an error or not
if msg:
greeting = FontAttr(msg, color="ff5060", size="+1")
else:
- greeting = _("Welcome!")
+ greeting = FontAttr(_('Welcome!'), size='+2')
welcome = []
mailmanlink = Link(mm_cfg.MAILMAN_URL, _('Mailman')).Format()
@@ -257,49 +264,100 @@
else:
welcome.extend([
greeting,
- _('''<p>Below is the collection of publicly-advertised
- %(mailmanlink)s mailing lists on %(hostname)s. Click on a list
- name to visit the configuration pages for that list.'''),
+ _('''<p>Below is the collection of all mailing lists
+ on %(hostname)s. Click on a list name to visit the configuration
+ pages for that list.'''),
])
creatorurl = Utils.ScriptURL('create')
- mailman_owner = Utils.get_site_email()
+ # mailman_owner = Utils.get_site_email()
+ mailman_owner = 'sysadmin@suse.de'
+
extra = msg and _('right ') or ''
welcome.extend([
- _('''To visit the administrators configuration page for an
- unadvertised list, open a URL similar to this one, but with a '/' and
- the %(extra)slist name appended. If you have the proper authority,
- you can also <a href="%(creatorurl)s">create a new mailing list</a>.
-
- <p>General list information can be found at '''),
+ _(''' <p>General list information can be found at '''),
Link(Utils.ScriptURL('listinfo'),
_('the mailing list overview page')),
'.',
- _('<p>(Send questions and comments to '),
+ _('<p>Send questions and comments to '),
Link('mailto:%s' % mailman_owner, mailman_owner),
- '.)<p>',
+ '.<p>',
])
table.AddRow([Container(*welcome)])
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=2)
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=columns)
if advertised:
- table.AddRow([' ', ' '])
- table.AddRow([Bold(FontAttr(_('List'), size='+2')),
- Bold(FontAttr(_('Description'), size='+2'))
- ])
- highlight = 1
- for url, real_name, description in advertised:
- table.AddRow(
- [Link(url, Bold(real_name)),
- description or Italic(_('[no description available]'))])
- if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR:
- table.AddRowInfo(table.GetCurrentRowIndex(),
- bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR)
- highlight = not highlight
+
+ if not mm_cfg.LISTINFO_USE_CATEGORIES:
+ table.AddRow([Bold(FontAttr(_('List'), size='+2')),
+ Bold(FontAttr(_('Description'), size='+2'))
+ ])
+ highlight = 1
+ for mlist in advertised:
+ table.AddRow(
+ [Link(mlist.GetScriptURL('admin'), Bold(mlist.real_name)),
+ mlist.description or Italic(_('[no description available]'))])
+ if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR:
+ table.AddRowInfo(table.GetCurrentRowIndex(),
+ bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR)
+ highlight = not highlight
+
+ else:
+ catdict = Utils.category_dictionary_for_display(advertised)
+ list_categories = catdict.keys()
+ list_categories.sort()
+
+ catdesc = Utils.CategoryDescriptions()
+ policydesc = Utils.SimplifiedPolicyDescriptions()
+
+ table.AddRow([Bold("Lists sorted by category:")])
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
+ colspan=columns, align="center")
+
+ list_links = map(lambda l: '<a href="#'+l+'">'+l+'</a>', list_categories)
+ table.AddRow([string.join(list_links, ", ")])
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
+ colspan=columns, align="center")
+
+ for cat in list_categories:
+ table.AddRow([Anchor(cat), ' '])
+ if not catdesc.has_key(cat):
+ catdesc[cat] = 'yet unclassified mailing lists'
+ table.AddRow([Bold(TextWithLegend(cat))])
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
+ colspan=columns, align="center")
+ highlight = 1
+ for mlist in catdict[cat]:
+ policy = mlist.GetSimplifiedPolicy()
+ table.AddRow(
+ [Link(mlist.GetScriptURL('admin'), Bold(mlist.real_name)),
+ mlist.description or Italic('[no description available]'),
+ TextWithLegend(policy)
+ ])
+
+ if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR:
+ table.AddRowInfo(table.GetCurrentRowIndex(),
+ bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR)
+ highlight = not highlight
doc.AddItem(table)
doc.AddItem('<hr>')
+
+ if mm_cfg.LISTINFO_USE_CATEGORIES:
+ table = Table(border=0, width="100%")
+ keys = catdesc.keys()
+ keys.sort()
+ for cat in keys:
+ table.AddRow([Anchor(cat+'desc'), Bold(cat+":"), catdesc[cat]])
+ table.AddRow([' ',' '])
+ keys = policydesc.keys()
+ keys.sort()
+ for policy in keys:
+ table.AddRow([Anchor(policy+'desc'), Bold(policy+":"), policydesc[policy]])
+ doc.AddItem(table)
+ doc.AddItem('<hr>')
+
doc.AddItem(MailmanLogo())
print doc.Format()
--- Mailman/Cgi/listinfo.py
+++ Mailman/Cgi/listinfo.py
@@ -21,6 +21,7 @@
import os
import cgi
+import string
from Mailman import mm_cfg
from Mailman import Utils
@@ -73,9 +74,14 @@
legend = _("%(hostname)s Mailing Lists")
doc.SetTitle(legend)
+ if not mm_cfg.LISTINFO_USE_CATEGORIES:
+ columns=2
+ else:
+ columns=3
+
table = Table(border=0, width="100%")
table.AddRow([Center(Header(2, legend))])
- table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=columns,
bgcolor=mm_cfg.WEB_HEADER_COLOR)
# Skip any mailing lists that isn't advertised.
@@ -85,15 +91,15 @@
for name in listnames:
mlist = MailList.MailList(name, lock=0)
- if mlist.advertised:
+ # enforce visibility for all lists
+ if mlist.advertised or not mlist.advertised:
if mm_cfg.VIRTUAL_HOST_OVERVIEW and \
mlist.web_page_url.find(hostname) == -1:
# List is for different identity of this host - skip it.
continue
else:
- advertised.append((mlist.GetScriptURL('listinfo'),
- mlist.real_name,
- mlist.description))
+ advertised.append(mlist)
+
if msg:
greeting = FontAttr(msg, color="ff5060", size="+1")
else:
@@ -107,19 +113,18 @@
%(mailmanlink)s mailing lists on %(hostname)s.'''))
else:
welcome.append(
- _('''<p>Below is a listing of all the public mailing lists on
- %(hostname)s. Click on a list name to get more information about
- the list, or to subscribe, unsubscribe, and change the preferences
+ _('''<p>Below is a listing of all mailing lists on %(hostname)s.
+ Click on a list name to get more information about the list, or
+ to subscribe, unsubscribe, and change the preferences
on your subscription.'''))
# set up some local variables
adj = msg and _('right') or ''
- siteowner = Utils.get_site_email()
+ # siteowner = Utils.get_site_email()
+ siteowner = 'sysadmin@suse.de'
+
welcome.extend(
- (_(''' To visit the general information page for an unadvertised list,
- open a URL similar to this one, but with a '/' and the %(adj)s
- list name appended.
- <p>List administrators, you can visit '''),
+ (_(''' <p>List administrators, you can visit '''),
Link(Utils.ScriptURL('admin'),
_('the list admin overview page')),
_(''' to find the management interface for your list.
@@ -128,25 +133,79 @@
'.<p>'))
table.AddRow([apply(Container, welcome)])
- table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=2)
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=columns)
if advertised:
- table.AddRow([' ', ' '])
- table.AddRow([Bold(FontAttr(_('List'), size='+2')),
- Bold(FontAttr(_('Description'), size='+2'))
- ])
- highlight = 1
- for url, real_name, description in advertised:
- table.AddRow(
- [Link(url, Bold(real_name)),
- description or Italic(_('[no description available]'))])
- if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR:
- table.AddRowInfo(table.GetCurrentRowIndex(),
- bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR)
- highlight = not highlight
+
+ if not mm_cfg.LISTINFO_USE_CATEGORIES:
+ table.AddRow([Bold(FontAttr(_('List'), size='+2')),
+ Bold(FontAttr(_('Description'), size='+2'))
+ ])
+ highlight = 1
+ for mlist in advertised:
+ table.AddRow(
+ [Link(mlist.GetScriptURL('listinfo'), Bold(mlist.real_name)),
+ mlist.description or Italic(_('[no description available]'))])
+ if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR:
+ table.AddRowInfo(table.GetCurrentRowIndex(),
+ bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR)
+ highlight = not highlight
+
+ else:
+ catdict = Utils.category_dictionary_for_display(advertised)
+ list_categories = catdict.keys()
+ list_categories.sort()
+
+ catdesc = Utils.CategoryDescriptions()
+ policydesc = Utils.SimplifiedPolicyDescriptions()
+
+ table.AddRow([Bold("Lists sorted by category:")])
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
+ colspan=columns, align="center")
+
+ list_links = map(lambda l: '<a href="#'+l+'">'+l+'</a>', list_categories)
+ table.AddRow([string.join(list_links, ", ")])
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
+ colspan=columns, align="center")
+
+ for cat in list_categories:
+ table.AddRow([Anchor(cat), ' '])
+ if not catdesc.has_key(cat):
+ catdesc[cat] = 'yet unclassified mailing lists'
+ table.AddRow([Bold(TextWithLegend(cat))])
+ table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0,
+ colspan=columns, align="center")
+ highlight = 1
+ for mlist in catdict[cat]:
+ policy = mlist.GetSimplifiedPolicy()
+ table.AddRow(
+ [Link(mlist.GetScriptURL('listinfo'), Bold(mlist.real_name)),
+ mlist.description or Italic('[no description available]'),
+ TextWithLegend(policy)
+ ])
+
+ if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR:
+ table.AddRowInfo(table.GetCurrentRowIndex(),
+ bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR)
+ highlight = not highlight
doc.AddItem(table)
doc.AddItem('<hr>')
+
+ if mm_cfg.LISTINFO_USE_CATEGORIES:
+ table = Table(border=0, width="100%")
+ keys = catdesc.keys()
+ keys.sort()
+ for cat in keys:
+ table.AddRow([Anchor(cat+'desc'), Bold(cat+":"), catdesc[cat]])
+ table.AddRow([' ',' '])
+ keys = policydesc.keys()
+ keys.sort()
+ for policy in keys:
+ table.AddRow([Anchor(policy+'desc'), Bold(policy+":"), policydesc[policy]])
+ doc.AddItem(table)
+ doc.AddItem('<hr>')
+
doc.AddItem(MailmanLogo())
print doc.Format()
--- Mailman/Commands/cmd_lists.py
+++ Mailman/Commands/cmd_lists.py
@@ -40,30 +40,6 @@
res.results.append(_('Usage:'))
res.results.append(gethelp(mlist))
return STOP
- hostname = mlist.host_name
- res.results.append(_('Public mailing lists at %(hostname)s:'))
- lists = Utils.list_names()
- lists.sort()
- i = 1
- for listname in lists:
- if listname == mlist.internal_name():
- xlist = mlist
- else:
- xlist = MailList(listname, lock=0)
- # We can mention this list if you already know about it
- if not xlist.advertised and xlist is not mlist:
- continue
- # Skip the list if it isn't in the same virtual domain. BAW: should a
- # message to the site list include everything regardless of domain?
- if mm_cfg.VIRTUAL_HOST_OVERVIEW and \
- xlist.host_name <> mlist.host_name:
- continue
- realname = xlist.real_name
- description = xlist.description or _('n/a')
- requestaddr = xlist.GetRequestEmail()
- if i > 1:
- res.results.append('')
- res.results.append(_('%(i)3d. List name: %(realname)s'))
- res.results.append(_(' Description: %(description)s'))
- res.results.append(_(' Requests to: %(requestaddr)s'))
- i += 1
+ res.results.append(_('(The list command has been disabled for this site.)'))
+ res.results.append('')
+
--- Mailman/Handlers/CookHeaders.py
+++ Mailman/Handlers/CookHeaders.py
@@ -140,8 +140,7 @@
# because some folks think that some MUAs make it easier to delete
# addresses from the right than from the left.
if mlist.reply_goes_to_list == 1:
- i18ndesc = uheader(mlist, mlist.description, 'Reply-To')
- add((str(i18ndesc), mlist.GetListEmail()))
+ add(mlist.GetListEmail())
del msg['reply-to']
# Don't put Reply-To: back if there's nothing to add!
if new:
--- Mailman/MTA/Utils.py
+++ Mailman/MTA/Utils.py
@@ -57,6 +57,7 @@
'request', 'subscribe', 'unsubscribe'):
aliases.append(('%s-%s' % (listname, ext),
'"|%s %s %s"' % (wrapper, ext, safename)))
+ aliases.append(('owner-%s' % listname, '"|%s owner %s"' % (wrapper, safename)))
return aliases
--- Mailman/MailList.py
+++ Mailman/MailList.py
@@ -31,6 +31,7 @@
import socket
import urllib
import cPickle
+import string
from cStringIO import StringIO
from UserDict import UserDict
@@ -347,7 +348,7 @@
self.header_filter_rules = []
self.anonymous_list = mm_cfg.DEFAULT_ANONYMOUS_LIST
internalname = self.internal_name()
- self.real_name = internalname[0].upper() + internalname[1:]
+ self.real_name = internalname[0] + internalname[1:]
self.description = ''
self.info = ''
self.welcome_msg = ''
@@ -1528,3 +1529,22 @@
# When testing, it's possible we've disabled a language, so just
# filter things out so we don't get tracebacks.
return [lang for lang in langs if mm_cfg.LC_DESCRIPTIONS.has_key(lang)]
+
+ def GetListCategories(self):
+ category_list = []
+ catdesc = Utils.CategoryDescriptions()
+ for category in catdesc.keys():
+ if string.find(self.info, category) >= 0:
+ category_list.append(category)
+ return category_list
+
+ def GetSimplifiedPolicy(self):
+ if string.find(self.info, '(autogenerated)') >= 0:
+ return 'essential'
+ if self.default_member_moderation and self.subscribe_policy >= 2:
+ return 'authoritative'
+ if self.subscribe_policy >= 2:
+ return 'closed'
+ return 'public'
+
+
--- Mailman/Queue/NewsRunner.py
+++ Mailman/Queue/NewsRunner.py
@@ -135,7 +135,7 @@
#
# Our Message-ID format is <mailman.secs.pid.listname@hostname>
msgid = msg['message-id']
- hackmsgid = True
+ hackmsgid = False
if msgid:
mo = mcre.search(msgid)
if mo:
--- Mailman/Utils.py
+++ Mailman/Utils.py
@@ -860,6 +860,32 @@
# Nope, it contains funny characters, so html-ref it
return uquote(s)
+
+def category_dictionary_for_display(mlists):
+ """Given a list of MailLists, return a dictionary of
+ all of the list names, keyed by category"""
+ catdict = {}
+ for mlist in mlists:
+ list_categories = mlist.GetListCategories()
+ if not list_categories:
+ list_categories = ["Unclassified"]
+ for cat in list_categories:
+ if not catdict.has_key(cat):
+ catdict[cat] = []
+ catdict[cat].append(mlist)
+ return catdict
+
+def CategoryDescriptions():
+ return {'ORG_ANNOUNCE': 'organizational announcements',\
+ 'ORG_UNIT': 'team specific organizational announcements',\
+ 'TOPIC_DISCUSS': 'topic related discussion',\
+ 'TOPIC_LEISURE': 'off-time topics (leisure)'}
+
+def SimplifiedPolicyDescriptions():
+ return {'essential': 'subscription is inevitable for the audience',\
+ 'authoritative': 'subscription needs approval, postings are moderated',\
+ 'closed': 'subscription needs approval, postings are not moderated',\
+ 'public': 'subscription is free to everybody, postings are not moderated'}
def uquote(s):
a = []
--- Mailman/htmlformat.py
+++ Mailman/htmlformat.py
@@ -688,3 +688,16 @@
text = text + spaces + opt + "\n"
return text + spaces + '</Select>'
+
+class Anchor:
+ def __init__(self, name):
+ self.name = name
+
+ def Format(self, indent=0):
+ return '<a name="%s"></a>' % (HTMLFormatObject(self.name, indent))
+
+def TextWithLegend(text):
+ def url(file):
+ return mm_cfg.IMAGE_LOGOS + file
+ return '%s <a href="#%s"><img src="%s"></a>' % (text, text+'desc', url("mm-text.png"))
+
--- bin/sync_members
+++ bin/sync_members
@@ -256,6 +256,7 @@
try:
if not dryrun:
mlist.ApprovedAddMember(userdesc, welcome, notifyadmin)
+ enc = sys.getdefaultencoding()
s = email.Utils.formataddr((name, addr)).encode(enc, 'replace')
print _('Added : %(s)s')
except Errors.MMAlreadyAMember:
@@ -276,6 +277,7 @@
# reasons is in the database. Use a lower level remove to
# get rid of this member's entry
mlist.removeMember(addr)
+ enc = sys.getdefaultencoding()
s = email.Utils.formataddr((name, addr)).encode(enc, 'replace')
print _('Removed: %(s)s')