From 81418455cdfef62ac6186efdb94f81a0ccf3afc9 Mon Sep 17 00:00:00 2001 From: David Rotermund <54365609+davrot@users.noreply.github.com> Date: Tue, 9 Apr 2024 20:09:22 +0200 Subject: [PATCH] Add files via upload --- user_tools/allowed_domains.json | 5 ++ user_tools/blocked_users.json | 5 ++ user_tools/check_mailbox.py | 58 ------------------- user_tools/config_mail.json | 8 ++- user_tools/does_user_exists.py | 13 +++++ user_tools/exec_docker.py | 26 +++++++++ user_tools/get_activation_requests.py | 2 +- user_tools/prepare.sh | 1 + user_tools/process_emails.py | 68 ++++++++++++++++++++++ user_tools/process_invitations.py | 81 +++++++++++++++++++++++++++ user_tools/send_mail.py | 21 +++++++ 11 files changed, 228 insertions(+), 60 deletions(-) create mode 100644 user_tools/allowed_domains.json create mode 100644 user_tools/blocked_users.json create mode 100644 user_tools/does_user_exists.py create mode 100644 user_tools/exec_docker.py create mode 100644 user_tools/process_emails.py create mode 100644 user_tools/process_invitations.py create mode 100644 user_tools/send_mail.py diff --git a/user_tools/allowed_domains.json b/user_tools/allowed_domains.json new file mode 100644 index 0000000..46672e3 --- /dev/null +++ b/user_tools/allowed_domains.json @@ -0,0 +1,5 @@ +{ + "allowed_domains": [ + "uni-bremen.de" + ] +} \ No newline at end of file diff --git a/user_tools/blocked_users.json b/user_tools/blocked_users.json new file mode 100644 index 0000000..dab8b76 --- /dev/null +++ b/user_tools/blocked_users.json @@ -0,0 +1,5 @@ +{ + "blocked_users": [ + "" + ] +} \ No newline at end of file diff --git a/user_tools/check_mailbox.py b/user_tools/check_mailbox.py index 7629ae5..542090e 100644 --- a/user_tools/check_mailbox.py +++ b/user_tools/check_mailbox.py @@ -1,8 +1,5 @@ -# pip install email_validator import imaplib import json -import email.utils -from email_validator import validate_email, EmailNotValidError # type: ignore def check_mails( @@ -64,58 +61,3 @@ def check_mails( imap_connection.close() return result - - -def process_emails( - mail_to_process: list[dict], - config_file: str = "allowed_domains.json", - blocked_user_file: str = "blocked_users.json", -) -> list[dict]: - - result: list[dict] = [] - - with open(config_file, "r") as file: - allowed_domains: dict = json.load(file) - - with open(blocked_user_file, "r") as file: - blocked_users: dict = json.load(file) - - for mail in mail_to_process: - temp = email.utils.parseaddr(mail["from"])[1] - if (temp != "") and (temp is not None): - - email_status: bool = False - - try: - emailinfo = validate_email(temp, check_deliverability=False) - email_status = True - temp = emailinfo.normalized - except EmailNotValidError: - email_status = False - - domain_found = False - if email_status: - for domain in allowed_domains["allowed_domains"]: - if temp.endswith(domain): - domain_found = True - - if domain_found: - for blocked_user in blocked_users["blocked_users"]: - if temp == blocked_user: - domain_found = False - - if domain_found: - from_validated_ab = email.utils.parseaddr(mail["from"]) - from_validated = validate_email( - from_validated_ab[1], check_deliverability=False - ) - result.append( - { - "from_a": from_validated_ab[0], - "from_b": from_validated.normalized, - "to": mail["to"], - "subject": mail["subject"], - } - ) - - return result diff --git a/user_tools/config_mail.json b/user_tools/config_mail.json index 9115e69..854983b 100644 --- a/user_tools/config_mail.json +++ b/user_tools/config_mail.json @@ -1 +1,7 @@ -{"overleafdomain": "https://overleaf.neuro.uni-bremen.de"} \ No newline at end of file +{ + "overleafdomain": "https://overleaf.neuro.uni-bremen.de", + "user": "XXXXXX", + "password": "XXXXXX", + "host": "XXXXX", + "port": 993 +} \ No newline at end of file diff --git a/user_tools/does_user_exists.py b/user_tools/does_user_exists.py new file mode 100644 index 0000000..e47840a --- /dev/null +++ b/user_tools/does_user_exists.py @@ -0,0 +1,13 @@ +import pymongo + + +def does_user_exists(email_to_find: str) -> bool: + client = pymongo.MongoClient("overleafmongo", 27017) + db = client.sharelatex + users = db.users + + search_result = users.find_one({"email": email_to_find}) + if search_result is None: + return False + else: + return True diff --git a/user_tools/exec_docker.py b/user_tools/exec_docker.py new file mode 100644 index 0000000..bc37dfe --- /dev/null +++ b/user_tools/exec_docker.py @@ -0,0 +1,26 @@ +import docker + + +def identify_container(client, label: str = "overleaf") -> int | None: + + containers = client.containers.list(all=True) + for container in containers: + if str(container.name) == label: + return container.id + + return None + + +def docker_exec(exec_command: str = "ls") -> tuple[bool, str]: + client = docker.from_env() + docker_id = identify_container(client) + assert docker_id is not None + container = client.containers.get(docker_id) + command = f'/bin/bash -c "{exec_command}"' + + try: + result = container.exec_run(command, stream=False) + result_string: str = result.output + return True, result_string + except docker.errors.APIError as e: + return False, str("") diff --git a/user_tools/get_activation_requests.py b/user_tools/get_activation_requests.py index 4fb7002..9d0012b 100644 --- a/user_tools/get_activation_requests.py +++ b/user_tools/get_activation_requests.py @@ -8,7 +8,7 @@ import json def get_activation_requests(remove_old_entries: bool = False) -> list[dict]: results: list[dict] = [] - filename = "last_run.pkl" + filename = "last_run_activations.pkl" with open("config_mail.json", "r") as file: config = json.load(file) diff --git a/user_tools/prepare.sh b/user_tools/prepare.sh index f8bece1..0bbbb7e 100644 --- a/user_tools/prepare.sh +++ b/user_tools/prepare.sh @@ -1,4 +1,5 @@ apk add mc +apk add bash pip install docker pip install pymongo pip install email_validator diff --git a/user_tools/process_emails.py b/user_tools/process_emails.py new file mode 100644 index 0000000..d8ae954 --- /dev/null +++ b/user_tools/process_emails.py @@ -0,0 +1,68 @@ +# pip install email_validator + +import email.utils +from email_validator import validate_email # type: ignore +import email_validator +import json + + +def process_emails( + mail_to_process: list[dict], + config_file: str = "allowed_domains.json", + blocked_user_file: str = "blocked_users.json", +) -> list[dict]: + + result: list[dict] = [] + + with open(config_file, "r") as file: + allowed_domains: dict = json.load(file) + + with open(blocked_user_file, "r") as file: + blocked_users: dict = json.load(file) + + for mail in mail_to_process: + temp = email.utils.parseaddr(mail["from"])[1] + if (temp != "") and (temp is not None): + + email_status: bool = False + + try: + emailinfo = validate_email(temp, check_deliverability=False) + email_status = True + temp = emailinfo.normalized + except email_validator.exceptions_types.EmailSyntaxError: + email_status = False + except email_validator.exceptions_types.EmailNotValidError: + email_status = False + + domain_found = False + if email_status: + for domain in allowed_domains["allowed_domains"]: + if temp.endswith(domain): + domain_found = True + + if domain_found: + for blocked_user in blocked_users["blocked_users"]: + if temp == blocked_user: + domain_found = False + + if domain_found: + from_validated_ab = email.utils.parseaddr(mail["from"]) + try: + from_validated = validate_email( + from_validated_ab[1], check_deliverability=False + ) + result.append( + { + "from_a": from_validated_ab[0], + "from_b": from_validated.normalized, + "to": mail["to"], + "subject": mail["subject"], + } + ) + except email_validator.exceptions_types.EmailSyntaxError: + pass + except email_validator.exceptions_types.EmailNotValidError: + pass + + return result diff --git a/user_tools/process_invitations.py b/user_tools/process_invitations.py new file mode 100644 index 0000000..ef417de --- /dev/null +++ b/user_tools/process_invitations.py @@ -0,0 +1,81 @@ +import pymongo +import datetime +import os +import pickle +import email.utils +from email_validator import validate_email # type: ignore +import email_validator + + +def process_invitations(remove_old_entries: bool = False): + + results: list[dict] = [] + + filename = "last_run_invitations.pkl" + + now = datetime.datetime.now() + + client = pymongo.MongoClient("overleafmongo", 27017) + db = client.sharelatex + project_invites = db.projectInvites + + continue_at_time = None + if remove_old_entries: + if os.path.exists(filename): + with open(filename, "rb") as file: + continue_at_time = pickle.load(file) + + query = {"expires": {"$gt": now}} + if continue_at_time is not None: + query["createdAt"] = {"$gt": continue_at_time} + + newest = None + for project_invite in project_invites.find(query): + if newest is None: + newest = project_invite["createdAt"] + elif project_invite["createdAt"] > newest: + newest = project_invite["createdAt"] + + # Freeze time. We don't want to misshandle item that are newer than the last check + if newest is not None: + if "createdAt" in query: + query["createdAt"] = {"$gt": continue_at_time, "$lte": newest} + else: + query["createdAt"] = {"$lte": newest} + + # Find unique user ids + user_id_set = set() + + for project_invite in project_invites.find(query): + user_id_set.add(project_invite["email"]) + + user_ids = list(user_id_set) + + # Store the time stamp for newest + with open(filename, "wb") as file: + pickle.dump(newest, file) + + for uid in user_ids: + + from_validated_ab = email.utils.parseaddr(uid) + try: + from_validated = validate_email( + from_validated_ab[1], check_deliverability=False + ) + results.append( + { + "from_a": None, + "from_b": from_validated.normalized, + "to": None, + "subject": None, + } + ) + except email_validator.exceptions_types.EmailSyntaxError: + pass + except email_validator.exceptions_types.EmailNotValidError: + pass + + return results + + +print(process_invitations()) diff --git a/user_tools/send_mail.py b/user_tools/send_mail.py new file mode 100644 index 0000000..f39dbf4 --- /dev/null +++ b/user_tools/send_mail.py @@ -0,0 +1,21 @@ +import smtplib +from email.message import EmailMessage + + +def send_mail( + email_body: str, + email_subject: str, + email_from: str, + email_to: str, + smtpd_host: str = "overleafsmtpd", +): + + msg = EmailMessage() + msg.set_content(email_body.decode("utf-8")) + msg["Subject"] = email_subject + msg["From"] = email_from + msg["To"] = email_to + + s = smtplib.SMTP(smtpd_host) + s.send_message(msg) + s.quit()