diff --git a/CHANGELOG.md b/CHANGELOG.md index 2826efa..b463e9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## untagged +- metadata: add support for `/shared/vendor/deltachat/irohrelay` + ([#284](https://github.com/deltachat/chatmail/pull/284)) + - Emit "XCHATMAIL" capability from IMAP server ([#278](https://github.com/deltachat/chatmail/pull/278)) diff --git a/chatmaild/src/chatmaild/config.py b/chatmaild/src/chatmaild/config.py index 03802df..f338989 100644 --- a/chatmaild/src/chatmaild/config.py +++ b/chatmaild/src/chatmaild/config.py @@ -20,6 +20,7 @@ class Config: self.passthrough_recipients = params["passthrough_recipients"].split() self.filtermail_smtp_port = int(params["filtermail_smtp_port"]) self.postfix_reinject_port = int(params["postfix_reinject_port"]) + self.iroh_relay = params.get("iroh_relay") self.privacy_postal = params.get("privacy_postal") self.privacy_mail = params.get("privacy_mail") self.privacy_pdo = params.get("privacy_pdo") diff --git a/chatmaild/src/chatmaild/metadata.py b/chatmaild/src/chatmaild/metadata.py index 582cd78..5b6d62e 100644 --- a/chatmaild/src/chatmaild/metadata.py +++ b/chatmaild/src/chatmaild/metadata.py @@ -8,6 +8,7 @@ from socketserver import ( UnixStreamServer, ) +from .config import read_config from .filedict import FileDict from .notifier import Notifier @@ -48,32 +49,40 @@ class Metadata: return mdict.get(self.DEVICETOKEN_KEY, []) -def handle_dovecot_protocol(rfile, wfile, notifier, metadata): +def handle_dovecot_protocol(rfile, wfile, notifier, metadata, iroh_relay=None): transactions = {} while True: msg = rfile.readline().strip().decode() if not msg: break - res = handle_dovecot_request(msg, transactions, notifier, metadata) + res = handle_dovecot_request(msg, transactions, notifier, metadata, iroh_relay) if res: wfile.write(res.encode("ascii")) wfile.flush() -def handle_dovecot_request(msg, transactions, notifier, metadata): +def handle_dovecot_request(msg, transactions, notifier, metadata, iroh_relay=None): # see https://doc.dovecot.org/3.0/developer_manual/design/dict_protocol/ short_command = msg[0] parts = msg[1:].split("\t") if short_command == DICTPROXY_LOOKUP_CHAR: # Lpriv/43f5f508a7ea0366dff30200c15250e3/devicetoken\tlkj123poi@c2.testrun.org - keyparts = parts[0].split("/") + keyparts = parts[0].split("/", 2) if keyparts[0] == "priv": keyname = keyparts[2] addr = parts[1] if keyname == metadata.DEVICETOKEN_KEY: res = " ".join(metadata.get_tokens_for_addr(addr)) return f"O{res}\n" + elif keyparts[0] == "shared": + keyname = keyparts[2] + if ( + keyname == "vendor/vendor.dovecot/pvt/server/vendor/deltachat/irohrelay" + and iroh_relay + ): + # Handle `GETMETADATA "" /shared/vendor/deltachat/irohrelay` + return f"O{iroh_relay}\n" logging.warning("lookup ignored: %r", msg) return "N\n" elif short_command == DICTPROXY_ITERATE_CHAR: @@ -119,7 +128,10 @@ class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer): def main(): - socket, vmail_dir = sys.argv[1:] + socket, vmail_dir, config_path = sys.argv[1:] + + config = read_config(config_path) + iroh_relay = config.iroh_relay vmail_dir = Path(vmail_dir) if not vmail_dir.exists(): @@ -135,7 +147,9 @@ def main(): class Handler(StreamRequestHandler): def handle(self): try: - handle_dovecot_protocol(self.rfile, self.wfile, notifier, metadata) + handle_dovecot_protocol( + self.rfile, self.wfile, notifier, metadata, iroh_relay + ) except Exception: logging.exception("Exception in the dovecot dictproxy handler") raise diff --git a/chatmaild/src/chatmaild/tests/test_metadata.py b/chatmaild/src/chatmaild/tests/test_metadata.py index c24bfbf..d93fb8e 100644 --- a/chatmaild/src/chatmaild/tests/test_metadata.py +++ b/chatmaild/src/chatmaild/tests/test_metadata.py @@ -296,3 +296,17 @@ def test_persistent_queue_items(tmp_path, testaddr, token): item2.delete() assert not item2.path.exists() assert not queue_item < item2 and not item2 < queue_item + + +def test_iroh_relay(metadata): + rfile = io.BytesIO( + b"\n".join( + [ + b"H", + b"Lshared/0123/vendor/vendor.dovecot/pvt/server/vendor/deltachat/irohrelay\tuser@example.org", + ] + ) + ) + wfile = io.BytesIO() + handle_dovecot_protocol(rfile, wfile, notifier, metadata, "https://example.org/") + assert wfile.getvalue() == b"Ohttps://example.org/\n" diff --git a/cmdeploy/src/cmdeploy/service/chatmail-metadata.service.f b/cmdeploy/src/cmdeploy/service/chatmail-metadata.service.f index 0ba43d9..a3ed905 100644 --- a/cmdeploy/src/cmdeploy/service/chatmail-metadata.service.f +++ b/cmdeploy/src/cmdeploy/service/chatmail-metadata.service.f @@ -2,7 +2,7 @@ Description=Chatmail dict proxy for IMAP METADATA [Service] -ExecStart={execpath} /run/chatmail-metadata/metadata.socket /home/vmail/mail/{mail_domain} +ExecStart={execpath} /run/chatmail-metadata/metadata.socket /home/vmail/mail/{mail_domain} {config_path} Restart=always RestartSec=30 User=vmail