diff --git a/config.py.example b/config.py.example index cf7d0ba3b8551363673e6ccccd1221a1b2ab6371..3ae558dbd9bedd9ee2a87f2401cc2ecb89a1e998 100644 --- a/config.py.example +++ b/config.py.example @@ -31,3 +31,9 @@ ERROR_PAGE = 'static/500.html' RWTH_IP_RANGES = ['134.130.0.0/16', '137.226.0.0/16', '134.61.0.0/16', '192.35.229.0/24', '2a00:8a60::/32'] FSMPI_IP_RANGES = ['137.226.35.192/29', '137.226.75.0/27', '137.226.127.32/27', '137.226.231.192/26', '134.130.102.0/26' ] DISABLE_SCHEDULER = False +#MAIL_SERVER = 'mail.fsmpi.rwth-aachen.de' +MAIL_FROM = 'Video AG-Website <videoag-it@lists.fsmpi.rwth-aachen.de>' +MAIL_SUFFIX = 'fsmpi.rwth-aachen.de' +MAIL_SERVER = 'mail.fsmpi.rwth-aachen.de' +MAIL_DEFAULT = 'Video AG <videoag@fsmpi.rwth-aachen.de>' +MAIL_ADMINS = 'videoag-it@lists.fsmpi.rwth-aachen.de' diff --git a/db_schema.sql b/db_schema.sql index b5f8a4dc1f02c11c1eccc25de5fffc72d3b06096..8a6bc103a8dd53bc10f9cec0d4b6987e3539a430 100644 --- a/db_schema.sql +++ b/db_schema.sql @@ -205,7 +205,8 @@ CREATE TABLE IF NOT EXISTS `users` ( `fsacc` varchar(32) NOT NULL, `last_login` datetime DEFAULT NULL, `calendar_key` varchar(40) NOT NULL, - `rfc6238` varchar(20) NOT NULL + `rfc6238` varchar(20) NOT NULL, + `mail_notifications` INTEGER NOT NULL DEFAULT '1' ); CREATE TABLE IF NOT EXISTS `videos_data` ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, @@ -292,6 +293,12 @@ CREATE TABLE IF NOT EXISTS `jobs` ( `status` text NOT NULL DEFAULT '{}' ); +CREATE TABLE IF NOT EXISTS `responsible` ( +`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + `course_id` INTEGER NOT NULL, + `user_id` INTEGER NOT NULL +); + CREATE VIEW IF NOT EXISTS `courses` AS select * from `courses_data` where (not(`courses_data`.`deleted`)); CREATE VIEW IF NOT EXISTS `lectures` AS select `lectures_data`.* from `lectures_data` join `courses_data` on (`courses_data`.`id` = `course_id`) where (not(`lectures_data`.`deleted` or `courses_data`.`deleted`)); CREATE VIEW IF NOT EXISTS `videos` AS select `videos_data`.* from `videos_data` join `lectures_data` on (`lectures_data`.`id` = `lecture_id`) join `courses_data` on (`courses_data`.`id` = `course_id`) where (not(`videos_data`.`deleted` or `lectures_data`.`deleted` or `courses_data`.`deleted`)); diff --git a/mail.py b/mail.py new file mode 100644 index 0000000000000000000000000000000000000000..35bd774c6466efe53e8db78116e11fd51f0659b1 --- /dev/null +++ b/mail.py @@ -0,0 +1,67 @@ +from server import * + +from email.message import EmailMessage +import smtplib +import traceback + +def send_message(msgtype, recipients, **kwargs): + msg = EmailMessage() + msg['From'] = config['MAIL_FROM'] + msg['To'] = ', '.join([r.replace(',', '') for r in recipients]) + cc = kwargs.pop('cc', []) + if cc: + msg['Cc'] = ', '.join([r.replace(',', '') for r in cc]) + try: + msg['Subject'] = render_template('mails/'+msgtype+'.subject', **kwargs) + msg.set_content(render_template('mails/'+msgtype+'.body', **kwargs)) + except: + traceback.print_exc() + return + if 'MAIL_SERVER' not in config: + return + s = smtplib.SMTP(config['MAIL_SERVER']) + s.send_message(msg) + s.quit() + +def notify_users(msgtype, uids, **kwargs): + recipients = [] + exclude = kwargs.pop('exclude_uids', []) + for uid in uids: + user = query('SELECT * FROM users WHERE id = ?', uid) + if user[0]['id'] in exclude: + continue + if not user or not user[0]['fsacc'] or not user[0]['mail_notifications']: + continue + if msgtype in user[0] and not user[0][msgtype]: + continue + if user[0]['realname']: + recipients.append('%s <%s@%s>'%(user[0]['realname'], user[0]['fsacc'], + config['MAIL_SUFFIX'])) + else: + recipients.append('%s@%s'%(user[0]['fsacc'], config['MAIL_SUFFIX'])) + if recipients: + if kwargs.pop('importend', False): + kwargs['cc'] = [config['MAIL_DEFAULT']] + else: + if kwargs.pop('importend', False): + recipients = [config['MAIL_DEFAULT']] + else: + return + send_message(msgtype, recipients, **kwargs) + +def notify_mods(msgtype, course_id, **kwargs): + users = query('SELECT * FROM responsible WHERE course_id = ?', course_id) + uids = [] + for user in users: + if msgtype in user and not user[msgtype]: + continue + uids.append(user['user_id']) + notify_users(msgtype, uids, **kwargs) + +def notify_admins(msgtype, **kwargs): + try: + send_message(msgtype, [config['MAIL_ADMINS']], **kwargs) + except: + traceback.print_exc() + pass + diff --git a/server.py b/server.py index 5e2cda4204721be0576e81d0c7dc474de00aabb1..60740ee12054f93bf7457b2ae2fc649c4087ac2d 100644 --- a/server.py +++ b/server.py @@ -46,6 +46,7 @@ from db import query, modify, show, searchquery from ldap import ldapauth from legacy import legacy_index from scheduler import sched_func +from mail import notify_mods, notify_admins mod_endpoints = [] @@ -123,6 +124,7 @@ def handle_not_found(e=None): @app.errorhandler(Exception) def handle_internal_error(e): traceback.print_exc() + notify_admins('exception', traceback=traceback.format_exc()) return render_template('500.html'), 500 @sched_func(5*60, firstdelay=0) diff --git a/templates/mails/exception.body b/templates/mails/exception.body new file mode 100644 index 0000000000000000000000000000000000000000..e0ebfe5bcc4345b0331cb1613e16b283441b65bf --- /dev/null +++ b/templates/mails/exception.body @@ -0,0 +1,6 @@ +{{ request.method }} {{ request.url }} + +Endpoint: {{ request.endpoint }} +Hostname: {{ gethostname() }} + +{{ traceback }} diff --git a/templates/mails/exception.subject b/templates/mails/exception.subject new file mode 100644 index 0000000000000000000000000000000000000000..6ee488a121a78ba9b12d989dbc39afd655ebce24 --- /dev/null +++ b/templates/mails/exception.subject @@ -0,0 +1 @@ +Exception in endpoint "{{ request.endpoint }}"