From ef4c016cfe6fcc0b5a1b6dc6c5dc3ab5ebbf44c6 Mon Sep 17 00:00:00 2001 From: Asmita Dabholkar Date: Thu, 22 Feb 2024 12:05:36 -0600 Subject: [PATCH] BCC recipients in Document export email (#224) * added BCC receipients in send_email() * added export endpoint again, it dissapeared during merge --- ai_ta_backend/emails.py | 21 +++++++++++++++------ ai_ta_backend/export_data.py | 19 +++++++++++++++++-- ai_ta_backend/main.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/ai_ta_backend/emails.py b/ai_ta_backend/emails.py index a2b3d18c..2f17dce0 100644 --- a/ai_ta_backend/emails.py +++ b/ai_ta_backend/emails.py @@ -4,16 +4,25 @@ from email.mime.multipart import MIMEMultipart -def send_email(subject, body_text, sender, receipients): +def send_email(subject: str, body_text: str, sender: str, receipients: list, bcc_receipients: list): + """ + Send an email using the AWS SES service + :param subject: The subject of the email + :param body_text: The body of the email + :param sender: The email address of the sender + :param receipients: A list of email addresses to send the email to + :param bcc_receipients: A list of email addresses to send the email to as BCC + :return: A string indicating the result of the email send operation + + """ # Create message content message = MIMEMultipart("alternative") message["Subject"] = subject message["From"] = sender + message["To"] = ", ".join(receipients) - if len(receipients) == 1: - message["To"] = receipients[0] - else: - message["To"] = ", ".join(receipients) + if len(bcc_receipients) > 0: + message["Bcc"] = ", ".join(bcc_receipients) # Add plain text part part1 = MIMEText(body_text, "plain") @@ -24,6 +33,6 @@ def send_email(subject, body_text, sender, receipients): # Connect to SMTP server with smtplib.SMTP_SSL(os.getenv('SES_HOST'), os.getenv('SES_PORT')) as server: # type: ignore server.login(os.getenv('USERNAME_SMTP'), os.getenv('PASSWORD_SMTP')) # type: ignore - server.sendmail(sender, receipients, message.as_string()) + server.sendmail(sender, receipients + bcc_receipients, message.as_string()) return "Email sent successfully!" \ No newline at end of file diff --git a/ai_ta_backend/export_data.py b/ai_ta_backend/export_data.py index d03f53dd..299b3435 100644 --- a/ai_ta_backend/export_data.py +++ b/ai_ta_backend/export_data.py @@ -19,7 +19,9 @@ def export_documents_json(course_name: str, from_date='', to_date=''): """ - This function exports the documents to a csv file. + This function exports the documents to a json file. + 1. If the number of documents is greater than 1000, it calls a background task to upload the documents to S3. + 2. If the number of documents is less than 1000, it fetches the documents and zips them. Args: course_name (str): The name of the course. from_date (str, optional): The start date for the data export. Defaults to ''. @@ -198,14 +200,27 @@ def export_data_in_bg(response, download_type, course_name, s3_path): course_metadata = response.json() course_metadata = json.loads(course_metadata['result']) admin_emails = course_metadata['course_admins'] + bcc_emails = [] + + # check for Kastan's email and move to bcc + if 'kvday2@illinois.edu' in admin_emails: + admin_emails.remove('kvday2@illinois.edu') + bcc_emails.append('kvday2@illinois.edu') + + # add course owner email to admin_emails admin_emails.append(course_metadata['course_owner']) admin_emails = list(set(admin_emails)) print("admin_emails: ", admin_emails) + print("bcc_emails: ", bcc_emails) + + # add a check for emails, don't send email if no admin emails + if len(admin_emails) == 0: + return "No admin emails found. Email not sent." # send email to admins subject = "UIUC.chat Data Export Complete for " + course_name body_text = "The data export for " + course_name + " is complete.\n\nYou can download the file from the following link: \n\n" + s3_url + "\n\nThis link will expire in 48 hours." - email_status = send_email(subject, body_text, os.getenv('EMAIL_SENDER'), admin_emails) + email_status = send_email(subject, body_text, os.getenv('EMAIL_SENDER'), admin_emails, bcc_emails) print("email_status: ", email_status) return "File uploaded to S3. Email sent to admins." diff --git a/ai_ta_backend/main.py b/ai_ta_backend/main.py index 4a5a140e..60d423a8 100644 --- a/ai_ta_backend/main.py +++ b/ai_ta_backend/main.py @@ -631,6 +631,35 @@ def export_convo_history(): return response +@app.route('/exportDocuments', methods=['GET']) +def exportDocuments(): + course_name: str = request.args.get('course_name', default='', type=str) + from_date: str = request.args.get('from_date', default='', type=str) + to_date: str = request.args.get('to_date', default='', type=str) + + if course_name == '': + # proper web error "400 Bad request" + abort(400, description=f"Missing required parameter: 'course_name' must be provided. Course name: `{course_name}`") + + export_status = export_documents_json(course_name, from_date, to_date) + print("EXPORT FILE LINKS: ", export_status) + + if export_status['response'] == "No data found between the given dates.": + response = Response(status=204) + response.headers.add('Access-Control-Allow-Origin', '*') + + elif export_status['response'] == "Download from S3": + response = jsonify({"response": "Download from S3", "s3_path": export_status['s3_path']}) + response.headers.add('Access-Control-Allow-Origin', '*') + + else: + response = make_response(send_from_directory(export_status['response'][2], export_status['response'][1], as_attachment=True)) + response.headers.add('Access-Control-Allow-Origin', '*') + response.headers["Content-Disposition"] = f"attachment; filename={export_status['response'][1]}" + os.remove(export_status['response'][0]) + + return response + @app.route('/getTopContextsWithMQR', methods=['GET']) def getTopContextsWithMQR() -> Response: