metadata: add support for /shared/vendor/deltachat/irohrelay

This commit is contained in:
link2xt 2024-05-05 20:57:06 +00:00
parent c1163228f6
commit 76b56d7b78
5 changed files with 39 additions and 7 deletions

View File

@ -2,6 +2,9 @@
## untagged ## untagged
- metadata: add support for `/shared/vendor/deltachat/irohrelay`
([#284](https://github.com/deltachat/chatmail/pull/284))
- Emit "XCHATMAIL" capability from IMAP server - Emit "XCHATMAIL" capability from IMAP server
([#278](https://github.com/deltachat/chatmail/pull/278)) ([#278](https://github.com/deltachat/chatmail/pull/278))

View File

@ -20,6 +20,7 @@ class Config:
self.passthrough_recipients = params["passthrough_recipients"].split() self.passthrough_recipients = params["passthrough_recipients"].split()
self.filtermail_smtp_port = int(params["filtermail_smtp_port"]) self.filtermail_smtp_port = int(params["filtermail_smtp_port"])
self.postfix_reinject_port = int(params["postfix_reinject_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_postal = params.get("privacy_postal")
self.privacy_mail = params.get("privacy_mail") self.privacy_mail = params.get("privacy_mail")
self.privacy_pdo = params.get("privacy_pdo") self.privacy_pdo = params.get("privacy_pdo")

View File

@ -8,6 +8,7 @@ from socketserver import (
UnixStreamServer, UnixStreamServer,
) )
from .config import read_config
from .filedict import FileDict from .filedict import FileDict
from .notifier import Notifier from .notifier import Notifier
@ -48,32 +49,40 @@ class Metadata:
return mdict.get(self.DEVICETOKEN_KEY, []) 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 = {} transactions = {}
while True: while True:
msg = rfile.readline().strip().decode() msg = rfile.readline().strip().decode()
if not msg: if not msg:
break break
res = handle_dovecot_request(msg, transactions, notifier, metadata) res = handle_dovecot_request(msg, transactions, notifier, metadata, iroh_relay)
if res: if res:
wfile.write(res.encode("ascii")) wfile.write(res.encode("ascii"))
wfile.flush() 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/ # see https://doc.dovecot.org/3.0/developer_manual/design/dict_protocol/
short_command = msg[0] short_command = msg[0]
parts = msg[1:].split("\t") parts = msg[1:].split("\t")
if short_command == DICTPROXY_LOOKUP_CHAR: if short_command == DICTPROXY_LOOKUP_CHAR:
# Lpriv/43f5f508a7ea0366dff30200c15250e3/devicetoken\tlkj123poi@c2.testrun.org # Lpriv/43f5f508a7ea0366dff30200c15250e3/devicetoken\tlkj123poi@c2.testrun.org
keyparts = parts[0].split("/") keyparts = parts[0].split("/", 2)
if keyparts[0] == "priv": if keyparts[0] == "priv":
keyname = keyparts[2] keyname = keyparts[2]
addr = parts[1] addr = parts[1]
if keyname == metadata.DEVICETOKEN_KEY: if keyname == metadata.DEVICETOKEN_KEY:
res = " ".join(metadata.get_tokens_for_addr(addr)) res = " ".join(metadata.get_tokens_for_addr(addr))
return f"O{res}\n" 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) logging.warning("lookup ignored: %r", msg)
return "N\n" return "N\n"
elif short_command == DICTPROXY_ITERATE_CHAR: elif short_command == DICTPROXY_ITERATE_CHAR:
@ -119,7 +128,10 @@ class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer):
def main(): 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) vmail_dir = Path(vmail_dir)
if not vmail_dir.exists(): if not vmail_dir.exists():
@ -135,7 +147,9 @@ def main():
class Handler(StreamRequestHandler): class Handler(StreamRequestHandler):
def handle(self): def handle(self):
try: try:
handle_dovecot_protocol(self.rfile, self.wfile, notifier, metadata) handle_dovecot_protocol(
self.rfile, self.wfile, notifier, metadata, iroh_relay
)
except Exception: except Exception:
logging.exception("Exception in the dovecot dictproxy handler") logging.exception("Exception in the dovecot dictproxy handler")
raise raise

View File

@ -296,3 +296,17 @@ def test_persistent_queue_items(tmp_path, testaddr, token):
item2.delete() item2.delete()
assert not item2.path.exists() assert not item2.path.exists()
assert not queue_item < item2 and not item2 < queue_item 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"

View File

@ -2,7 +2,7 @@
Description=Chatmail dict proxy for IMAP METADATA Description=Chatmail dict proxy for IMAP METADATA
[Service] [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 Restart=always
RestartSec=30 RestartSec=30
User=vmail User=vmail