[PATCH liblore] utils: extract message-ID before clean_header to fix Gnus In-Reply-To

Marc-André Lureau <[email protected]> Tue, 21 Jul 2026 11:41:51 +0400
Newsgroups org.kernel.linux.tools
Message-ID <[email protected]>
When an In-Reply-To header contains both a message-ID and RFC 2047
encoded words (as produced by Gnus), clean_header() would enter the
email-address parsing path and destroy the message-ID.  This caused
get_clean_msgid() to return None for the In-Reply-To header, making
the follow-up trailer logic fall back to References and pick the
cover letter as parent, which then broadcast the trailer to all
patches via add_cover_trailers().

tests: add test for get_clean_msgid with Gnus-style In-Reply-To

Co-Authored-By: Claude Opus 4.6 <[email protected]>
---
Signed-off-by: Marc-André Lureau <[email protected]>
---
 src/liblore/utils.py  |  8 +++++++-
 tests/test_message.py | 10 ++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/liblore/utils.py b/src/liblore/utils.py
index 04823bf..73be4d6 100644
--- a/src/liblore/utils.py
+++ b/src/liblore/utils.py
@@ -82,7 +82,13 @@ def get_clean_msgid(msg: EmailMessage, header: str = 'Message-Id') -> str | None
     """Extract a clean message ID (without angle brackets) from a header."""
     raw = msg.get(header)
     if raw:
-        matches = re.search(r'<([^>]+)>', clean_header(raw))
+        # Try the raw value first — message-IDs are always in angle brackets
+        # and never need RFC 2047 decoding.  Passing through clean_header()
+        # can destroy the value when the header also contains encoded words
+        # (e.g. Gnus-style In-Reply-To with a display-name comment).
+        matches = re.search(r'<([^>]+)>', raw)
+        if not matches:
+            matches = re.search(r'<([^>]+)>', clean_header(raw))
         if matches:
             return matches.groups()[0]
     return None
diff --git a/tests/test_message.py b/tests/test_message.py
index 77c4cd4..6d3aa84 100644
--- a/tests/test_message.py
+++ b/tests/test_message.py
@@ -50,6 +50,16 @@ class TestGetCleanMsgid:
         msg = make_msg(in_reply_to='[email protected]')
         assert get_clean_msgid(msg, 'In-Reply-To') == '[email protected]'
 
+    def test_in_reply_to_with_encoded_comment(self) -> None:
+        """Gnus adds an RFC 2047 encoded comment after the message-ID."""
+        msg = EmailMessage()
+        msg['In-Reply-To'] = (
+            '<[email protected]>'
+            ' (=?utf-8?Q?=22Marc-Andr=C3=A9?= Lureau"\'s'
+            ' message of "Mon, 20 Jul 2026 11:55:30 +0400")'
+        )
+        assert get_clean_msgid(msg, 'In-Reply-To') == '[email protected]'
+
 
 class TestParseMessage:
     def test_roundtrip(self) -> None:

---
base-commit: a20d90228c111908d1af6f7de583bfcf9197c0ad
change-id: 20260721-fix-gnus-in-reply-to-0f4194139202

Best regards,
--  
Marc-André Lureau <[email protected]>