"""Produce and handle the member options."""
import sys
import os
import cgi
import signal
import urllib
from types import ListType
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import MailList
from Mailman import Errors
from Mailman import MemberAdaptor
from Mailman import i18n
from Mailman.htmlformat import *
from Mailman.Logging.Syslog import syslog
SLASH = '/'
SETLANGUAGE = -1
_ = i18n._
i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
try:
True, False
except NameError:
True = 1
False = 0
def main():
doc = Document()
doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
parts = Utils.GetPathPieces()
lenparts = parts and len(parts)
if not parts or lenparts < 1:
title = _('CGI script error')
doc.SetTitle(title)
doc.AddItem(Header(2, title))
doc.addError(_('Invalid options to CGI script.'))
doc.AddItem('<hr>')
doc.AddItem(MailmanLogo())
print doc.Format()
return
listname = parts[0].lower()
try:
mlist = MailList.MailList(listname, lock=0)
except Errors.MMListError, e:
safelistname = Utils.websafe(listname)
title = _('CGI script error')
doc.SetTitle(title)
doc.AddItem(Header(2, title))
doc.addError(_('No such list <em>%(safelistname)s</em>'))
doc.AddItem('<hr>')
doc.AddItem(MailmanLogo())
print doc.Format()
syslog('error', 'No such list "%s": %s\n', listname, e)
return
cgidata = cgi.FieldStorage(keep_blank_values=1)
language = cgidata.getvalue('language')
if not Utils.IsLanguage(language):
language = mlist.preferred_language
i18n.set_language(language)
doc.set_language(language)
if lenparts < 2:
user = cgidata.getvalue('email')
if not user:
if not cgidata.getvalue('UserOptions'):
doc.addError(_('No address given'))
loginpage(mlist, doc, None, language)
print doc.Format()
return
else:
user = Utils.LCDomain(Utils.UnobscureEmail(SLASH.join(parts[1:])))
safeuser = Utils.websafe(user)
try:
Utils.ValidateEmail(user)
except Errors.EmailAddressError:
doc.addError(_('Illegal Email Address: %(safeuser)s'))
loginpage(mlist, doc, None, language)
print doc.Format()
return
if not mlist.isMember(user) and mlist.private_roster == 0:
doc.addError(_('No such member: %(safeuser)s.'))
loginpage(mlist, doc, None, language)
print doc.Format()
return
lcuser = user.lower()
try:
cpuser = mlist.getMemberCPAddress(lcuser)
except Errors.NotAMemberError:
cpuser = None
if lcuser == cpuser:
cpuser = None
userlang = cgidata.getvalue('language')
if not Utils.IsLanguage(userlang):
userlang = mlist.getMemberLanguage(user)
doc.set_language(userlang)
i18n.set_language(userlang)
varhelp = None
if cgidata.has_key('VARHELP'):
varhelp = cgidata['VARHELP'].value
elif os.environ.get('QUERY_STRING'):
qs = cgi.parse_qs(os.environ['QUERY_STRING']).get('VARHELP')
if qs and type(qs) == types.ListType:
varhelp = qs[0]
if varhelp:
topic_details(mlist, doc, user, cpuser, userlang, varhelp)
return
if cgidata.has_key('login-unsub'):
if mlist.isMember(user):
try:
mlist.Lock()
if mlist.unsubscribe_policy:
mlist.HoldUnsubscription(user)
doc.addError(_("""Your unsubscription request has been
forwarded to the list administrator for approval."""),
tag='')
else:
mlist.ConfirmUnsubscription(user, userlang)
doc.addError(_('The confirmation email has been sent.'),
tag='')
mlist.Save()
finally:
mlist.Unlock()
else:
if mlist.private_roster == 0:
doc.addError(_('No such member: %(safeuser)s.'))
else:
syslog('mischief',
'Unsub attempt of non-member w/ private rosters: %s',
user)
doc.addError(_('The confirmation email has been sent.'),
tag='')
loginpage(mlist, doc, user, language)
print doc.Format()
return
if cgidata.has_key('login-remind'):
if mlist.isMember(user):
mlist.MailUserPassword(user)
doc.addError(
_('A reminder of your password has been emailed to you.'),
tag='')
else:
if mlist.private_roster == 0:
doc.addError(_('No such member: %(safeuser)s.'))
else:
syslog('mischief',
'Reminder attempt of non-member w/ private rosters: %s',
user)
doc.addError(
_('A reminder of your password has been emailed to you.'),
tag='')
loginpage(mlist, doc, user, language)
print doc.Format()
return
password = cgidata.getvalue('password', '').strip()
if mm_cfg.ALLOW_SITE_ADMIN_COOKIES:
user_or_siteadmin_context = (mm_cfg.AuthUser, mm_cfg.AuthSiteAdmin)
else:
user_or_siteadmin_context = (mm_cfg.AuthUser,)
is_user_or_siteadmin = mlist.WebAuthenticate(
user_or_siteadmin_context, password, user)
if not is_user_or_siteadmin and \
not mlist.WebAuthenticate((mm_cfg.AuthListAdmin,
mm_cfg.AuthSiteAdmin),
password, user):
if cgidata.has_key('password'):
doc.addError(_('Authentication failed.'))
if mlist.private_roster <> 0:
syslog('mischief',
'Login failure with private rosters: %s',
user)
user = None
loginpage(mlist, doc, user, language)
print doc.Format()
return
if cgidata.has_key('logout'):
print mlist.ZapCookie(mm_cfg.AuthUser, user)
loginpage(mlist, doc, user, language)
print doc.Format()
return
if cgidata.has_key('emailpw'):
mlist.MailUserPassword(user)
options_page(
mlist, doc, user, cpuser, userlang,
_('A reminder of your password has been emailed to you.'))
print doc.Format()
return
if cgidata.has_key('othersubs'):
if not is_user_or_siteadmin:
doc.addError(_("""The list administrator may not view the other
subscriptions for this user."""), _('Note: '))
options_page(mlist, doc, user, cpuser, userlang)
print doc.Format()
return
hostname = mlist.host_name
title = _('List subscriptions for %(safeuser)s on %(hostname)s')
doc.SetTitle(title)
doc.AddItem(Header(2, title))
doc.AddItem(_('''Click on a link to visit your options page for the
requested mailing list.'''))
onlists = []
for gmlist in lists_of_member(mlist, user) + [mlist]:
url = gmlist.GetOptionsURL(user)
link = Link(url, gmlist.real_name)
onlists.append((gmlist.real_name, link))
onlists.sort()
items = OrderedList(*[link for name, link in onlists])
doc.AddItem(items)
print doc.Format()
return
if cgidata.has_key('change-of-address'):
membername = cgidata.getvalue('fullname')
membername = Utils.canonstr(membername, language)
newaddr = cgidata.getvalue('new-address')
confirmaddr = cgidata.getvalue('confirm-address')
oldname = mlist.getMemberName(user)
set_address = set_membername = 0
globally = cgidata.getvalue('changeaddr-globally')
if globally and not is_user_or_siteadmin:
doc.addError(_("""The list administrator may not change the names
or addresses for this user's other subscriptions. However, the
subscription for this mailing list has been changed."""),
_('Note: '))
globally = False
if membername and membername <> oldname:
set_membername = 1
if not membername and oldname:
set_membername = 1
msg = ''
if newaddr and confirmaddr:
if newaddr <> confirmaddr:
options_page(mlist, doc, user, cpuser, userlang,
_('Addresses did not match!'))
print doc.Format()
return
if newaddr == cpuser:
options_page(mlist, doc, user, cpuser, userlang,
_('You are already using that email address'))
print doc.Format()
return
if mlist.isMember(newaddr):
safenewaddr = Utils.websafe(newaddr)
if globally:
listname = mlist.real_name
msg += _("""\
The new address you requested %(newaddr)s is already a member of the
%(listname)s mailing list, however you have also requested a global change of
address. Upon confirmation, any other mailing list containing the address
%(safeuser)s will be changed. """)
else:
options_page(
mlist, doc, user, cpuser, userlang,
_('The new address is already a member: %(newaddr)s'))
print doc.Format()
return
set_address = 1
elif (newaddr or confirmaddr) and not set_membername:
options_page(mlist, doc, user, cpuser, userlang,
_('Addresses may not be blank'))
print doc.Format()
return
def sigterm_handler(signum, frame, mlist=mlist):
mlist.Unlock()
sys.exit(0)
signal.signal(signal.SIGTERM, sigterm_handler)
if set_address:
if cpuser is None:
cpuser = user
msg += _('A confirmation message has been sent to %(newaddr)s. ')
mlist.Lock()
try:
try:
mlist.ChangeMemberAddress(cpuser, newaddr, globally)
mlist.Save()
finally:
mlist.Unlock()
except Errors.MMBadEmailError:
msg = _('Bad email address provided')
except Errors.MMHostileAddress:
msg = _('Illegal email address provided')
except Errors.MMAlreadyAMember:
msg = _('%(newaddr)s is already a member of the list.')
except Errors.MembershipIsBanned:
owneraddr = mlist.GetOwnerEmail()
msg = _("""%(newaddr)s is banned from this list. If you
think this restriction is erroneous, please contact
the list owners at %(owneraddr)s.""")
if set_membername:
mlist.Lock()
try:
mlist.ChangeMemberName(user, membername, globally)
mlist.Save()
finally:
mlist.Unlock()
msg += _('Member name successfully changed. ')
options_page(mlist, doc, user, cpuser, userlang, msg)
print doc.Format()
return
if cgidata.has_key('changepw'):
newpw = cgidata.getvalue('newpw')
confirmpw = cgidata.getvalue('confpw')
if not newpw or not confirmpw:
options_page(mlist, doc, user, cpuser, userlang,
_('Passwords may not be blank'))
print doc.Format()
return
if newpw <> confirmpw:
options_page(mlist, doc, user, cpuser, userlang,
_('Passwords did not match!'))
print doc.Format()
return
pw_globally = cgidata.getvalue('pw-globally')
if pw_globally and not is_user_or_siteadmin:
doc.addError(_("""The list administrator may not change the
password for this user's other subscriptions. However, the
password for this mailing list has been changed."""),
_('Note: '))
pw_globally = False
mlists = [mlist]
if pw_globally:
mlists.extend(lists_of_member(mlist, user))
for gmlist in mlists:
change_password(gmlist, user, newpw, confirmpw)
print mlist.MakeCookie(mm_cfg.AuthUser, user)
options_page(mlist, doc, user, cpuser, userlang,
_('Password successfully changed.'))
print doc.Format()
return
if cgidata.has_key('unsub'):
if not cgidata.getvalue('unsubconfirm'):
options_page(
mlist, doc, user, cpuser, userlang,
_('''You must confirm your unsubscription request by turning
on the checkbox below the <em>Unsubscribe</em> button. You
have not been unsubscribed!'''))
print doc.Format()
return
def sigterm_handler(signum, frame, mlist=mlist):
mlist.Unlock()
sys.exit(0)
signal.signal(signal.SIGTERM, sigterm_handler)
mlist.Lock()
needapproval = False
try:
try:
mlist.DeleteMember(
user, 'via the member options page', userack=1)
except Errors.MMNeedApproval:
needapproval = True
mlist.Save()
finally:
mlist.Unlock()
fqdn_listname = mlist.GetListEmail()
owneraddr = mlist.GetOwnerEmail()
url = mlist.GetScriptURL('listinfo', absolute=1)
title = _('Unsubscription results')
doc.SetTitle(title)
doc.AddItem(Header(2, title))
if needapproval:
doc.AddItem(_("""Your unsubscription request has been received and
forwarded on to the list moderators for approval. You will
receive notification once the list moderators have made their
decision."""))
else:
doc.AddItem(_("""You have been successfully unsubscribed from the
mailing list %(fqdn_listname)s. If you were receiving digest
deliveries you may get one more digest. If you have any questions
about your unsubscription, please contact the list owners at
%(owneraddr)s."""))
doc.AddItem(mlist.GetMailmanFooter())
print doc.Format()
return
if cgidata.has_key('options-submit'):
digestwarn = 0
cantdigest = 0
mustdigest = 0
newvals = []
for item, flag in (('digest', mm_cfg.Digests),
('mime', mm_cfg.DisableMime),
('dontreceive', mm_cfg.DontReceiveOwnPosts),
('ackposts', mm_cfg.AcknowledgePosts),
('disablemail', mm_cfg.DisableDelivery),
('conceal', mm_cfg.ConcealSubscription),
('remind', mm_cfg.SuppressPasswordReminder),
('rcvtopic', mm_cfg.ReceiveNonmatchingTopics),
('nodupes', mm_cfg.DontReceiveDuplicates),
):
try:
newval = int(cgidata.getvalue(item))
except (TypeError, ValueError):
newval = None
if newval is None:
continue
elif flag == mm_cfg.DisableDelivery:
status = mlist.getDeliveryStatus(user)
if not newval and status <> MemberAdaptor.ENABLED:
newval = MemberAdaptor.ENABLED
elif newval and status == MemberAdaptor.ENABLED:
newval = MemberAdaptor.BYUSER
else:
continue
elif newval == mlist.getMemberOption(user, flag):
continue
if flag == mm_cfg.Digests and \
newval == 0 and mlist.getMemberOption(user, flag):
digestwarn = 1
newvals.append((flag, newval))
if userlang not in mlist.GetAvailableLanguages():
newvals.append((SETLANGUAGE, mlist.preferred_language))
else:
newvals.append((SETLANGUAGE, userlang))
topicnames = cgidata.getvalue('usertopic')
if topicnames:
if not isinstance(topicnames, ListType):
topicnames = [topicnames]
topicnames = [urllib.unquote_plus(n) for n in topicnames]
def sigterm_handler(signum, frame, mlist=mlist):
mlist.Unlock()
sys.exit(0)
mlist.Lock()
try:
signal.signal(signal.SIGTERM, sigterm_handler)
for flag, newval in newvals:
if flag == SETLANGUAGE:
mlist.setMemberLanguage(user, newval)
elif flag == mm_cfg.DisableDelivery:
mlist.setDeliveryStatus(user, newval)
else:
try:
mlist.setMemberOption(user, flag, newval)
except Errors.CantDigestError:
cantdigest = 1
except Errors.MustDigestError:
mustdigest = 1
mlist.setMemberTopics(user, topicnames)
mlist.Save()
finally:
mlist.Unlock()
class Global:
enable = None
remind = None
nodupes = None
mime = None
def __nonzero__(self):
return len(self.__dict__.keys()) > 0
globalopts = Global()
if cgidata.getvalue('deliver-globally'):
for flag, newval in newvals:
if flag == mm_cfg.DisableDelivery:
globalopts.enable = newval
break
if cgidata.getvalue('remind-globally'):
for flag, newval in newvals:
if flag == mm_cfg.SuppressPasswordReminder:
globalopts.remind = newval
break
if cgidata.getvalue('nodupes-globally'):
for flag, newval in newvals:
if flag == mm_cfg.DontReceiveDuplicates:
globalopts.nodupes = newval
break
if cgidata.getvalue('mime-globally'):
for flag, newval in newvals:
if flag == mm_cfg.DisableMime:
globalopts.mime = newval
break
if globalopts:
if not is_user_or_siteadmin:
doc.addError(_("""The list administrator may not change the
options for this user's other subscriptions. However the
options for this mailing list subscription has been
changed."""), _('Note: '))
else:
for gmlist in lists_of_member(mlist, user):
global_options(gmlist, user, globalopts)
if cantdigest:
msg = _('''The list administrator has disabled digest delivery for
this list, so your delivery option has not been set. However your
other options have been set successfully.''')
elif mustdigest:
msg = _('''The list administrator has disabled non-digest delivery
for this list, so your delivery option has not been set. However
your other options have been set successfully.''')
else:
msg = _('You have successfully set your options.')
if digestwarn:
msg += _('You may get one last digest.')
options_page(mlist, doc, user, cpuser, userlang, msg)
print doc.Format()
return
if mlist.isMember(user):
options_page(mlist, doc, user, cpuser, userlang)
else:
loginpage(mlist, doc, user, userlang)
print doc.Format()
def options_page(mlist, doc, user, cpuser, userlang, message=''):
doc.suppress_head = 1
if mlist.obscure_addresses:
presentable_user = Utils.ObscureEmail(user, for_text=1)
if cpuser is not None:
cpuser = Utils.ObscureEmail(cpuser, for_text=1)
else:
presentable_user = user
fullname = Utils.uncanonstr(mlist.getMemberName(user), userlang)
if fullname:
presentable_user += ', %s' % Utils.websafe(fullname)
replacements = mlist.GetStandardReplacements(userlang)
replacements['<mm-results>'] = Bold(FontSize('+1', message)).Format()
replacements['<mm-digest-radio-button>'] = mlist.FormatOptionButton(
mm_cfg.Digests, 1, user)
replacements['<mm-undigest-radio-button>'] = mlist.FormatOptionButton(
mm_cfg.Digests, 0, user)
replacements['<mm-plain-digests-button>'] = mlist.FormatOptionButton(
mm_cfg.DisableMime, 1, user)
replacements['<mm-mime-digests-button>'] = mlist.FormatOptionButton(
mm_cfg.DisableMime, 0, user)
replacements['<mm-global-mime-button>'] = (
CheckBox('mime-globally', 1, checked=0).Format())
replacements['<mm-delivery-enable-button>'] = mlist.FormatOptionButton(
mm_cfg.DisableDelivery, 0, user)
replacements['<mm-delivery-disable-button>'] = mlist.FormatOptionButton(
mm_cfg.DisableDelivery, 1, user)
replacements['<mm-disabled-notice>'] = mlist.FormatDisabledNotice(user)
replacements['<mm-dont-ack-posts-button>'] = mlist.FormatOptionButton(
mm_cfg.AcknowledgePosts, 0, user)
replacements['<mm-ack-posts-button>'] = mlist.FormatOptionButton(
mm_cfg.AcknowledgePosts, 1, user)
replacements['<mm-receive-own-mail-button>'] = mlist.FormatOptionButton(
mm_cfg.DontReceiveOwnPosts, 0, user)
replacements['<mm-dont-receive-own-mail-button>'] = (
mlist.FormatOptionButton(mm_cfg.DontReceiveOwnPosts, 1, user))
replacements['<mm-dont-get-password-reminder-button>'] = (
mlist.FormatOptionButton(mm_cfg.SuppressPasswordReminder, 1, user))
replacements['<mm-get-password-reminder-button>'] = (
mlist.FormatOptionButton(mm_cfg.SuppressPasswordReminder, 0, user))
replacements['<mm-public-subscription-button>'] = (
mlist.FormatOptionButton(mm_cfg.ConcealSubscription, 0, user))
replacements['<mm-hide-subscription-button>'] = mlist.FormatOptionButton(
mm_cfg.ConcealSubscription, 1, user)
replacements['<mm-dont-receive-duplicates-button>'] = (
mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 1, user))
replacements['<mm-receive-duplicates-button>'] = (
mlist.FormatOptionButton(mm_cfg.DontReceiveDuplicates, 0, user))
replacements['<mm-unsubscribe-button>'] = (
mlist.FormatButton('unsub', _('Unsubscribe')) + '<br>' +
CheckBox('unsubconfirm', 1, checked=0).Format() +
_('<em>Yes, I really want to unsubscribe</em>'))
replacements['<mm-new-pass-box>'] = mlist.FormatSecureBox('newpw')
replacements['<mm-confirm-pass-box>'] = mlist.FormatSecureBox('confpw')
replacements['<mm-change-pass-button>'] = (
mlist.FormatButton('changepw', _("Change My Password")))
replacements['<mm-other-subscriptions-submit>'] = (
mlist.FormatButton('othersubs',
_('List my other subscriptions')))
replacements['<mm-form-start>'] = (
mlist.FormatFormStart('options', user))
replacements['<mm-user>'] = user
replacements['<mm-presentable-user>'] = presentable_user
replacements['<mm-email-my-pw>'] = mlist.FormatButton(
'emailpw', (_('Email My Password To Me')))
replacements['<mm-umbrella-notice>'] = (
mlist.FormatUmbrellaNotice(user, _("password")))
replacements['<mm-logout-button>'] = (
mlist.FormatButton('logout', _('Log out')))
replacements['<mm-options-submit-button>'] = mlist.FormatButton(
'options-submit', _('Submit My Changes'))
replacements['<mm-global-pw-changes-button>'] = (
CheckBox('pw-globally', 1, checked=0).Format())
replacements['<mm-global-deliver-button>'] = (
CheckBox('deliver-globally', 1, checked=0).Format())
replacements['<mm-global-remind-button>'] = (
CheckBox('remind-globally', 1, checked=0).Format())
replacements['<mm-global-nodupes-button>'] = (
CheckBox('nodupes-globally', 1, checked=0).Format())
days = int(mm_cfg.PENDING_REQUEST_LIFE / mm_cfg.days(1))
if days > 1:
units = _('days')
else:
units = _('day')
replacements['<mm-pending-days>'] = _('%(days)d %(units)s')
replacements['<mm-new-address-box>'] = mlist.FormatBox('new-address')
replacements['<mm-confirm-address-box>'] = mlist.FormatBox(
'confirm-address')
replacements['<mm-change-address-button>'] = mlist.FormatButton(
'change-of-address', _('Change My Address and Name'))
replacements['<mm-global-change-of-address>'] = CheckBox(
'changeaddr-globally', 1, checked=0).Format()
replacements['<mm-fullname-box>'] = mlist.FormatBox(
'fullname', value=fullname)
usertopics = mlist.getMemberTopics(user)
if mlist.topics:
table = Table(border="0")
for name, pattern, description, emptyflag in mlist.topics:
quotedname = urllib.quote_plus(name)
details = Link(mlist.GetScriptURL('options') +
'/%s/?VARHELP=%s' % (user, quotedname),
' (Details)')
if name in usertopics:
checked = 1
else:
checked = 0
table.AddRow([CheckBox('usertopic', quotedname, checked=checked),
name + details.Format()])
topicsfield = table.Format()
else:
topicsfield = _('<em>No topics defined</em>')
replacements['<mm-topics>'] = topicsfield
replacements['<mm-suppress-nonmatching-topics>'] = (
mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 0, user))
replacements['<mm-receive-nonmatching-topics>'] = (
mlist.FormatOptionButton(mm_cfg.ReceiveNonmatchingTopics, 1, user))
if cpuser is not None:
replacements['<mm-case-preserved-user>'] = _('''
You are subscribed to this list with the case-preserved address
<em>%(cpuser)s</em>.''')
else:
replacements['<mm-case-preserved-user>'] = ''
doc.AddItem(mlist.ParseTags('options.html', replacements, userlang))
def loginpage(mlist, doc, user, lang):
realname = mlist.real_name
actionurl = mlist.GetScriptURL('options')
if user is None:
title = _('%(realname)s list: member options login page')
extra = _('email address and ')
else:
safeuser = Utils.websafe(user)
title = _('%(realname)s list: member options for user %(safeuser)s')
obuser = Utils.ObscureEmail(user)
extra = ''
doc.SetTitle(title)
table = Table(width='100%', border=0, cellspacing=4, cellpadding=5)
table.AddRow([Center(Header(2, title))])
table.AddCellInfo(table.GetCurrentRowIndex(), 0,
bgcolor=mm_cfg.WEB_HEADER_COLOR)
if len(mlist.GetAvailableLanguages()) > 1:
langform = Form(actionurl)
langform.AddItem(SubmitButton('displang-button',
_('View this page in')))
langform.AddItem(mlist.GetLangSelectBox(lang))
if user:
langform.AddItem(Hidden('email', user))
table.AddRow([Center(langform)])
doc.AddItem(table)
form = Form(actionurl)
table = Table(width='100%', border=0, cellspacing=4, cellpadding=5)
table.AddRow([_("""In order to change your membership option, you must
first log in by giving your %(extra)smembership password in the section
below. If you don't remember your membership password, you can have it
emailed to you by clicking on the button below. If you just want to
unsubscribe from this list, click on the <em>Unsubscribe</em> button and a
confirmation message will be sent to you.
<p><strong><em>Important:</em></strong> From this point on, you must have
cookies enabled in your browser, otherwise none of your changes will take
effect.
""")])
ptable = Table(width='50%', border=0, cellspacing=4, cellpadding=5)
if user is None:
ptable.AddRow([Label(_('Email address:')),
TextBox('email', size=20)])
else:
ptable.AddRow([Hidden('email', user)])
ptable.AddRow([Label(_('Password:')),
PasswordBox('password', size=20)])
ptable.AddRow([Center(SubmitButton('login', _('Log in')))])
ptable.AddCellInfo(ptable.GetCurrentRowIndex(), 0, colspan=2)
table.AddRow([Center(ptable)])
table.AddRow([Center(Header(2, _('Unsubscribe')))])
table.AddCellInfo(table.GetCurrentRowIndex(), 0,
bgcolor=mm_cfg.WEB_HEADER_COLOR)
table.AddRow([_("""By clicking on the <em>Unsubscribe</em> button, a
confirmation message will be emailed to you. This message will have a
link that you should click on to complete the removal process (you can
also confirm by email; see the instructions in the confirmation
message).""")])
table.AddRow([Center(SubmitButton('login-unsub', _('Unsubscribe')))])
table.AddRow([Center(Header(2, _('Password reminder')))])
table.AddCellInfo(table.GetCurrentRowIndex(), 0,
bgcolor=mm_cfg.WEB_HEADER_COLOR)
table.AddRow([_("""By clicking on the <em>Remind</em> button, your
password will be emailed to you.""")])
table.AddRow([Center(SubmitButton('login-remind', _('Remind')))])
form.AddItem(table)
doc.AddItem(form)
doc.AddItem(mlist.GetMailmanFooter())
def lists_of_member(mlist, user):
hostname = mlist.host_name
onlists = []
for listname in Utils.list_names():
if listname == mlist.internal_name():
continue
glist = MailList.MailList(listname, lock=0)
if glist.host_name <> hostname:
continue
if not glist.isMember(user):
continue
onlists.append(glist)
return onlists
def change_password(mlist, user, newpw, confirmpw):
def sigterm_handler(signum, frame, mlist=mlist):
mlist.Unlock()
sys.exit(0)
mlist.Lock()
try:
signal.signal(signal.SIGTERM, sigterm_handler)
mlist.setMemberPassword(user, newpw)
mlist.Save()
finally:
mlist.Unlock()
def global_options(mlist, user, globalopts):
for attr in dir(globalopts):
if attr.startswith('_'):
continue
if getattr(globalopts, attr) is not None:
break
else:
return
def sigterm_handler(signum, frame, mlist=mlist):
mlist.Unlock()
sys.exit(0)
mlist.Lock()
try:
signal.signal(signal.SIGTERM, sigterm_handler)
if globalopts.enable is not None:
mlist.setDeliveryStatus(user, globalopts.enable)
if globalopts.remind is not None:
mlist.setMemberOption(user, mm_cfg.SuppressPasswordReminder,
globalopts.remind)
if globalopts.nodupes is not None:
mlist.setMemberOption(user, mm_cfg.DontReceiveDuplicates,
globalopts.nodupes)
if globalopts.mime is not None:
mlist.setMemberOption(user, mm_cfg.DisableMime, globalopts.mime)
mlist.Save()
finally:
mlist.Unlock()
def topic_details(mlist, doc, user, cpuser, userlang, varhelp):
reflist = varhelp.split('/')
name = None
topicname = _('<missing>')
if len(reflist) == 1:
topicname = urllib.unquote_plus(reflist[0])
for name, pattern, description, emptyflag in mlist.topics:
if name == topicname:
break
else:
name = None
if not name:
options_page(mlist, doc, user, cpuser, userlang,
_('Requested topic is not valid: %(topicname)s'))
print doc.Format()
return
table = Table(border=3, width='100%')
table.AddRow([Center(Bold(_('Topic filter details')))])
table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2,
bgcolor=mm_cfg.WEB_SUBHEADER_COLOR)
table.AddRow([Bold(Label(_('Name:'))),
Utils.websafe(name)])
table.AddRow([Bold(Label(_('Pattern (as regexp):'))),
'<pre>' + Utils.websafe(pattern) + '</pre>'])
table.AddRow([Bold(Label(_('Description:'))),
Utils.websafe(description)])
for row in range(1, 4):
table.AddCellInfo(row, 0, bgcolor=mm_cfg.WEB_ADMINITEM_COLOR)
options_page(mlist, doc, user, cpuser, userlang, table.Format())
print doc.Format()