From f123729ed492f70de3db35c042874e5750bbea72 Mon Sep 17 00:00:00 2001 From: "Jannis M. Hoffmann" Date: Sat, 16 Nov 2024 23:27:12 +0100 Subject: properly implement move and remove added add_folder method to jwebmail api --- script/extract.py | 35 +++++++++++++++++++++++++++--- src/jwebmail/__init__.py | 17 +++++++++++++-- src/jwebmail/model/jwebmail.proto | 9 ++++++++ src/jwebmail/model/read_mails.py | 7 ++++++ src/jwebmail/static/src/dh-move-submit.js | 19 ++++++++++++++++ src/jwebmail/templates/_bot_nav.html | 10 ++++----- src/jwebmail/templates/displayheaders.html | 2 ++ src/jwebmail/webmail.py | 27 ++++++++++++++++++++--- 8 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 src/jwebmail/static/src/dh-move-submit.js diff --git a/script/extract.py b/script/extract.py index 3a3a17c..ab66869 100755 --- a/script/extract.py +++ b/script/extract.py @@ -33,7 +33,7 @@ from datetime import datetime from email.message import EmailMessage from itertools import islice from mailbox import Maildir, MaildirMessage -from os import environ, getpid, path, setuid +from os import environ, getpid, mkdir, path, setuid from pathlib import Path from pwd import getpwnam from sys import exit as sysexit @@ -448,7 +448,7 @@ def move_mail(f, req): fname = Path(f.get_filename(r.mid)) - assert r.to_f in f.list_folders() + assert r.to_f in f.list_folders() or r.to_f == "" sep = -2 if not r.from_f else -3 @@ -476,6 +476,23 @@ def remove_mail(f, req): return jwebmail.RemoveResp().SerializeToString() +def add_folder(f, req): + r = jwebmail.AddFolderReq() + r.ParseFromString(req) + + name = path.join(f._path, "." + r.name.translate(str.maketrans("/", "."))) + + if path.isdir(name): + return jwebmail.AddFolderResp(status=1).SerializeToString() + + mkdir(name) + mkdir(path.join(name, "cur")) + mkdir(path.join(name, "new")) + mkdir(path.join(name, "tmp")) + + return jwebmail.AddFolderResp(status=0).SerializeToString() + + def method_to_run(value): if value == "list": return list_mails @@ -493,6 +510,8 @@ def method_to_run(value): return remove_mail elif value == "search": return search_mails + elif value == "add_folder": + return add_folder else: raise ValueError(value) @@ -504,7 +523,17 @@ def parse_arguments(): ap.add_argument("mail_user") ap.add_argument( - "method", choices=["list", "count", "read", "raw", "folders", "move", "remove"] + "method", + choices=[ + "list", + "count", + "read", + "raw", + "folders", + "move", + "remove", + "add_folder", + ], ) return vars(ap.parse_args()) diff --git a/src/jwebmail/__init__.py b/src/jwebmail/__init__.py index 6ccca40..d692c30 100644 --- a/src/jwebmail/__init__.py +++ b/src/jwebmail/__init__.py @@ -22,6 +22,7 @@ from .webmail import ( logout, move, readmail, + remove, sendmail, writemail, ) @@ -35,7 +36,7 @@ else: toml_read_file = dict(load=toml_load, text=True) -__version__ = "2.5.0.dev2" +__version__ = "2.6.0.dev0" csrf = CSRFProtect() @@ -156,6 +157,18 @@ def route(app): methods=["POST"], ) + lr_move = login_required(move) + app.add_url_rule("//move/", view_func=lr_move, methods=["POST"]) + app.add_url_rule("//move/", view_func=lr_move, methods=["POST"]) + + lr_remove = login_required(remove) app.add_url_rule( - "//move/", view_func=login_required(move), methods=["POST"] + "//remove/", + view_func=lr_remove, + methods=["POST"], + ) + app.add_url_rule( + "//remove/", + view_func=lr_remove, + methods=["POST"], ) diff --git a/src/jwebmail/model/jwebmail.proto b/src/jwebmail/model/jwebmail.proto index bf1454a..e4cba3b 100644 --- a/src/jwebmail/model/jwebmail.proto +++ b/src/jwebmail/model/jwebmail.proto @@ -144,6 +144,14 @@ message RemoveReq { message RemoveResp { } +message AddFolderReq { + string name = 1; +} + +message AddFolderResp { + int32 status = 1; +} + service MailService { rpc List(ListReq) returns (ListResp); rpc Stats(StatsReq) returns (StatsResp); @@ -153,4 +161,5 @@ service MailService { rpc Folders(FoldersReq) returns (FoldersResp); rpc Move(MoveReq) returns (MoveResp); rpc Remove(RemoveReq) returns (RemoveResp); + rpc AddFolder(AddFolderReq) returns (AddFolderResp); } diff --git a/src/jwebmail/model/read_mails.py b/src/jwebmail/model/read_mails.py index 769589f..633c358 100644 --- a/src/jwebmail/model/read_mails.py +++ b/src/jwebmail/model/read_mails.py @@ -114,6 +114,13 @@ class QMailAuthuser: r.ParseFromString(resp) return True + def add_folder(self, name): + req = pb2.AddFolderReq(name=name) + resp = self.build_and_run("add_folder", req.SerializeToString()) + r = pb2.AddFolderResp() + r.ParseFromString(resp) + return r.status + @staticmethod def _address(addr): if not addr: diff --git a/src/jwebmail/static/src/dh-move-submit.js b/src/jwebmail/static/src/dh-move-submit.js new file mode 100644 index 0000000..cf16f9c --- /dev/null +++ b/src/jwebmail/static/src/dh-move-submit.js @@ -0,0 +1,19 @@ +function add_mail_ids(form_id) { + const chkbox = document.getElementsByClassName("jwm-mail-checkbox"); + const move_form = document.getElementById(form_id); + + for (const m of chkbox) { + if (m.checked) { + let inp = document.createElement("input"); + inp.setAttribute("type", "hidden"); + inp.setAttribute("name", "mail"); + inp.setAttribute("value", m.name); + move_form.append(inp); + } + } +} + +document.addEventListener("DOMContentLoaded", function() { + document.getElementById("move").addEventListener("click", () => add_mail_ids("move-mail")); + document.getElementById("remove").addEventListener("click", () => add_mail_ids("remove-mail")); +}); diff --git a/src/jwebmail/templates/_bot_nav.html b/src/jwebmail/templates/_bot_nav.html index e2be5f5..73a5170 100644 --- a/src/jwebmail/templates/_bot_nav.html +++ b/src/jwebmail/templates/_bot_nav.html @@ -7,8 +7,8 @@
{% if mail_folders|length > 1 %} -
- {{ form.csrf_token }} + +
@@ -22,16 +22,16 @@
- +
{% endif %} -
- {{ from.csrf_token }} +
diff --git a/src/jwebmail/templates/displayheaders.html b/src/jwebmail/templates/displayheaders.html index 36a1f68..47bb587 100644 --- a/src/jwebmail/templates/displayheaders.html +++ b/src/jwebmail/templates/displayheaders.html @@ -7,6 +7,8 @@ + {% endblock %} diff --git a/src/jwebmail/webmail.py b/src/jwebmail/webmail.py index cb4d5db..9c446c2 100644 --- a/src/jwebmail/webmail.py +++ b/src/jwebmail/webmail.py @@ -190,11 +190,11 @@ def writemail(): return render_template("writemail.html", form=WriteForm()) -def move(folder): +def move(folder=""): folders = get_read_mails_logged_in().folders() - mm = request.args.getlist("mail") - to_folder = request.args["folder"] + mm = request.form.getlist("mail") + to_folder = request.form["select-folder"] if folder not in folders or to_folder not in folders: raise ValueError("folder not valid") @@ -206,6 +206,27 @@ def move(folder): return redirect(url_for("displayheaders"), 303) +def remove(folder=""): + folders = get_read_mails_logged_in().add_folder("Trash") + + mm = request.form.getlist("mail") + + folders = get_read_mails_logged_in().folders() + + if folder not in folders: + raise ValueError("folder not valid") + + if folder == "Trash": + for m in mm: + get_read_mails_logged_in().remove(m, folder) + else: + for m in mm: + get_read_mails_logged_in().move(m, folder, "Trash") + + flash(gettext("succ_remove")) + return redirect(url_for("displayheaders"), 303) + + def sendmail(): form = WriteForm() -- cgit v1.2.3