201 lines
5.8 KiB
Python
201 lines
5.8 KiB
Python
"""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)
|
|
|
|
# Change permissions to 0600
|
|
os.chmod(filepath, 0o600)
|
|
|
|
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/<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/<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
|