summaryrefslogtreecommitdiff
path: root/src/jwebmail/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/jwebmail/model')
-rw-r--r--src/jwebmail/model/read_mails.py61
1 files changed, 50 insertions, 11 deletions
diff --git a/src/jwebmail/model/read_mails.py b/src/jwebmail/model/read_mails.py
index 534f2f7..c9cee7a 100644
--- a/src/jwebmail/model/read_mails.py
+++ b/src/jwebmail/model/read_mails.py
@@ -1,5 +1,6 @@
import os
from base64 import b64decode
+from functools import wraps
from socket import socketpair
import varlink
@@ -11,6 +12,28 @@ class QMAuthError(Exception):
self.rc = rc
+class JWebmailMailStorageError(Exception):
+ def __init__(self, err, params):
+ self.name = err
+ self.parameters = params
+
+
+def remap_errors(func):
+ prefix = "de.jmhoffmann.jwebmail.mail-storage."
+
+ @wraps(func)
+ def decorator(*args, **kvargs):
+ try:
+ return func(*args, **kvargs)
+ except varlink.VarlinkError as ex:
+ if (name := ex.error().removeprefix(prefix)) != ex.error():
+ raise JWebmailMailStorageError(name, ex.parameters())
+ else:
+ raise
+
+ return decorator
+
+
class QMailAuthuser:
def __init__(self, prog, mailbox_path, virtual_user, authenticator):
self._prog = prog
@@ -23,6 +46,7 @@ class QMailAuthuser:
self._client = None
self._connection = None
+ @remap_errors
def list_search(self, folder, bound, after, limit, sort, search):
sort_val = dict()
if sort[0] == "!":
@@ -64,6 +88,7 @@ class QMailAuthuser:
req["last"],
)
+ @remap_errors
def count(self, folder):
resp = self._connection.Stats(folder=folder)
return {
@@ -72,6 +97,7 @@ class QMailAuthuser:
"unread_mails": resp["unread_count"],
}
+ @remap_errors
def show(self, folder, msgid):
resp = self._connection.Show(folder=folder, mid=msgid)
return {
@@ -79,6 +105,7 @@ class QMailAuthuser:
"body": self._mail_body(resp["mail"]["body"]),
}
+ @remap_errors
def raw(self, folder, mid, path):
resp = self._connection.Raw(folder=folder, mid=mid, path=path)
return {
@@ -86,18 +113,22 @@ class QMailAuthuser:
"body": b64decode(resp["body"]),
}
+ @remap_errors
def folders(self):
resp = self._connection.Folders()
return list(resp["folders"]) + [""]
+ @remap_errors
def move(self, mid, from_f, to_f):
self._connection.Move(mid=mid, from_folder=from_f, to_folder=to_f)
return True
+ @remap_errors
def remove(self, folder, msgid):
self._connection.Remove(folder=folder, mid=msgid)
return True
+ @remap_errors
def add_folder(self, name):
resp = self._connection.AddFolder(name=name)
return resp["status"]
@@ -176,8 +207,8 @@ class QMailAuthuser:
assert False
def open(self, username, password):
- (rp, wp) = os.pipe()
- (sp, sc) = socketpair()
+ rp, wp = os.pipe()
+ sp, sc = socketpair()
cmdline = [self._authenticator, self._prog]
if (pid := os.fork()) == 0:
# child
@@ -204,24 +235,32 @@ class QMailAuthuser:
"de.jmhoffmann.jwebmail.mail-storage", connection=sp
)
except ConnectionResetError:
- (pid, status) = os.waitpid(pid, os.WNOHANG)
- if pid != 0:
- raise QMAuthError(os.waitstatus_to_exitcode(status))
+ pid, status = os.waitpid(self._pid, 0)
+ if (rc := os.waitstatus_to_exitcode(status)) != 0:
+ raise QMAuthError(rc)
else:
raise
user = username[: username.index("@")]
- self._connection.Init(
- unix_user=self._virtual_user,
- mailbox_path=os.path.join(self._mailbox_path, user),
- )
+ try:
+ self._connection.Init(
+ unix_user=self._virtual_user,
+ mailbox_path=os.path.join(self._mailbox_path, user),
+ )
+ except BrokenPipeError:
+ pid, status = os.waitpid(self._pid, 0)
+ assert pid == self._pid
+ if (rc := os.waitstatus_to_exitcode(status)) != 0:
+ raise QMAuthError(rc)
+ else:
+ raise
return self
def close(self):
self._connection.close()
self._socket.close()
- (pid, status) = os.waitpid(self._pid, 0)
+ pid, status = os.waitpid(self._pid, 0)
assert pid == self._pid
rc = os.waitstatus_to_exitcode(status)
if rc != 0:
@@ -234,7 +273,7 @@ class QMailAuthuser:
if ex_val is None:
self.close()
elif issubclass(ex_type, BrokenPipeError):
- (pid, _status) = os.waitpid(self._pid, 0)
+ pid, _status = os.waitpid(self._pid, 0)
assert pid == self._pid
return False