"""Provide basic settings and views""" import fileinput import os import re import shutil from pathlib import Path from flask import abort, request, render_template from flask_basicauth import BasicAuth from jinja2 import Template from autoreply_editor import app basic_auth = BasicAuth(app) def qmail_status(user): """Find out whether the filter is currently activated for the given mail user""" with open(get_qmailfile(user), encoding="utf8") as qmailfile: # trigger to check whether we have to re-open the file for initialisation initialise = False # try to find active filter if re.search( rf"{get_maildropline(user, active=True, regex=True)}", qmailfile.read(), re.MULTILINE, ): return True else: # jump back to top of file because we've read it in the "if" qmailfile.seek(0) # filter is deactivated (commented) if re.search( rf"{get_maildropline(user, active=False, regex=True)}", qmailfile.read(), re.MULTILINE, ): return False # The maildrop line does not exist in the expected form else: initialise = True # Append a commented filter command to the file if initialise: with open(get_qmailfile(user), mode="a", encoding="utf8") as qmailfile: qmailfile.write(f"{get_maildropline(user, active=False)}") return False def check_user(user): """Check if user exists""" fulluser = [ item for item in app.config.get("USERS") if item[1].split("@")[0] == user ] if not fulluser: return False else: return fulluser[0] def get_messagefile(user): """Return message file of user, and create if necessary""" # Path of the project gitpath = str(Path(app.root_path).parent) # File name of the message filename = f"message-{user}.txt" # Combine path filepath = os.path.join(gitpath, filename) if not os.path.isfile(filepath): Path(filepath).touch() return filepath def get_qmailfile(user): """Return qmail file of user, and create if necessary based on default qmail""" qmail_base = f"{str(Path.home())}/.qmail" filepath = f"{qmail_base}-{user}" if not os.path.isfile(filepath): shutil.copy(f"{qmail_base}-default", filepath) return filepath def get_filterfile(user): """Return .filter-autoreply file of user, and create if necessary""" filter_base = f"{str(Path.home())}/.filter-autoreply" filepath = f"{filter_base}-{user}" if not os.path.isfile(filepath): with open( os.path.join(app.root_path, "templates/filterfile.j2"), encoding="utf-8" ) as template: filterconfig = Template(template.read()).render( email=check_user(user)[1], user=user, name=check_user(user)[0], messagefile=get_messagefile(user), ) with open(filepath, "w", encoding="utf-8") as filterfile: filterfile.write(filterconfig) return filepath def get_maildropline(user, active=True, regex=False): """ Define the line calling maildrop, with options to have the line disabled or in Regex format """ base = f"|maildrop {get_filterfile(user)}" # If the filter should be inactive, we comment it if not active: base = f"#{base}" # depending on whether it should be RE escaped or not, return the line if regex: return f"^{re.escape(base)}$" else: return base @app.route("/") def index(): """Index page listing available users""" return render_template( "index.html", users=app.config.get("USERS"), ) @app.route("/user/") def user_status(user): """Status for specific user""" # Check if user is valid if not check_user(user): abort(404) with open(get_messagefile(user), "r", encoding="utf-8") as messagefile: message = messagefile.read() return render_template( "user.html", message=message, qmail_status=qmail_status(user), ) @app.route("/user/", methods=["POST"]) def user_update(user): """Update user with POST request""" # Check if user is valid if not check_user(user): abort(404) if request.form["action"] == "message": input_message = request.form["message"] with open(get_messagefile(user), "w", encoding="utf-8") as messagefile: messagefile.write(str(input_message)) result = "Success: The autoreply message has been updated!" if request.form["action"] == "qmail": # define whether to set a comment if request.form["status"] == "on": state_current = get_maildropline(user, active=False) state_desired = get_maildropline(user) else: state_current = get_maildropline(user) state_desired = get_maildropline(user, active=False) with fileinput.FileInput( get_qmailfile(user), inplace=True, ) as qmailfile: for line in qmailfile: print( line.replace(state_current, state_desired), end="", ) result = f"Success: the autoreply is now {request.form['status']}." try: return render_template("update.html", user=user, result=result) except UnboundLocalError: return render_template( "update.html", user=user, result="Something went terribly wrong!" ) @app.errorhandler(404) def page_not_found(error): """Error for 404""" return render_template("error.html", error=error), 404