From 5aa4d805aa63d81f6897506694fcfc368f93b356 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Sun, 1 Mar 2026 23:51:44 +0100 Subject: [PATCH] feat: allow to run the test suite against underscore-domain relays Such relays serve self-signed certificates, and are created e.g. by cmlxc deploys. --- .../src/deltachat_rpc_client/pytestplugin.py | 27 ++++++++++++++----- deltachat-rpc-client/tests/conftest.py | 6 ++++- .../tests/test_iroh_webxdc.py | 9 +++++++ python/src/deltachat/direct_imap.py | 7 ++++- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/pytestplugin.py b/deltachat-rpc-client/src/deltachat_rpc_client/pytestplugin.py index 8f78420c3..dc2674da4 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/pytestplugin.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/pytestplugin.py @@ -9,6 +9,7 @@ import platform import random import subprocess import sys +import urllib.parse from typing import AsyncGenerator, Optional import pytest @@ -280,10 +281,16 @@ def alice_and_remote_bob(tmp_path, acfactory, get_core_python_env): accounts_dir = str(tmp_path.joinpath("account1_venv1")) channel = gw.remote_exec(remote_bob_loop) - cm = os.environ.get("CHATMAIL_DOMAIN") + + # old cores need "ic=3" to accept + # the self-signed cert of an underscore domain + addr, password = acfactory.get_credentials() + dclogin_qr = f"dclogin://{urllib.parse.quote(addr, safe='@')}?p={urllib.parse.quote(password)}&v=1" + if os.environ["CHATMAIL_DOMAIN"].startswith("_"): + dclogin_qr += "&ic=3" # trigger getting an online account on bob's side - channel.send((accounts_dir, str(rpc_server_path), cm)) + channel.send((accounts_dir, str(rpc_server_path), dclogin_qr)) # meanwhile get a local alice account alice = acfactory.get_online_account() @@ -315,10 +322,8 @@ def remote_bob_loop(channel): import os from deltachat_rpc_client import DeltaChat, Rpc - from deltachat_rpc_client.pytestplugin import ACFactory - accounts_dir, rpc_server_path, chatmail_domain = channel.receive() - os.environ["CHATMAIL_DOMAIN"] = chatmail_domain + accounts_dir, rpc_server_path, dclogin_qr = channel.receive() # older core versions don't support specifying rpc_server_path # so we can't just pass `rpc_server_path` argument to Rpc constructor @@ -329,8 +334,16 @@ def remote_bob_loop(channel): with rpc: dc = DeltaChat(rpc) channel.send(dc.rpc.get_system_info()["deltachat_core_version"]) - acfactory = ACFactory(dc) - bob = acfactory.get_online_account() + + # ACFactory would configure from a "dcaccount" QR, + # which old cores cannot use on underscore domains + bob = dc.add_account() + bob.set_config_from_qr(dclogin_qr) + if not bob.is_configured(): + # cores <=2.22 only store login values from a "dclogin" QR + bob.configure() + bob.bring_online() + alice_vcard = channel.receive() [alice_contact] = bob.import_vcard(alice_vcard) ns = {"bob": bob, "bob_contact_alice": alice_contact} diff --git a/deltachat-rpc-client/tests/conftest.py b/deltachat-rpc-client/tests/conftest.py index 75de80869..b8f160045 100644 --- a/deltachat-rpc-client/tests/conftest.py +++ b/deltachat-rpc-client/tests/conftest.py @@ -37,7 +37,11 @@ class DirectImap: host = user.rsplit("@")[-1] pw = self.account.get_config("mail_pw") - self.conn = MailBox(host, port, ssl_context=ssl.create_default_context()) + ssl_context = ssl.create_default_context() + if host.startswith("_"): + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE + self.conn = MailBox(host, port, ssl_context=ssl_context) self.conn.login(user, pw) self.select_folder("INBOX") diff --git a/deltachat-rpc-client/tests/test_iroh_webxdc.py b/deltachat-rpc-client/tests/test_iroh_webxdc.py index 4162f9710..f79ea7862 100644 --- a/deltachat-rpc-client/tests/test_iroh_webxdc.py +++ b/deltachat-rpc-client/tests/test_iroh_webxdc.py @@ -17,6 +17,15 @@ import pytest from deltachat_rpc_client import EventType +# Relays on underscore domains advertise themselves as iroh relay +# but serve a self-signed certificate that iroh's TLS stack rejects. +# Skipping instead of xfailing keeps the run fast: +# these tests only fail after waiting for realtime connections to time out. +pytestmark = pytest.mark.skipif( + os.environ.get("CHATMAIL_DOMAIN", "").startswith("_"), + reason="iroh does not accept the self-signed certificate of an underscore domain", +) + @pytest.fixture def path_to_webxdc(request): diff --git a/python/src/deltachat/direct_imap.py b/python/src/deltachat/direct_imap.py index b1074a63e..aa3e222e5 100644 --- a/python/src/deltachat/direct_imap.py +++ b/python/src/deltachat/direct_imap.py @@ -43,9 +43,14 @@ class DirectImap: host = user.rsplit("@")[-1] pw = self.account.get_config("mail_pw") + ssl_context = ssl.create_default_context() + if host.startswith("_"): + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE + while True: try: - self.conn = MailBox(host, port, ssl_context=ssl.create_default_context()) + self.conn = MailBox(host, port, ssl_context=ssl_context) self.conn.login(user, pw) self.select_folder("INBOX") return