aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman')
-rw-r--r--Mailman/Cgi/admin.py110
-rw-r--r--Mailman/Gui/Membership.py1
2 files changed, 110 insertions, 1 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py
index 36a5af6e..4cd619bb 100644
--- a/Mailman/Cgi/admin.py
+++ b/Mailman/Cgi/admin.py
@@ -32,6 +32,7 @@ from email.Utils import unquote, parseaddr, formataddr
from Mailman import mm_cfg
from Mailman import Utils
+from Mailman import Message
from Mailman import MailList
from Mailman import Errors
from Mailman import MemberAdaptor
@@ -523,7 +524,7 @@ def show_results(mlist, doc, category, subcat, cgidata):
if category == 'members':
# Figure out which subcategory we should display
subcat = Utils.GetPathPieces()[-1]
- if subcat not in ('list', 'add', 'remove'):
+ if subcat not in ('list', 'add', 'remove', 'change'):
subcat = 'list'
# Add member category specific tables
form.AddItem(membership_options(mlist, subcat, cgidata, doc, form))
@@ -877,6 +878,13 @@ def membership_options(mlist, subcat, cgidata, doc, form):
container.AddItem(header)
mass_remove(mlist, container)
return container
+ if subcat == 'change':
+ header.AddRow([Center(Header(2, _('Address Change')))])
+ header.AddCellInfo(header.GetCurrentRowIndex(), 0, colspan=2,
+ bgcolor=mm_cfg.WEB_HEADER_COLOR)
+ container.AddItem(header)
+ address_change(mlist, container)
+ return container
# Otherwise...
header.AddRow([Center(Header(2, _('Membership List')))])
header.AddCellInfo(header.GetCurrentRowIndex(), 0, colspan=2,
@@ -1244,6 +1252,38 @@ def mass_remove(mlist, container):
+def address_change(mlist, container):
+ # ADDRESS CHANGE
+ GREY = mm_cfg.WEB_ADMINITEM_COLOR
+ table = Table(width='90%')
+ table.AddRow([Italic(_("""To change a list member's address, enter the
+ member's current and new addresses below. Use the check boxes to send
+ notice of the change to the old and/or new address(es)."""))])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=3)
+ table.AddRow([
+ Label(_("Member's current address")),
+ TextBox(name='change_from'),
+ CheckBox('notice_old', 'yes', 0).Format() +
+ ' ' +
+ _('Send notice')
+ ])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ table.AddCellInfo(table.GetCurrentRowIndex(), 1, bgcolor=GREY)
+ table.AddCellInfo(table.GetCurrentRowIndex(), 2, bgcolor=GREY)
+ table.AddRow([
+ Label(_('Address to change to')),
+ TextBox(name='change_to'),
+ CheckBox('notice_new', 'yes', 0).Format() +
+ ' ' +
+ _('Send notice')
+ ])
+ table.AddCellInfo(table.GetCurrentRowIndex(), 0, bgcolor=GREY)
+ table.AddCellInfo(table.GetCurrentRowIndex(), 1, bgcolor=GREY)
+ table.AddCellInfo(table.GetCurrentRowIndex(), 2, bgcolor=GREY)
+ container.AddItem(Center(table))
+
+
+
def password_inputs(mlist):
adminurl = mlist.GetScriptURL('admin', absolute=1)
table = Table(cellspacing=3, cellpadding=4)
@@ -1466,6 +1506,74 @@ def change_options(mlist, category, subcat, cgidata, doc):
color='#ff0000', size='+2')).Format()))
doc.AddItem(UnorderedList(*unsubscribe_errors))
doc.AddItem('<p>')
+ # Address Changes
+ if cgidata.has_key('change_from'):
+ change_from = cgidata.getvalue('change_from', '')
+ change_to = cgidata.getvalue('change_to', '')
+ schange_from = Utils.websafe(change_from)
+ schange_to = Utils.websafe(change_to)
+ success = False
+ msg = None
+ if not (change_from and change_to):
+ msg = _('You must provide both current and new addresses.')
+ elif change_from == change_to:
+ msg = _('Current and new addresses must be different.')
+ elif mlist.isMember(change_to):
+ # ApprovedChangeMemberAddress will just delete the old address
+ # and we don't want that here.
+ msg = _('%(schange_to)s is already a list member.')
+ else:
+ try:
+ Utils.ValidateEmail(change_to)
+ except (Errors.MMBadEmailError, Errors.MMHostileAddress):
+ msg = _('%(schange_to)s is not a valid email address.')
+ if msg:
+ doc.AddItem(Header(3, msg))
+ doc.AddItem('<p>')
+ return
+ try:
+ mlist.ApprovedChangeMemberAddress(change_from, change_to, False)
+ except Errors.NotAMemberError:
+ msg = _('%(schange_from)s is not a member')
+ except Errors.MMAlreadyAMember:
+ msg = _('%(schange_to)s is already a member')
+ except Errors.MembershipIsBanned, pat:
+ spat = Utils.websafe(str(pat))
+ msg = _('%(schange_to)s matches banned pattern %(spat)s')
+ else:
+ msg = _('Address %(schange_from)s changed to %(schange_to)s')
+ success = True
+ doc.AddItem(Header(3, msg))
+ lang = mlist.getMemberLanguage(change_to)
+ otrans = i18n.get_translation()
+ i18n.set_language(lang)
+ list_name = mlist.getListAddress()
+ text = Utils.wrap(_("""The member address %(change_from)s on the
+%(list_name)s list has been changed to %(change_to)s.
+"""))
+ subject = _('%(list_name)s address change notice.')
+ i18n.set_translation(otrans)
+ if success and cgidata.getvalue('notice_old', '') == 'yes':
+ # Send notice to old address.
+ msg = Message.UserNotification(change_from,
+ mlist.GetOwnerEmail(),
+ text=text,
+ subject=subject,
+ lang=lang
+ )
+ msg.send(mlist)
+ doc.AddItem(Header(3, _('Notification sent to %(schange_from)s.')))
+ if success and cgidata.getvalue('notice_new', '') == 'yes':
+ # Send notice to new address.
+ msg = Message.UserNotification(change_to,
+ mlist.GetOwnerEmail(),
+ text=text,
+ subject=subject,
+ lang=lang
+ )
+ msg.send(mlist)
+ doc.AddItem(Header(3, _('Notification sent to %(schange_to)s.')))
+ doc.AddItem('<p>')
# See if this was a moderation bit operation
if cgidata.has_key('allmodbit_btn'):
val = safeint('allmodbit_val')
diff --git a/Mailman/Gui/Membership.py b/Mailman/Gui/Membership.py
index 7e1bf324..fdf5a7ca 100644
--- a/Mailman/Gui/Membership.py
+++ b/Mailman/Gui/Membership.py
@@ -30,5 +30,6 @@ class Membership:
return [('list', _('Membership&nbsp;List')),
('add', _('Mass&nbsp;Subscription')),
('remove', _('Mass&nbsp;Removal')),
+ ('change', _('Address&nbsp;Change')),
]
return None