Commit def763d6 authored by Martin Mareš's avatar Martin Mareš
Browse files

If a user has multiple e-mails in CAS, pick one of them

We prefer local UK addresses.
parent 72e5ab00
......@@ -6,7 +6,6 @@ CREATE TABLE owl_users (
auth_token varchar(64) UNIQUE DEFAULT NULL, -- this is called "access key" in UI
full_name varchar(255) NOT NULL,
email varchar(255) DEFAULT NULL,
-- we allow CAS's format "{email1,email2,...}"
created timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_admin boolean NOT NULL DEFAULT false,
notify boolean NOT NULL DEFAULT false,
......@@ -1033,7 +1033,7 @@ def user_settings(): = user.notify_self = user.inline_att
return render_template('settings.html', form=form, user=user, emails=parse_emails(
return render_template('settings.html', form=form, user=user)
### Administration ###
......@@ -1347,17 +1347,37 @@ def cas_login():
return redirect(next)
def parse_cas_emails(raw_email):
if raw_email[0] == '{' and raw_email[-1] == '}':
# Strange CAS encoding of multiple e-mail addresses
return raw_email[1:-1].split(',')
return [raw_email]
def primary_cas_email(raw_email):
emails = parse_cas_emails(raw_email)
if not emails:
return None
uk = [e for e in emails if e.endswith('')]
if uk:
return uk[0]
return emails[0]
def session_from_cas(user, attrs):
db_query("SELECT * FROM owl_users WHERE ukco=%s", (user,))
row = db.fetchone()
if row:'Logged in user: uid=%s, ukco=%s, cn=%s, mail=%s, admin=%s', row.uid, row.ukco, row.full_name,, row.is_admin)
email = primary_cas_email(attrs['mail'])
INSERT INTO owl_users(ukco, full_name, email)
VALUES (%s, %s, %s)
RETURNING uid, ukco, full_name, email, is_admin, inline_att
""", (user, attrs['cn'], attrs['mail']))
""", (user, attrs['cn'], email))
row = db.fetchone()'Created new user: uid=%s, ukco=%s, cn=%s, mail=%s', row.uid, row.ukco, row.full_name,
......@@ -1562,6 +1582,25 @@ def cli_add_teacher(course_ident, teacher):
def cli_convert_emails():
"""Convert up e-mail addresses in the database from old SIS format."""
FROM owl_users
WHERE email LIKE '%%{%%'
users = db.fetchall()
for u in users:
primary = primary_cas_email(
print(u.uid, u.full_name,, '->', primary)
db_query("UPDATE owl_users SET email=%s WHERE uid=%s", (primary, u.uid))
### Sending notifications ###
......@@ -1626,26 +1665,20 @@ def send_notify_post(post):"E-mail: not sending self-notify to uid={dest.uid}")
def parse_emails(raw_email):
if raw_email[0] == '{' and raw_email[-1] == '}':
# Strange CAS encoding of multiple e-mail addresses
return raw_email[1:-1].split(',')
return [raw_email]
def send_notify_to_dest(post, topic, course, author, target, dest):
emails = parse_emails(
if 'MAIL_FROM' not in app.config:'Not sending: MAIL_FROM not defined')
return"E-mail: uid={dest.uid} emails={emails}")
if not"E-mail: uid={dest.uid} has no address")
return"E-mail: uid={dest.uid} email={}")
msg = email.message.EmailMessage()
msg['From'] = email.headerregistry.Address(display_name=author.full_name + " via Owl", addr_spec=app.config['MAIL_FROM'])
msg['To'] = [ email.headerregistry.Address(display_name=dest.full_name, addr_spec=e) for e in emails ]
msg['To'] = email.headerregistry.Address(display_name=dest.full_name,
msg['Subject'] = f'Owl: {topic.title}'
msg['Date'] = (post.modified or post.created).astimezone()
if 'MAIL_REFERENCES' in app.config:
......@@ -1690,7 +1723,8 @@ def send_notify_to_dest(post, topic, course, author, target, dest):
"-f", app.config['MAIL_FROM'],
] + emails, stdin=subprocess.PIPE),
], stdin=subprocess.PIPE)
if sm.returncode != 0:
app.logger.error("Sendmail failed with return code %d", sm.returncode)
......@@ -6,7 +6,7 @@
{{ form.csrf_token }}
<table class=settings>
<tr><td>Name:<td>{{ user.full_name }}
<tr><td>E-mail:<td>{{ "<br>".join(emails) }}
<tr><td>E-mail:<td>{{ }}
<tr><td>Notify by e-mail:<td>{{ form.notify() }}
<tr><td>Notify on own posts:<td>{{ form.notify_self() }}
<tr><td>Show PDF attachments inline:<td>{{ form.inline_att() }}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment