From c7475bd6648a74413f6a593764e196df741846ac Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 01:25:32 -0500 Subject: [PATCH 01/10] Send email when marked absent from house meeting Also sends an email when evals updates an active members house meeting attendance. --- conditional/blueprints/attendance.py | 10 ++++++ conditional/util/email.py | 51 ++++++++++++++++++++++++++++ config.env.py | 6 ++++ 3 files changed, 67 insertions(+) create mode 100644 conditional/util/email.py diff --git a/conditional/blueprints/attendance.py b/conditional/blueprints/attendance.py index 7adbf995..4ae92a7f 100644 --- a/conditional/blueprints/attendance.py +++ b/conditional/blueprints/attendance.py @@ -1,4 +1,5 @@ from datetime import datetime +from threading import Thread import structlog from flask import Blueprint, jsonify, redirect, request @@ -22,6 +23,7 @@ from conditional.util.ldap import ldap_get_member from conditional.util.ldap import ldap_is_eboard from conditional.util.ldap import ldap_is_eval_director +from conditional.util.email import send_absent_hm_attendance_emails, send_present_hm_attendance_email logger = structlog.get_logger() @@ -261,7 +263,9 @@ def submit_house_attendance(user_dict=None): db.session.flush() db.session.refresh(meeting) + # logs whether a user was marked absent or present for attendance and sends an email to anyone marked absent if "members" in post_data: + absent_members = [] for m in post_data['members']: log.info('Marked {} {} for House Meeting on {}'.format( m['uid'], @@ -272,6 +276,10 @@ def submit_house_attendance(user_dict=None): meeting.id, None, m['status'])) + if m['status'] == 'Absent': + absent_members.append(m['uid']) + thread = Thread(target=send_absent_hm_attendance_emails, name="HM Emails", args=(absent_members,)) + thread.start() if "freshmen" in post_data: for f in post_data['freshmen']: @@ -304,6 +312,8 @@ def alter_house_attendance(uid, hid, user_dict=None): MemberHouseMeetingAttendance.uid == uid, MemberHouseMeetingAttendance.meeting_id == hid ).first() + thread = Thread(target=send_present_hm_attendance_email, name="HM Emails", args=(uid,)) + thread.start() member_meeting.attendance_status = "Attended" db.session.commit() return jsonify({"success": True}), 200 diff --git a/conditional/util/email.py b/conditional/util/email.py new file mode 100644 index 00000000..38d7dd66 --- /dev/null +++ b/conditional/util/email.py @@ -0,0 +1,51 @@ +import smtplib +from email.mime.text import MIMEText +from email.utils import formatdate +from email.mime.multipart import MIMEMultipart +from datetime import date +from conditional import app + +def send_absent_hm_attendance_emails(absent_members): + today_date = date.today().strftime("%m/%d") + subject = "You were marked as absent for the {} House Meeting.".format(today_date) + body = subject + "\n\nIf this is a mistake please message the evaluations director and let them know." + # doing this uses the same connection for all emails sent to absent members + send_email(absent_members, subject, body) + +def send_present_hm_attendance_email(member): + today_date = date.today().strftime("%m/%d") + subject = "You were marked as present for the {} House Meeting.".format(today_date) + body = subject + # doing this uses the same connection for all emails sent to absent members + send_email([member], subject, body) + +def send_attenance_requirement_met_email(user): + subject = "You have attended 30 Directorship Meetings" + # pylint: disable=line-too-long + body = "You have met one of the requirements of active membership by attending 30 directorship meetings. Congratulations or I'm Sorry!" + send_email([user], subject, body) + +def send_email(members, subject, body): + """A function capable of sending one or many emails""" + debug_email = app.config['DEBUG_EMAIL'] + should_send_email = app.config['SEND_EMAIL'] + + if should_send_email: + recipents = map("{}@csh.rit.edu".format, members) + server = smtplib.SMTP(app.config['MAIL_SERVER']) + server.starttls() + server.login('conditional', app.config['EMAIL_PASSWORD']) + sender_addr = "conditional@csh.rit.edu" + for member in recipents: + msg = MIMEMultipart() + if debug_email is not None: + recipient_addr = debug_email + else: + recipient_addr = "{}@csh.rit.edu".format(member) + msg["To"] = recipient_addr + msg["From"] = sender_addr + msg["Subject"] = subject + msg["Date"] = formatdate(localtime=True) + msg.attach(MIMEText(body, 'plain')) + server.sendmail(sender_addr, recipient_addr, msg.as_string()) + server.quit() diff --git a/config.env.py b/config.env.py index 7956d1ac..ce1b165e 100644 --- a/config.env.py +++ b/config.env.py @@ -47,3 +47,9 @@ # General config DUES_PER_SEMESTER = env.get("CONDITIONAL_DUES_PER_SEMESTER", 80) + +# Email +SEND_EMAIL = env.get("CONDITIONAL_SEND_EMAIL", True) +MAIL_SERVER = env.get("CONDITIONAL_MAIL_SERVER", "thoth.csh.rit.edu") +DEBUG_EMAIL = env.get("CONDITIONAL_DEBUG_EMAIL", "") +EMAIL_PASSWORD = env.get("CONDITIONAL_MAIL_PASSWORD", "") \ No newline at end of file From 8d5cd97aeddd98dfd5c91d77bd3b208534bae065 Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 01:59:49 -0500 Subject: [PATCH 02/10] Added newline to end of file --- config.env.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.env.py b/config.env.py index ce1b165e..e6f06675 100644 --- a/config.env.py +++ b/config.env.py @@ -52,4 +52,4 @@ SEND_EMAIL = env.get("CONDITIONAL_SEND_EMAIL", True) MAIL_SERVER = env.get("CONDITIONAL_MAIL_SERVER", "thoth.csh.rit.edu") DEBUG_EMAIL = env.get("CONDITIONAL_DEBUG_EMAIL", "") -EMAIL_PASSWORD = env.get("CONDITIONAL_MAIL_PASSWORD", "") \ No newline at end of file +EMAIL_PASSWORD = env.get("CONDITIONAL_MAIL_PASSWORD", "") From dc28471c66c1c902182e28c2ef4aa3fe5259eae7 Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:00:37 -0500 Subject: [PATCH 03/10] Default value of SEND_EMAIL is now False --- config.env.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.env.py b/config.env.py index e6f06675..018382e0 100644 --- a/config.env.py +++ b/config.env.py @@ -49,7 +49,7 @@ DUES_PER_SEMESTER = env.get("CONDITIONAL_DUES_PER_SEMESTER", 80) # Email -SEND_EMAIL = env.get("CONDITIONAL_SEND_EMAIL", True) +SEND_EMAIL = env.get("CONDITIONAL_SEND_EMAIL", False) MAIL_SERVER = env.get("CONDITIONAL_MAIL_SERVER", "thoth.csh.rit.edu") DEBUG_EMAIL = env.get("CONDITIONAL_DEBUG_EMAIL", "") EMAIL_PASSWORD = env.get("CONDITIONAL_MAIL_PASSWORD", "") From a2ddf28033fda668296befcabf22633ca60be5fe Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:08:03 -0500 Subject: [PATCH 04/10] Removed unnecessary comment --- conditional/util/email.py | 1 - 1 file changed, 1 deletion(-) diff --git a/conditional/util/email.py b/conditional/util/email.py index 38d7dd66..3076c5f5 100644 --- a/conditional/util/email.py +++ b/conditional/util/email.py @@ -16,7 +16,6 @@ def send_present_hm_attendance_email(member): today_date = date.today().strftime("%m/%d") subject = "You were marked as present for the {} House Meeting.".format(today_date) body = subject - # doing this uses the same connection for all emails sent to absent members send_email([member], subject, body) def send_attenance_requirement_met_email(user): From 422372a29b3923be169dffbc1b444b7ef6899f7f Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:11:54 -0500 Subject: [PATCH 05/10] long strings now span multiple lines --- conditional/util/email.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/conditional/util/email.py b/conditional/util/email.py index 3076c5f5..f92be913 100644 --- a/conditional/util/email.py +++ b/conditional/util/email.py @@ -20,8 +20,9 @@ def send_present_hm_attendance_email(member): def send_attenance_requirement_met_email(user): subject = "You have attended 30 Directorship Meetings" - # pylint: disable=line-too-long - body = "You have met one of the requirements of active membership by attending 30 directorship meetings. Congratulations or I'm Sorry!" + body = """You have met one of the requirements of active + membership by attending 30 directorship meetings. + Congratulations or I'm Sorry!""" send_email([user], subject, body) def send_email(members, subject, body): From ae3b3c5c9a7fcb5403425027d0d3a0f3cd8deec5 Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:14:53 -0500 Subject: [PATCH 06/10] Added documentation to email environment variables --- config.env.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.env.py b/config.env.py index 018382e0..5839e5b5 100644 --- a/config.env.py +++ b/config.env.py @@ -49,7 +49,7 @@ DUES_PER_SEMESTER = env.get("CONDITIONAL_DUES_PER_SEMESTER", 80) # Email -SEND_EMAIL = env.get("CONDITIONAL_SEND_EMAIL", False) +SEND_EMAIL = env.get("CONDITIONAL_SEND_EMAIL", False) # When false, requests to send emails are ignored MAIL_SERVER = env.get("CONDITIONAL_MAIL_SERVER", "thoth.csh.rit.edu") -DEBUG_EMAIL = env.get("CONDITIONAL_DEBUG_EMAIL", "") +DEBUG_EMAIL = env.get("CONDITIONAL_DEBUG_EMAIL", "") # when set all email is sent to the specified email EMAIL_PASSWORD = env.get("CONDITIONAL_MAIL_PASSWORD", "") From 838a96709c6a89152b6d273e9bb974848ab4ee33 Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:17:00 -0500 Subject: [PATCH 07/10] removed stuff for directorship meeting requirement --- conditional/util/email.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/conditional/util/email.py b/conditional/util/email.py index f92be913..08bb6490 100644 --- a/conditional/util/email.py +++ b/conditional/util/email.py @@ -18,13 +18,6 @@ def send_present_hm_attendance_email(member): body = subject send_email([member], subject, body) -def send_attenance_requirement_met_email(user): - subject = "You have attended 30 Directorship Meetings" - body = """You have met one of the requirements of active - membership by attending 30 directorship meetings. - Congratulations or I'm Sorry!""" - send_email([user], subject, body) - def send_email(members, subject, body): """A function capable of sending one or many emails""" debug_email = app.config['DEBUG_EMAIL'] From 949680410c5b69bf3ba16fac49fcecce5df7d05e Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:20:25 -0500 Subject: [PATCH 08/10] Update conditional/util/email.py Co-authored-by: Max Meinhold --- conditional/util/email.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/conditional/util/email.py b/conditional/util/email.py index 08bb6490..28eb1ac8 100644 --- a/conditional/util/email.py +++ b/conditional/util/email.py @@ -21,9 +21,8 @@ def send_present_hm_attendance_email(member): def send_email(members, subject, body): """A function capable of sending one or many emails""" debug_email = app.config['DEBUG_EMAIL'] - should_send_email = app.config['SEND_EMAIL'] - if should_send_email: + if app.config['SEND_EMAIL']: recipents = map("{}@csh.rit.edu".format, members) server = smtplib.SMTP(app.config['MAIL_SERVER']) server.starttls() From b511d05190c8f33fe60e3a1e2b5b0cbb9eed4cd4 Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:20:46 -0500 Subject: [PATCH 09/10] Update conditional/util/email.py Co-authored-by: Max Meinhold --- conditional/util/email.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conditional/util/email.py b/conditional/util/email.py index 28eb1ac8..f18ef5ed 100644 --- a/conditional/util/email.py +++ b/conditional/util/email.py @@ -30,7 +30,7 @@ def send_email(members, subject, body): sender_addr = "conditional@csh.rit.edu" for member in recipents: msg = MIMEMultipart() - if debug_email is not None: + if debug_email: recipient_addr = debug_email else: recipient_addr = "{}@csh.rit.edu".format(member) From d4651274f67cb13f5ddd43b8d111f90596c7d362 Mon Sep 17 00:00:00 2001 From: Lonnie Gerol Date: Sun, 14 Feb 2021 02:22:54 -0500 Subject: [PATCH 10/10] renamed server to conn in email.py --- conditional/util/email.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/conditional/util/email.py b/conditional/util/email.py index f18ef5ed..01fff45d 100644 --- a/conditional/util/email.py +++ b/conditional/util/email.py @@ -24,9 +24,9 @@ def send_email(members, subject, body): if app.config['SEND_EMAIL']: recipents = map("{}@csh.rit.edu".format, members) - server = smtplib.SMTP(app.config['MAIL_SERVER']) - server.starttls() - server.login('conditional', app.config['EMAIL_PASSWORD']) + conn = smtplib.SMTP(app.config['MAIL_SERVER']) + conn.starttls() + conn.login('conditional', app.config['EMAIL_PASSWORD']) sender_addr = "conditional@csh.rit.edu" for member in recipents: msg = MIMEMultipart() @@ -39,5 +39,5 @@ def send_email(members, subject, body): msg["Subject"] = subject msg["Date"] = formatdate(localtime=True) msg.attach(MIMEText(body, 'plain')) - server.sendmail(sender_addr, recipient_addr, msg.as_string()) - server.quit() + conn.sendmail(sender_addr, recipient_addr, msg.as_string()) + conn.quit()