Add UI for email forwarding

We nag users to update their forwarding address every time they renew
membership.
This commit is contained in:
Michael Spang 2009-08-23 11:15:03 -04:00
parent 9eefe615c5
commit 35179ec978
3 changed files with 132 additions and 2 deletions

View File

@ -9,7 +9,7 @@ Transactions are used in each method that modifies the database.
Future changes to the members database that need to be atomic
must also be moved into this module.
"""
import os, re, subprocess, ldap
import os, re, subprocess, ldap, socket
from ceo import conf, ldapi, terms, remote, ceo_pb2
from ceo.excep import InvalidArgument
@ -164,6 +164,54 @@ def create_member(username, password, name, program, email):
raise MemberException(e)
def check_email(email):
match = re.match('^\S+?@(\S+)$', email)
if not match:
return 'Invalid email address'
# some characters are treated specially in .forward
for c in email:
if c in ('"', "'", ',', '|', '$', '/', '#', ':'):
return 'Invalid character in address: %s' % c
host = match.group(1)
try:
ip = socket.gethostbyname(host)
except:
return 'Invalid host: %s' % host
def current_email(username):
fwdpath = '%s/%s/.forward' % (cfg['member_home'], username)
try:
fwd = open(fwdpath).read().strip()
if not check_email(fwd):
return fwd
except OSError:
pass
except IOError:
pass
def change_email(username, forward):
try:
request = ceo_pb2.UpdateMail()
request.username = username
request.forward = forward
out = remote.run_remote('mail', request.SerializeToString())
response = ceo_pb2.AddUserResponse()
response.ParseFromString(out)
if any(message.status != 0 for message in response.messages):
return '\n'.join(message.message for message in response.messages)
except remote.RemoteException, e:
raise MemberException(e)
except OSError, e:
raise MemberException(e)
def get(userid):
"""
Look up attributes of a member by userid.

View File

@ -87,15 +87,19 @@ def renew_member(*args, **kwargs):
push_wizard("Renew Membership", [
renew.IntroPage,
renew.UserPage,
renew.EmailPage,
renew.EmailDonePage,
renew.TermPage,
renew.PayPage,
renew.EndPage,
])
], (60, 15))
def renew_club_user(*args, **kwargs):
push_wizard("Renew Club Rep Account", [
renew.ClubUserIntroPage,
renew.UserPage,
renew.EmailPage,
renew.EmailDonePage,
(renew.TermPage, "clubuser"),
(renew.EndPage, "clubuser"),
], (60, 15))

View File

@ -49,6 +49,84 @@ class UserPage(WizardPanel):
self.focus_widget(self.userid)
return True
class EmailPage(WizardPanel):
def init_widgets(self):
self.email = SingleEdit("Email: ")
self.widgets = [
urwid.Text( "Mail Forwarding" ),
urwid.Divider(),
urwid.Text("Please ensure the forwarding address for "
"your CSC email is up to date."),
urwid.Divider(),
urwid.Text("Warning: Changing this overwrites ~/.forward"),
urwid.Divider(),
self.email,
]
def activate(self):
cfwd = members.current_email(self.state['userid'])
self.state['old_forward'] = cfwd if cfwd else ''
self.email.set_edit_text(self.state['old_forward'])
def check(self):
fwd = self.email.get_edit_text().strip().lower()
if fwd:
msg = members.check_email(fwd)
if msg:
set_status(msg)
return True
if fwd == '%s@csclub.uwaterloo.ca' % self.state['userid']:
set_status('You cannot forward your address to itself. Leave it blank to disable forwarding.')
return True
self.state['new_forward'] = fwd
class EmailDonePage(WizardPanel):
def init_widgets(self):
self.status = urwid.Text("")
self.widgets = [
urwid.Text("Mail Forwarding"),
urwid.Divider(),
self.status,
]
def focusable(self):
return False
def activate(self):
if self.state['old_forward'] == self.state['new_forward']:
if self.state['old_forward']:
self.status.set_text(
'You have chosen to leave your forwarding address '
'as %s. Make sure to check this email for updates '
'from the CSC.' % self.state['old_forward'])
else:
self.status.set_text(
'You have chosen not to set a forwarding address. '
'Please check your CSC email regularly (via IMAP, POP, or locally) '
'for updates from the CSC.'
'\n\n'
'Note: If you do have a ~/.forward, we were not able to read it or '
'it was not a single email address. Do not worry, we have left it '
'as is.')
else:
try:
msg = members.change_email(self.state['userid'], self.state['new_forward'])
if msg:
self.status.set_text("Errors occured updating your forwarding address:"
"\n\n%s" % msg)
else:
if self.state['new_forward']:
self.status.set_text(
'Your email forwarding address has been successfully set '
'to %s. Test it out by emailing %s@csclub.uwaterloo.ca and '
'making sure you receive it at your forwarding address.'
% (self.state['new_forward'], self.state['userid']))
else:
self.status.set_text(
'Your email forwarding address has been successfully cleared. '
'Please check your CSC email regularly (via IMAP, POP, or locally) '
'for updates from the CSC.')
except Exception, e:
self.status.set_text(
'An exception occured updating your email:\n\n%s' % e)
class TermPage(WizardPanel):
def __init__(self, state, utype='member'):
self.utype = utype