diff options
Diffstat (limited to 'src/jwebmail/model')
-rw-r--r-- | src/jwebmail/model/read_mails.py | 61 |
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 |