summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscript/extract.py35
-rw-r--r--src/jwebmail/__init__.py17
-rw-r--r--src/jwebmail/model/jwebmail.proto9
-rw-r--r--src/jwebmail/model/read_mails.py7
-rw-r--r--src/jwebmail/static/src/dh-move-submit.js19
-rw-r--r--src/jwebmail/templates/_bot_nav.html10
-rw-r--r--src/jwebmail/templates/displayheaders.html2
-rw-r--r--src/jwebmail/webmail.py27
8 files changed, 113 insertions, 13 deletions
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("/<lang_code>/move/", view_func=lr_move, methods=["POST"])
+ app.add_url_rule("/<lang_code>/move/<folder>", view_func=lr_move, methods=["POST"])
+
+ lr_remove = login_required(remove)
app.add_url_rule(
- "/<lang_code>/move/<folder>", view_func=login_required(move), methods=["POST"]
+ "/<lang_code>/remove/",
+ view_func=lr_remove,
+ methods=["POST"],
+ )
+ app.add_url_rule(
+ "/<lang_code>/remove/<folder>",
+ 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 @@
<div class="column">
{% if mail_folders|length > 1 %}
- <form href="{{ url_for('move', folder=folder) }}" id='move-mail' class=is-pulled-left>
- {{ form.csrf_token }}
+ <form action="{{ url_for('move', folder=folder) }}" id="move-mail" class=is-pulled-left method=POST>
+ <input type=hidden name=csrf_token value="{{ csrf_token() }}">
<div class="field has-addons">
<div class=control>
<div class=select>
@@ -22,16 +22,16 @@
</div>
</div>
<div class=control>
- <input type=submit class=button value="{{ gettext('Move') }}">
+ <input id=move type=submit class=button value="{{ gettext('Move') }}">
</div>
</div>
</form>
{% endif %}
- <form href="{{ url_for('move', folder=folder) }}" id="remove-mail"
+ <form action="{{ url_for('remove', folder=folder) }}" id="remove-mail"
method=POST class="is-pulled-left ml-2">
- {{ from.csrf_token }}
+ <input type=hidden name=csrf_token value="{{ csrf_token() }}">
<div class=control>
<input id=remove type=submit class=button value="{{ gettext('Remove') }}">
</div>
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 @@
</script>
<script src="{{ url_for('static', filename='src/dh-submit-sort-on-change.js') }}" defer>
</script>
+ <script src="{{ url_for('static', filename='src/dh-move-submit.js') }}" defer>
+ </script>
<script src="{{ url_for('static', filename='src/localtime.js') }}" defer>
</script>
{% 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()