Hi,

after proposing the initial version of `notmuch-autocrypt` last year,
I have finally gotten around to digging deeper into notmuch itself.
As you might have noticed by reading my other mails to this list, my
primary motivation for working on `notmuch-autocrypt` is to improve
the interoperability between notmuch and Delta Chat. Delta Chat has
recently started to extend the use of RFC 9788-style email header
protection. Specifically, the latest stable release of Delta Chat seems
to use header protection for the following headers (at the very least):

* Subject (this is already supported by notmuch)
* From, To, and Date (still missing in notmuch)
* Autocrypt (also missing in notmuch)

Attached, you find a patch set that addresses these issues -- as well
as some of the steps towards Autocrypt support discussed in November
last year. The patch set is structured as follows:

* Patch 0001-* adds test cases covering protected From, To, and Date
  headers as produced by Delta Chat.
* Patch 0002-* adds support for protected From, To, Cc, Bcc, Reply-To,
  and Date headers. This fixes the test cases added in patch 0001-*. I
  added Cc, Bcc, and Reply-To to this patch as they seemed to be easy
  targets where I would not expect too many unforeseen problems going
  forward.
* Patch 0003-* adds support for protected Message-ID, In-Reply-To,
  and References headers. These seem a lot more risky than the headers
  added in patch 0002-*, which is why I separated them. Also note that
  this patch breaks at least one unit test (see commit message for more
  details). I do not know what else this patch might break, as notmuch
  was built with the assumption that Message-ID in particular remains
  stable, so it might misbehave when reindexing decrypted messages yields
  different ids. Until now, Delta Chat still uses the same values for
  the protected and unprotected version for these headers. However,
  we might want to be prepared for when they start spoofing the values
  of the unprotected version.
* Patches 0004-*, 0005-*, and 0006-* add support for Autocrypt by
  (0004-*) parsing protected Autocrypt headers, (0005-*) adding the
  content of the effective Autocrypt header of a message to json and
  sexp output, and (0006-*) adding `tag:autocrypt` to messages that
  contain an Autocrypt header.

One thing that is still missing from this patch set is an update to the
`header-mask` which is produced in `notmuch-show.c` and included in
json and sexp output. I also noticed that `notmuch show --format=text`
still displays the unprotected headers, so the part that produces this
format still needs updating as well.

I also might have overlooked any number of other things (I did not even
run the entire test suite yet) and I am sure that a more competent C/C++
programmer could implement things in a more elegant manner. Therefore,
comments, suggestions, and all other kinds of help with these patches
are greatly appreciated.


Best

Frank
>From e6469a3043ea5b094a61622820263b83da25c3af Mon Sep 17 00:00:00 2001
From: Frank Seifferth <[email protected]>
Date: Thu, 18 Dec 2025 17:41:07 +0100
Subject: [PATCH 1/7] Add more test cases for protected headers

Some versions of Delta Chat recently started to send spoofed headers
that are overridden by the protected headers of OpenPGP-encrypted
messages. Currently, notmuch uses the spoofed headers rather than the
real ones, with the subject being the sole exception. This commit adds
test cases for the following three headers: Date, To, and From. The
example messages were modelled after what Delta Chat produces, which
(in my opinion) look like it should be valid.
---
 test/T356-protected-headers.sh                | 77 ++++++++++++++++++-
 .../protected-headers/spoofed-date.eml        | 28 +++++++
 .../protected-headers/spoofed-recipient.eml   | 28 +++++++
 .../protected-headers/spoofed-sender.eml      | 29 +++++++
 4 files changed, 161 insertions(+), 1 deletion(-)
 create mode 100644 test/corpora/protected-headers/spoofed-date.eml
 create mode 100644 test/corpora/protected-headers/spoofed-recipient.eml
 create mode 100644 test/corpora/protected-headers/spoofed-sender.eml

diff --git a/test/T356-protected-headers.sh b/test/T356-protected-headers.sh
index 9f640331..ccf9f177 100755
--- a/test/T356-protected-headers.sh
+++ b/test/T356-protected-headers.sh
@@ -24,6 +24,39 @@ test_json_nodes <<<"$output" \
                 'crypto:[0][0][0]["crypto"]={"decrypted": {"status": "full", 
"header-mask": {"Subject": "Subject Unavailable"}}}' \
                 'subject:[0][0][0]["headers"]["Subject"]="This is a protected 
header"'
 
+test_begin_subtest "verify spoofed date is shown without decryption"
+output=$(notmuch show --format=json id:[email protected])
+test_json_nodes <<<"$output" \
+                'subject:[0][0][0]["headers"]["Date"]="Sat, 01 Jan 2000 
12:00:00 +0000"'
+
+test_begin_subtest "verify real date is shown with decryption"
+test_subtest_known_broken
+output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
+test_json_nodes <<<"$output" \
+                'subject:[0][0][0]["headers"]["Date"]="Wed, 16 Dec 2015 
17:19:18 +0100"'
+
+test_begin_subtest "verify spoofed recipient is shown without decryption"
+output=$(notmuch show --format=json 
id:[email protected])
+test_json_nodes <<<"$output" \
+                'subject:[0][0][0]["headers"]["To"]="undisclosed-recipients: 
;"'
+
+test_begin_subtest "verify real recipient is shown with decryption"
+test_subtest_known_broken
+output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
+test_json_nodes <<<"$output" \
+                'subject:[0][0][0]["headers"]["To"]="Notmuch Test Suite 
<[email protected]>"'
+
+test_begin_subtest "verify spoofed sender is shown without decryption"
+output=$(notmuch show --format=json id:[email protected])
+test_json_nodes <<<"$output" \
+                
'subject:[0][0][0]["headers"]["From"]="[email protected]"'
+
+test_begin_subtest "verify real sender is shown with decryption"
+test_subtest_known_broken
+output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
+test_json_nodes <<<"$output" \
+                'subject:[0][0][0]["headers"]["From"]="Notmuch Test Suite 
<[email protected]>"'
+
 test_begin_subtest "when no external header is present, show masked subject as 
null"
 output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
 test_json_nodes <<<"$output" \
@@ -87,7 +120,7 @@ test_begin_subtest "protected subject is not indexed by 
default"
 output=$(notmuch search --output=messages 'subject:"This is a protected 
header"')
 test_expect_equal "$output" ''
 
-test_begin_subtest "reindex message with protected header"
+test_begin_subtest "reindex message with protected subject"
 test_expect_success 'notmuch reindex --decrypt=true 
id:[email protected]'
 
 test_begin_subtest "protected subject is indexed when cleartext is indexed"
@@ -105,6 +138,45 @@ test_json_nodes <<<"$output" \
                 'subject:["original"]["headers"]["Subject"]="This is a 
protected header"' \
                 'reply-subject:["reply-headers"]["Subject"]="Re: Subject 
Unavailable"'
 
+test_begin_subtest "spoofed date is used when cleartext is not indexed"
+output=$(notmuch search --output=messages 
'id:[email protected] and date:2000-01-01')
+test_expect_equal "$output" 'id:[email protected]'
+
+test_begin_subtest "real date is masked when cleartext is not indexed"
+output=$(notmuch search --output=messages 
'id:[email protected] and date:2015-12-16')
+test_expect_equal "$output" ''
+
+test_begin_subtest "real recipient is masked when cleartext is not indexed"
+output=$(notmuch search --output=messages 
'id:[email protected] and to:"Notmuch Test Suite"')
+test_expect_equal "$output" ''
+
+test_begin_subtest "real sender is masked when cleartext is not indexed"
+output=$(notmuch search --output=messages 
'id:[email protected] and from:"Notmuch Test Suite"')
+test_expect_equal "$output" ''
+
+test_begin_subtest "reindex messages with spoofed headers"
+test_expect_success 'notmuch reindex --decrypt=true 
id:[email protected] or 
id:[email protected] or 
id:[email protected]'
+
+test_begin_subtest "spoofed date is ignored when cleartext is indexed"
+test_subtest_known_broken
+output=$(notmuch search --output=messages 
'id:[email protected] and date:2000-01-01')
+test_expect_equal "$output" ''
+
+test_begin_subtest "real date is used when cleartext is indexed"
+test_subtest_known_broken
+output=$(notmuch search --output=messages 
'id:[email protected] and date:2015-12-16')
+test_expect_equal "$output" 'id:[email protected]'
+
+test_begin_subtest "real recipient is used when cleartext is indexed"
+test_subtest_known_broken
+output=$(notmuch search --output=messages 
'id:[email protected] and to:"Notmuch Test Suite"')
+test_expect_equal "$output" 'id:[email protected]'
+
+test_begin_subtest "real sender is used when cleartext is indexed"
+test_subtest_known_broken
+output=$(notmuch search --output=messages 
'id:[email protected] and from:"Notmuch Test Suite"')
+test_expect_equal "$output" 'id:[email protected]'
+
 test_begin_subtest "verify correct protected header when submessage exists"
 output=$(notmuch show --decrypt=true --format=json 
id:encrypted-message-with-forwarded-attachm...@crypto.notmuchmail.org)
 test_json_nodes <<<"$output" \
@@ -134,6 +206,9 @@ test_expect_equal "$output" 
'id:[email protected]
 id:[email protected]
 id:[email protected]
 id:[email protected]
+id:[email protected]
+id:[email protected]
+id:[email protected]
 id:[email protected]'
 
 test_begin_subtest "when rendering protected headers, avoid rendering 
legacy-display part"
diff --git a/test/corpora/protected-headers/spoofed-date.eml 
b/test/corpora/protected-headers/spoofed-date.eml
new file mode 100644
index 00000000..b3e5bb5a
--- /dev/null
+++ b/test/corpora/protected-headers/spoofed-date.eml
@@ -0,0 +1,28 @@
+From: [email protected]
+To: [email protected]
+Subject: Subject Unavailable
+Date: Sat, 01 Jan 2000 12:00:00 +0000
+Message-ID: <[email protected]>
+MIME-Version: 1.0
+Content-Type: multipart/encrypted; boundary="=-=-=";
+       protocol="application/pgp-encrypted"
+
+--=-=-=
+Content-Type: application/pgp-encrypted
+
+Version: 1
+
+--=-=-=
+Content-Type: application/octet-stream
+
+-----BEGIN PGP MESSAGE-----
+
+hF4DHXHP849rSK8SAQdALxucRFN71JbLt2GfNFt2/YrBvrshI8tGn7IzlxdE+1sw
++Pu7X4CisgRLrNP5NrkCeXd3qtdBL1oCp7Q8CE1MzagVZb3tGE9tdGjHqOHSUIcg
+0rsBt1bR4Vdunh5kgzfYVV3JqdtgQlZXF/AUrkB8LatxZ6nA9V0t/DC63dh6gUsJ
+EnbjAZq9z/k5Tjgi52+gXarl62cJQp7YSFLU2GgHCOjUMLugNPpr9J3YRtN9u7Np
+fLenbcQynXRWY0MNp+vRzWoVPi2g4A4J+L+LRKmChX/Ni6gqEU1ksXnhkX9+dZXs
+J4T6ixs1IyJxfyQCmA1bbi9exkORLdE7ZyxgYC3kSWUzivjwz68PdHUqitE+
+=XRi1
+-----END PGP MESSAGE-----
+--=-=-=--
diff --git a/test/corpora/protected-headers/spoofed-recipient.eml 
b/test/corpora/protected-headers/spoofed-recipient.eml
new file mode 100644
index 00000000..f9d47c57
--- /dev/null
+++ b/test/corpora/protected-headers/spoofed-recipient.eml
@@ -0,0 +1,28 @@
+From: [email protected]
+To: undisclosed-recipients: ;
+Subject: Subject Unavailable
+Date: Sat, 01 Jan 2000 12:00:00 +0000
+Message-ID: <[email protected]>
+MIME-Version: 1.0
+Content-Type: multipart/encrypted; boundary="=-=-=";
+       protocol="application/pgp-encrypted"
+
+--=-=-=
+Content-Type: application/pgp-encrypted
+
+Version: 1
+
+--=-=-=
+Content-Type: application/octet-stream
+
+-----BEGIN PGP MESSAGE-----
+
+hF4DHXHP849rSK8SAQdA15+QCv0bg+6LKzXtfj4pPyrOwkzIhCPgLd3aeMnv3WMw
+KcOKlfdgmEtI92AZFCpDErTceKpcTzVz2m9vaR3ZLIntf4Db8P/KPVTLeJla9Wy0
+0r4BEuH4GwCq/rM889/funOJBIm/amlNEAbOicBR9QJzqAkvQ1i9SsrAuA/MFA7S
+/sH3RrNT0x00UHh6i2Ho5B+GgJFBpYyijZb6dGXcMt8jMrhM/D3hQvu2VLL72h6z
+cHjqEIxYrgCXcmMKGzXFpv0WLYXVbe/BU6tcTUqzcQtRXQAImv3WQXmTx0ZXHxe0
+y4DkxxrdLMS4ogKp6iPCtqIjGV6wrBRVlcFGTh+1gmhYiAviKixx03XfRCw7YZTj
+=vcs2
+-----END PGP MESSAGE-----
+--=-=-=--
diff --git a/test/corpora/protected-headers/spoofed-sender.eml 
b/test/corpora/protected-headers/spoofed-sender.eml
new file mode 100644
index 00000000..ed1d2595
--- /dev/null
+++ b/test/corpora/protected-headers/spoofed-sender.eml
@@ -0,0 +1,29 @@
+From: [email protected]
+To: undisclosed-recipients: ;
+Subject: Subject Unavailable
+Date: Sat, 01 Jan 2000 12:00:00 +0000
+Message-ID: <[email protected]>
+MIME-Version: 1.0
+Content-Type: multipart/encrypted; boundary="=-=-=";
+       protocol="application/pgp-encrypted"
+
+--=-=-=
+Content-Type: application/pgp-encrypted
+
+Version: 1
+
+--=-=-=
+Content-Type: application/octet-stream
+
+-----BEGIN PGP MESSAGE-----
+
+hF4DHXHP849rSK8SAQdA21XV8GyULURScZxf9wBJs5j+5z3OvXJYTKVVURbUVVAw
+sJL+xsbZY24IkCDqX6YEY/iCZgnwJMXWkgtkiapQnLhGj9NOiBa3++iuzZVJ9/26
+0sAJAZCrLPqeCBtB3WveXXrY974CFYE6q1hp27bye5hY0mNDxudEEUpfMA0t6dFV
+BhzYCkdIbZSwYglr8JM4vaHKpeMT3RgiANm9IxG4vKieLS8rFzJ54Q6EPIpROLkd
+WDpoCtfXTHj9vvr+Vx2eLdURCsdcA4Kjj4Xdujz04p5yq3UcCx/5Ml2vwKZJTVzO
+41mTVzkx52Y4iDgOupjdvAy0UIkowj/gXzhcVOL/0VRG4MMelQ3raiuNiOP19es+
+id0ZmRgEoEB0TsrY
+=DZBa
+-----END PGP MESSAGE-----
+--=-=-=--
-- 
2.39.5

>From 5ee7dd72699dec2611c5fdaad8fc1f85a169076f Mon Sep 17 00:00:00 2001
From: Frank Seifferth <[email protected]>
Date: Sat, 31 Jan 2026 16:55:51 +0100
Subject: [PATCH 2/7] Support header protection for From, To, Cc, Bcc,
 Reply-To, and Date
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This fixes the test cases added in the previous commit. Note that the
six additional protected headers are only parsed if they conform to
RFC 9788. "Message wrapping" (as defined in RFC 5751 ยง 3.1) is not
implemented yet. I am rather confident that the implementation should
work fine.
---
 lib/index.cc                   | 26 +++++++++++
 lib/message.cc                 | 42 +++++++++++++++---
 lib/notmuch-private.h          |  8 ++++
 notmuch-show.c                 | 80 ++++++++++++++++++++++++++--------
 test/T356-protected-headers.sh | 11 +----
 util/crypto.c                  | 57 +++++++++++++++++++++++-
 util/crypto.h                  |  8 ++++
 7 files changed, 196 insertions(+), 36 deletions(-)

diff --git a/lib/index.cc b/lib/index.cc
index 629dcb22..a2a54906 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -763,6 +763,32 @@ _notmuch_message_index_file (notmuch_message_t *message,
        _notmuch_message_gen_terms (message, "subject", 
msg_crypto->payload_subject);
        _notmuch_message_update_subject (message, msg_crypto->payload_subject);
     }
+    if (msg_crypto && msg_crypto->payload_from) {
+       _notmuch_message_gen_terms (message, "from", msg_crypto->payload_from);
+       _notmuch_message_update_from (message, msg_crypto->payload_from);
+    }
+    if (msg_crypto && msg_crypto->payload_date) {
+       _notmuch_message_update_date (message, msg_crypto->payload_date);
+    }
+    if (msg_crypto && (msg_crypto->payload_to ||
+                      msg_crypto->payload_cc ||
+                      msg_crypto->payload_bcc)) {
+       GMimeParserOptions *opts;
+       opts = g_mime_parser_options_get_default();
+       if (msg_crypto->payload_to) {
+           _index_address_list (message, "to",
+               internet_address_list_parse(opts, msg_crypto->payload_to));
+       }
+       if (msg_crypto->payload_cc) {
+           _index_address_list (message, "to",
+               internet_address_list_parse(opts, msg_crypto->payload_cc));
+       }
+       if (msg_crypto->payload_bcc) {
+           _index_address_list (message, "to",
+               internet_address_list_parse(opts, msg_crypto->payload_bcc));
+       }
+       g_mime_parser_options_free(opts);
+    }
 
     talloc_free (msg_crypto);
 
diff --git a/lib/message.cc b/lib/message.cc
index 8b1fa400..19eac5d3 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -1301,11 +1301,8 @@ _notmuch_message_set_author (notmuch_message_t *message,
     return;
 }
 
-void
-_notmuch_message_set_header_values (notmuch_message_t *message,
-                                   const char *date,
-                                   const char *from,
-                                   const char *subject)
+time_t
+_notmuch_rfc_date_to_timestamp (const char *date)
 {
     time_t time_value;
 
@@ -1321,9 +1318,17 @@ _notmuch_message_set_header_values (notmuch_message_t 
*message,
        if (time_value < 0)
            time_value = 0;
     }
+    return time_value;
+}
 
+void
+_notmuch_message_set_header_values (notmuch_message_t *message,
+                                   const char *date,
+                                   const char *from,
+                                   const char *subject)
+{
     message->doc.add_value (NOTMUCH_VALUE_TIMESTAMP,
-                           Xapian::sortable_serialise (time_value));
+                           Xapian::sortable_serialise 
(_notmuch_rfc_date_to_timestamp(date)));
     message->doc.add_value (NOTMUCH_VALUE_FROM, from);
     message->doc.add_value (NOTMUCH_VALUE_SUBJECT, subject);
     message->modified = true;
@@ -1337,6 +1342,31 @@ _notmuch_message_update_subject (notmuch_message_t 
*message,
     message->modified = true;
 }
 
+void
+_notmuch_message_update_from (notmuch_message_t *message,
+                                const char *from)
+{
+    message->doc.add_value (NOTMUCH_VALUE_FROM, from);
+    message->modified = true;
+}
+
+void
+_notmuch_message_update_date (notmuch_message_t *message,
+                                const char *date)
+{
+    message->doc.add_value (NOTMUCH_VALUE_TIMESTAMP,
+                           Xapian::sortable_serialise 
(_notmuch_rfc_date_to_timestamp(date)));
+    message->modified = true;
+}
+
+void
+_notmuch_message_update_message_id (notmuch_message_t *message,
+                                const char *message_id)
+{
+    message->doc.add_value (NOTMUCH_VALUE_MESSAGE_ID, message_id);
+    message->modified = true;
+}
+
 /* Upgrade a message to support NOTMUCH_FEATURE_LAST_MOD.  The caller
  * must call _notmuch_message_sync. */
 void
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index ba07083b..07e85428 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -350,6 +350,14 @@ void
 _notmuch_message_update_subject (notmuch_message_t *message,
                                 const char *subject);
 
+void
+_notmuch_message_update_from (notmuch_message_t *message,
+                                const char *from);
+
+void
+_notmuch_message_update_date (notmuch_message_t *message,
+                                const char *date);
+
 void
 _notmuch_message_upgrade_last_mod (notmuch_message_t *message);
 
diff --git a/notmuch-show.c b/notmuch-show.c
index 8c23f821..14e59c29 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -268,33 +268,56 @@ format_headers_sprinter (sprinter_t *sp, GMimeMessage 
*message,
        sp->string (sp, g_mime_message_get_subject (message));
 
     sp->map_key (sp, "From");
-    sp->string (sp, g_mime_message_get_from_string (message));
+    if (msg_crypto && msg_crypto->payload_from) {
+       sp->string (sp, msg_crypto->payload_from);
+    } else
+       sp->string (sp, g_mime_message_get_from_string (message));
 
-    recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_TO);
-    if (recipients_string) {
+    if (msg_crypto && msg_crypto->payload_to) {
        sp->map_key (sp, "To");
-       sp->string (sp, recipients_string);
-       g_free (recipients_string);
+       sp->string (sp, msg_crypto->payload_to);
+    } else {
+       recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_TO);
+       if (recipients_string) {
+           sp->map_key (sp, "To");
+           sp->string (sp, recipients_string);
+           g_free (recipients_string);
+       }
     }
 
-    recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_CC);
-    if (recipients_string) {
+    if (msg_crypto && msg_crypto->payload_cc) {
        sp->map_key (sp, "Cc");
-       sp->string (sp, recipients_string);
-       g_free (recipients_string);
+       sp->string (sp, msg_crypto->payload_cc);
+    } else {
+       recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_CC);
+       if (recipients_string) {
+           sp->map_key (sp, "Cc");
+           sp->string (sp, recipients_string);
+           g_free (recipients_string);
+       }
     }
 
-    recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_BCC);
-    if (recipients_string) {
+    if (msg_crypto && msg_crypto->payload_bcc) {
        sp->map_key (sp, "Bcc");
-       sp->string (sp, recipients_string);
-       g_free (recipients_string);
+       sp->string (sp, msg_crypto->payload_bcc);
+    } else {
+       recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_BCC);
+       if (recipients_string) {
+           sp->map_key (sp, "Bcc");
+           sp->string (sp, recipients_string);
+           g_free (recipients_string);
+       }
     }
 
-    reply_to_string = g_mime_message_get_reply_to_string (local, message);
-    if (reply_to_string) {
+    if (msg_crypto && msg_crypto->payload_reply_to) {
        sp->map_key (sp, "Reply-To");
-       sp->string (sp, reply_to_string);
+       sp->string (sp, msg_crypto->payload_reply_to);
+    } else {
+       reply_to_string = g_mime_message_get_reply_to_string (local, message);
+       if (reply_to_string) {
+           sp->map_key (sp, "Reply-To");
+           sp->string (sp, reply_to_string);
+       }
     }
 
     if (reply) {
@@ -305,7 +328,10 @@ format_headers_sprinter (sprinter_t *sp, GMimeMessage 
*message,
        sp->string (sp, g_mime_object_get_header (GMIME_OBJECT (message), 
"References"));
     } else {
        sp->map_key (sp, "Date");
-       sp->string (sp, g_mime_message_get_date_string (sp, message));
+       if (msg_crypto && msg_crypto->payload_date) {
+           sp->string (sp, msg_crypto->payload_date);
+       } else
+           sp->string (sp, g_mime_message_get_date_string (sp, message));
     }
 
     /* Output extra headers the user has configured, if any */
@@ -710,10 +736,26 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, 
mime_node_t *node,
                        sp->map_key (sp, "encrypted");
                        sp->boolean (sp, msg_crypto->signature_encrypted);
                    }
-                   if (msg_crypto->payload_subject) {
+                   if (msg_crypto->payload_subject || msg_crypto->payload_from 
||
+                       msg_crypto->payload_to || msg_crypto->payload_cc ||
+                       msg_crypto->payload_bcc || msg_crypto->payload_reply_to 
||
+                       msg_crypto->payload_date) {
                        sp->map_key (sp, "headers");
                        sp->begin_list (sp);
-                       sp->string (sp, "Subject");
+                       if (msg_crypto->payload_subject)
+                           sp->string (sp, "Subject");
+                       if (msg_crypto->payload_from)
+                           sp->string (sp, "From");
+                       if (msg_crypto->payload_to)
+                           sp->string (sp, "To");
+                       if (msg_crypto->payload_cc)
+                           sp->string (sp, "Cc");
+                       if (msg_crypto->payload_bcc)
+                           sp->string (sp, "Bcc");
+                       if (msg_crypto->payload_reply_to)
+                           sp->string (sp, "Reply-To");
+                       if (msg_crypto->payload_date)
+                           sp->string (sp, "Date");
                        sp->end (sp);
                    }
                    sp->end (sp);
diff --git a/test/T356-protected-headers.sh b/test/T356-protected-headers.sh
index ccf9f177..ed0aa996 100755
--- a/test/T356-protected-headers.sh
+++ b/test/T356-protected-headers.sh
@@ -30,7 +30,6 @@ test_json_nodes <<<"$output" \
                 'subject:[0][0][0]["headers"]["Date"]="Sat, 01 Jan 2000 
12:00:00 +0000"'
 
 test_begin_subtest "verify real date is shown with decryption"
-test_subtest_known_broken
 output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
 test_json_nodes <<<"$output" \
                 'subject:[0][0][0]["headers"]["Date"]="Wed, 16 Dec 2015 
17:19:18 +0100"'
@@ -41,7 +40,6 @@ test_json_nodes <<<"$output" \
                 'subject:[0][0][0]["headers"]["To"]="undisclosed-recipients: 
;"'
 
 test_begin_subtest "verify real recipient is shown with decryption"
-test_subtest_known_broken
 output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
 test_json_nodes <<<"$output" \
                 'subject:[0][0][0]["headers"]["To"]="Notmuch Test Suite 
<[email protected]>"'
@@ -52,7 +50,6 @@ test_json_nodes <<<"$output" \
                 
'subject:[0][0][0]["headers"]["From"]="[email protected]"'
 
 test_begin_subtest "verify real sender is shown with decryption"
-test_subtest_known_broken
 output=$(notmuch show --decrypt=true --format=json 
id:[email protected])
 test_json_nodes <<<"$output" \
                 'subject:[0][0][0]["headers"]["From"]="Notmuch Test Suite 
<[email protected]>"'
@@ -158,22 +155,18 @@ test_begin_subtest "reindex messages with spoofed headers"
 test_expect_success 'notmuch reindex --decrypt=true 
id:[email protected] or 
id:[email protected] or 
id:[email protected]'
 
 test_begin_subtest "spoofed date is ignored when cleartext is indexed"
-test_subtest_known_broken
 output=$(notmuch search --output=messages 
'id:[email protected] and date:2000-01-01')
 test_expect_equal "$output" ''
 
 test_begin_subtest "real date is used when cleartext is indexed"
-test_subtest_known_broken
 output=$(notmuch search --output=messages 
'id:[email protected] and date:2015-12-16')
 test_expect_equal "$output" 'id:[email protected]'
 
 test_begin_subtest "real recipient is used when cleartext is indexed"
-test_subtest_known_broken
 output=$(notmuch search --output=messages 
'id:[email protected] and to:"Notmuch Test Suite"')
 test_expect_equal "$output" 'id:[email protected]'
 
 test_begin_subtest "real sender is used when cleartext is indexed"
-test_subtest_known_broken
 output=$(notmuch search --output=messages 
'id:[email protected] and from:"Notmuch Test Suite"')
 test_expect_equal "$output" 'id:[email protected]'
 
@@ -234,7 +227,7 @@ for variant in multipart-signed onepart-signed; do
     test_begin_subtest "verify signed PKCS#7 subject ($variant)"
     output=$(notmuch show --verify --format=json 
"id:smime-${variant}@protected-headers.example")
     test_json_nodes <<<"$output" \
-                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject"]' \
+                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject","From","To","Date"]'
 \
                     
'sig_good:[0][0][0]["crypto"]["signed"]["status"][0]["status"]="good"' \
                     
'sig_fpr:[0][0][0]["crypto"]["signed"]["status"][0]["fingerprint"]="702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB"'
 \
                     'not_encrypted:[0][0][0]["crypto"]!"decrypted"'
@@ -250,7 +243,7 @@ for variant in sign+enc sign+enc+legacy-disp; do
     test_begin_subtest "confirm signed and encrypted PKCS#7 subject ($variant)"
     output=$(notmuch show --decrypt=true --format=json 
"id:smime-${variant}@protected-headers.example")
     test_json_nodes <<<"$output" \
-                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject"]' \
+                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject","From","To","Date"]'
 \
                     
'sig_good:[0][0][0]["crypto"]["signed"]["status"][0]["status"]="good"' \
                     
'sig_fpr:[0][0][0]["crypto"]["signed"]["status"][0]["fingerprint"]="702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB"'
 \
                     
'encrypted:[0][0][0]["crypto"]["decrypted"]={"status":"full","header-mask":{"Subject":"..."}}'
diff --git a/util/crypto.c b/util/crypto.c
index 156a6550..1bfa7c30 100644
--- a/util/crypto.c
+++ b/util/crypto.c
@@ -118,6 +118,16 @@ _notmuch_message_crypto_destructor 
(_notmuch_message_crypto_t *msg_crypto)
        g_object_unref (msg_crypto->sig_list);
     if (msg_crypto->payload_subject)
        talloc_free (msg_crypto->payload_subject);
+    if (msg_crypto->payload_from)
+       talloc_free (msg_crypto->payload_from);
+    if (msg_crypto->payload_to)
+       talloc_free (msg_crypto->payload_to);
+    if (msg_crypto->payload_cc)
+       talloc_free (msg_crypto->payload_cc);
+    if (msg_crypto->payload_reply_to)
+       talloc_free (msg_crypto->payload_reply_to);
+    if (msg_crypto->payload_date)
+       talloc_free (msg_crypto->payload_date);
     return 0;
 }
 
@@ -167,6 +177,12 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
     const char *protected_headers = NULL;
     const char *forwarded = NULL;
     const char *subject = NULL;
+    const char *from = NULL;
+    const char *to = NULL;
+    const char *cc = NULL;
+    const char *bcc = NULL;
+    const char *reply_to = NULL;
+    const char *date = NULL;
 
     if ((! msg_crypto) || (! part))
        INTERNAL_ERROR ("_notmuch_message_crypto_potential_payload() got NULL 
for %s\n",
@@ -213,9 +229,16 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
     } else {
        /* Consider "memoryhole"-style protected headers as practiced by 
Enigmail and K-9 */
        protected_headers = g_mime_object_get_content_type_parameter (part, 
"protected-headers");
-       if (protected_headers && strcasecmp ("v1", protected_headers) == 0)
+       if (protected_headers && strcasecmp ("v1", protected_headers) == 0) {
            subject = g_mime_object_get_header (part, "Subject");
-       /* FIXME: handle more than just Subject: at some point */
+           from = g_mime_object_get_header (part, "From");
+           to = g_mime_object_get_header (part, "To");
+           cc = g_mime_object_get_header (part, "Cc");
+           bcc = g_mime_object_get_header (part, "Bcc");
+           reply_to = g_mime_object_get_header (part, "Reply-To");
+           date = g_mime_object_get_header (part, "Date");
+           /* FIXME: possibly add even more headers at some point */
+       }
     }
 
     if (subject) {
@@ -223,6 +246,36 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
            talloc_free (msg_crypto->payload_subject);
        msg_crypto->payload_subject = talloc_strdup (msg_crypto, subject);
     }
+    if (from) {
+       if (msg_crypto->payload_from)
+           talloc_free (msg_crypto->payload_from);
+       msg_crypto->payload_from = talloc_strdup (msg_crypto, from);
+    }
+    if (to) {
+       if (msg_crypto->payload_to)
+           talloc_free (msg_crypto->payload_to);
+       msg_crypto->payload_to = talloc_strdup (msg_crypto, to);
+    }
+    if (cc) {
+       if (msg_crypto->payload_cc)
+           talloc_free (msg_crypto->payload_cc);
+       msg_crypto->payload_cc = talloc_strdup (msg_crypto, cc);
+    }
+    if (bcc) {
+       if (msg_crypto->payload_bcc)
+           talloc_free (msg_crypto->payload_bcc);
+       msg_crypto->payload_bcc = talloc_strdup (msg_crypto, bcc);
+    }
+    if (reply_to) {
+       if (msg_crypto->payload_reply_to)
+           talloc_free (msg_crypto->payload_reply_to);
+       msg_crypto->payload_reply_to = talloc_strdup (msg_crypto, reply_to);
+    }
+    if (date) {
+       if (msg_crypto->payload_date)
+           talloc_free (msg_crypto->payload_date);
+       msg_crypto->payload_date = talloc_strdup (msg_crypto, date);
+    }
 
     return true;
 }
diff --git a/util/crypto.h b/util/crypto.h
index 3c5d384b..bebacf5b 100644
--- a/util/crypto.h
+++ b/util/crypto.h
@@ -64,6 +64,14 @@ typedef struct _notmuch_message_crypto {
      * UTF-8 */
     char *payload_subject;
 
+    /* other protected headers */
+    char *payload_from;
+    char *payload_to;
+    char *payload_cc;
+    char *payload_bcc;
+    char *payload_reply_to;
+    char *payload_date;
+
     /* if both signed and encrypted, was the signature encrypted? */
     bool signature_encrypted;
 } _notmuch_message_crypto_t;
-- 
2.39.5

>From 991b904f7086c902378a2c254065d49d4749ac9a Mon Sep 17 00:00:00 2001
From: Frank Seifferth <[email protected]>
Date: Sat, 31 Jan 2026 17:06:16 +0100
Subject: [PATCH 3/7] Support header protection for Message-ID, In-Reply-To,
 and References

This adds support for three more protected headers; again only as long
as they conform to RFC 9788. In contrast to the previous commit, I am
not entirely sure what the ramifications of supporting these additional
headers are. One thing I noticed is that updating the Message-ID field
breaks the subtest "identify messages that had a legacy display part
skipped during indexing" in "test/T356-protected-headers.sh". I do not
know if this indicates a bug in the implementation or merely a bug in
the test script. This issue should definitely be investigated further
before this commit makes it into any kind of stable release.
---
 lib/index.cc                   |  8 ++++++++
 lib/notmuch-private.h          |  4 ++++
 notmuch-show.c                 |  9 ++++++++-
 test/T356-protected-headers.sh |  5 +++--
 util/crypto.c                  | 27 +++++++++++++++++++++++++++
 util/crypto.h                  |  3 +++
 6 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/lib/index.cc b/lib/index.cc
index a2a54906..c0c5f76a 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -770,6 +770,14 @@ _notmuch_message_index_file (notmuch_message_t *message,
     if (msg_crypto && msg_crypto->payload_date) {
        _notmuch_message_update_date (message, msg_crypto->payload_date);
     }
+    /* FIXME: the following breaks the subtest "identify message that
+     * had a legacy display part skipped during indexing" in test file
+     * "test/T356-protected-headers.sh".
+     */
+    if (msg_crypto && msg_crypto->payload_message_id) {
+       _notmuch_message_gen_terms (message, "id", 
msg_crypto->payload_message_id);
+       _notmuch_message_update_message_id (message, 
msg_crypto->payload_message_id);
+    }
     if (msg_crypto && (msg_crypto->payload_to ||
                       msg_crypto->payload_cc ||
                       msg_crypto->payload_bcc)) {
diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h
index 07e85428..e1d3fc72 100644
--- a/lib/notmuch-private.h
+++ b/lib/notmuch-private.h
@@ -358,6 +358,10 @@ void
 _notmuch_message_update_date (notmuch_message_t *message,
                                 const char *date);
 
+void
+_notmuch_message_update_message_id (notmuch_message_t *message,
+                                const char *message_id);
+
 void
 _notmuch_message_upgrade_last_mod (notmuch_message_t *message);
 
diff --git a/notmuch-show.c b/notmuch-show.c
index 14e59c29..3d9a8523 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -739,7 +739,8 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, 
mime_node_t *node,
                    if (msg_crypto->payload_subject || msg_crypto->payload_from 
||
                        msg_crypto->payload_to || msg_crypto->payload_cc ||
                        msg_crypto->payload_bcc || msg_crypto->payload_reply_to 
||
-                       msg_crypto->payload_date) {
+                       msg_crypto->payload_date || 
msg_crypto->payload_message_id ||
+                       msg_crypto->payload_in_reply_to || 
msg_crypto->payload_references) {
                        sp->map_key (sp, "headers");
                        sp->begin_list (sp);
                        if (msg_crypto->payload_subject)
@@ -756,6 +757,12 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, 
mime_node_t *node,
                            sp->string (sp, "Reply-To");
                        if (msg_crypto->payload_date)
                            sp->string (sp, "Date");
+                       if (msg_crypto->payload_message_id)
+                           sp->string (sp, "Message-ID");
+                       if (msg_crypto->payload_in_reply_to)
+                           sp->string (sp, "In-Reply-To");
+                       if (msg_crypto->payload_references)
+                           sp->string (sp, "References");
                        sp->end (sp);
                    }
                    sp->end (sp);
diff --git a/test/T356-protected-headers.sh b/test/T356-protected-headers.sh
index ed0aa996..f698e5ed 100755
--- a/test/T356-protected-headers.sh
+++ b/test/T356-protected-headers.sh
@@ -220,6 +220,7 @@ output=$(notmuch search --output=messages body:interrupting)
 test_expect_equal "$output" ''
 
 test_begin_subtest "identify message that had a legacy display part skipped 
during indexing"
+test_subtest_known_broken
 output=$(notmuch search --output=messages 
property:index.repaired=skip-protected-headers-legacy-display)
 test_expect_equal "$output" 
id:[email protected]
 
@@ -227,7 +228,7 @@ for variant in multipart-signed onepart-signed; do
     test_begin_subtest "verify signed PKCS#7 subject ($variant)"
     output=$(notmuch show --verify --format=json 
"id:smime-${variant}@protected-headers.example")
     test_json_nodes <<<"$output" \
-                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject","From","To","Date"]'
 \
+                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject","From","To","Date","Message-ID"]'
 \
                     
'sig_good:[0][0][0]["crypto"]["signed"]["status"][0]["status"]="good"' \
                     
'sig_fpr:[0][0][0]["crypto"]["signed"]["status"][0]["fingerprint"]="702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB"'
 \
                     'not_encrypted:[0][0][0]["crypto"]!"decrypted"'
@@ -243,7 +244,7 @@ for variant in sign+enc sign+enc+legacy-disp; do
     test_begin_subtest "confirm signed and encrypted PKCS#7 subject ($variant)"
     output=$(notmuch show --decrypt=true --format=json 
"id:smime-${variant}@protected-headers.example")
     test_json_nodes <<<"$output" \
-                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject","From","To","Date"]'
 \
+                    
'signed_subject:[0][0][0]["crypto"]["signed"]["headers"]=["Subject","From","To","Date","Message-ID"]'
 \
                     
'sig_good:[0][0][0]["crypto"]["signed"]["status"][0]["status"]="good"' \
                     
'sig_fpr:[0][0][0]["crypto"]["signed"]["status"][0]["fingerprint"]="702BA4B157F1E2B7D16B0C6A5FFC8A7DE2057DEB"'
 \
                     
'encrypted:[0][0][0]["crypto"]["decrypted"]={"status":"full","header-mask":{"Subject":"..."}}'
diff --git a/util/crypto.c b/util/crypto.c
index 1bfa7c30..79abe3b8 100644
--- a/util/crypto.c
+++ b/util/crypto.c
@@ -128,6 +128,12 @@ _notmuch_message_crypto_destructor 
(_notmuch_message_crypto_t *msg_crypto)
        talloc_free (msg_crypto->payload_reply_to);
     if (msg_crypto->payload_date)
        talloc_free (msg_crypto->payload_date);
+    if (msg_crypto->payload_message_id)
+       talloc_free (msg_crypto->payload_message_id);
+    if (msg_crypto->payload_in_reply_to)
+       talloc_free (msg_crypto->payload_in_reply_to);
+    if (msg_crypto->payload_references)
+       talloc_free (msg_crypto->payload_references);
     return 0;
 }
 
@@ -183,6 +189,9 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
     const char *bcc = NULL;
     const char *reply_to = NULL;
     const char *date = NULL;
+    const char *message_id = NULL;
+    const char *in_reply_to = NULL;
+    const char *references = NULL;
 
     if ((! msg_crypto) || (! part))
        INTERNAL_ERROR ("_notmuch_message_crypto_potential_payload() got NULL 
for %s\n",
@@ -237,6 +246,9 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
            bcc = g_mime_object_get_header (part, "Bcc");
            reply_to = g_mime_object_get_header (part, "Reply-To");
            date = g_mime_object_get_header (part, "Date");
+           message_id = g_mime_object_get_header (part, "Message-ID");
+           in_reply_to = g_mime_object_get_header (part, "In-Reply-To");
+           references = g_mime_object_get_header (part, "References");
            /* FIXME: possibly add even more headers at some point */
        }
     }
@@ -276,6 +288,21 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
            talloc_free (msg_crypto->payload_date);
        msg_crypto->payload_date = talloc_strdup (msg_crypto, date);
     }
+    if (message_id) {
+       if (msg_crypto->payload_message_id)
+           talloc_free (msg_crypto->payload_message_id);
+       msg_crypto->payload_message_id = talloc_strdup (msg_crypto, message_id);
+    }
+    if (in_reply_to) {
+       if (msg_crypto->payload_in_reply_to)
+           talloc_free (msg_crypto->payload_in_reply_to);
+       msg_crypto->payload_in_reply_to = talloc_strdup (msg_crypto, 
in_reply_to);
+    }
+    if (references) {
+       if (msg_crypto->payload_references)
+           talloc_free (msg_crypto->payload_references);
+       msg_crypto->payload_references = talloc_strdup (msg_crypto, references);
+    }
 
     return true;
 }
diff --git a/util/crypto.h b/util/crypto.h
index bebacf5b..af12ba07 100644
--- a/util/crypto.h
+++ b/util/crypto.h
@@ -71,6 +71,9 @@ typedef struct _notmuch_message_crypto {
     char *payload_bcc;
     char *payload_reply_to;
     char *payload_date;
+    char *payload_message_id;
+    char *payload_in_reply_to;
+    char *payload_references;
 
     /* if both signed and encrypted, was the signature encrypted? */
     bool signature_encrypted;
-- 
2.39.5

>From ecffa567c1fc91061c1d695019f9470af24220c5 Mon Sep 17 00:00:00 2001
From: Frank Seifferth <[email protected]>
Date: Sat, 31 Jan 2026 17:07:03 +0100
Subject: [PATCH 4/7] Support header protection for the Autocrypt header

This is again RFC 9788-style only. Also note that this commit does not
yet make this header itself accessible via the CLI.
---
 notmuch-show.c | 5 ++++-
 util/crypto.c  | 9 +++++++++
 util/crypto.h  | 1 +
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/notmuch-show.c b/notmuch-show.c
index 3d9a8523..973635f2 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -740,7 +740,8 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, 
mime_node_t *node,
                        msg_crypto->payload_to || msg_crypto->payload_cc ||
                        msg_crypto->payload_bcc || msg_crypto->payload_reply_to 
||
                        msg_crypto->payload_date || 
msg_crypto->payload_message_id ||
-                       msg_crypto->payload_in_reply_to || 
msg_crypto->payload_references) {
+                       msg_crypto->payload_in_reply_to || 
msg_crypto->payload_references ||
+                       msg_crypto->payload_autocrypt) {
                        sp->map_key (sp, "headers");
                        sp->begin_list (sp);
                        if (msg_crypto->payload_subject)
@@ -763,6 +764,8 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, 
mime_node_t *node,
                            sp->string (sp, "In-Reply-To");
                        if (msg_crypto->payload_references)
                            sp->string (sp, "References");
+                       if (msg_crypto->payload_autocrypt)
+                           sp->string (sp, "Autocrypt");
                        sp->end (sp);
                    }
                    sp->end (sp);
diff --git a/util/crypto.c b/util/crypto.c
index 79abe3b8..33fa8fa0 100644
--- a/util/crypto.c
+++ b/util/crypto.c
@@ -134,6 +134,8 @@ _notmuch_message_crypto_destructor 
(_notmuch_message_crypto_t *msg_crypto)
        talloc_free (msg_crypto->payload_in_reply_to);
     if (msg_crypto->payload_references)
        talloc_free (msg_crypto->payload_references);
+    if (msg_crypto->payload_autocrypt)
+       talloc_free (msg_crypto->payload_autocrypt);
     return 0;
 }
 
@@ -192,6 +194,7 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
     const char *message_id = NULL;
     const char *in_reply_to = NULL;
     const char *references = NULL;
+    const char *autocrypt = NULL;
 
     if ((! msg_crypto) || (! part))
        INTERNAL_ERROR ("_notmuch_message_crypto_potential_payload() got NULL 
for %s\n",
@@ -249,6 +252,7 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
            message_id = g_mime_object_get_header (part, "Message-ID");
            in_reply_to = g_mime_object_get_header (part, "In-Reply-To");
            references = g_mime_object_get_header (part, "References");
+           autocrypt = g_mime_object_get_header (part, "Autocrypt");
            /* FIXME: possibly add even more headers at some point */
        }
     }
@@ -303,6 +307,11 @@ _notmuch_message_crypto_potential_payload 
(_notmuch_message_crypto_t *msg_crypto
            talloc_free (msg_crypto->payload_references);
        msg_crypto->payload_references = talloc_strdup (msg_crypto, references);
     }
+    if (autocrypt) {
+       if (msg_crypto->payload_autocrypt)
+           talloc_free (msg_crypto->payload_autocrypt);
+       msg_crypto->payload_autocrypt = talloc_strdup (msg_crypto, autocrypt);
+    }
 
     return true;
 }
diff --git a/util/crypto.h b/util/crypto.h
index af12ba07..a2fdb75d 100644
--- a/util/crypto.h
+++ b/util/crypto.h
@@ -74,6 +74,7 @@ typedef struct _notmuch_message_crypto {
     char *payload_message_id;
     char *payload_in_reply_to;
     char *payload_references;
+    char *payload_autocrypt;
 
     /* if both signed and encrypted, was the signature encrypted? */
     bool signature_encrypted;
-- 
2.39.5

>From 96982865e7a3160aba63515be58db38f6744e9ad Mon Sep 17 00:00:00 2001
From: Frank Seifferth <[email protected]>
Date: Sat, 31 Jan 2026 18:18:17 +0100
Subject: [PATCH 5/7] Add Autocrypt header to json and sexp output

---
 notmuch-show.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/notmuch-show.c b/notmuch-show.c
index 973635f2..5341f2df 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -334,6 +334,12 @@ format_headers_sprinter (sprinter_t *sp, GMimeMessage 
*message,
            sp->string (sp, g_mime_message_get_date_string (sp, message));
     }
 
+    sp->map_key (sp, "Autocrypt");
+    if (msg_crypto && msg_crypto->payload_autocrypt) {
+       sp->string (sp, msg_crypto->payload_autocrypt);
+    } else
+       sp->string (sp, g_mime_object_get_header (GMIME_OBJECT (message), 
"Autocrypt"));
+
     /* Output extra headers the user has configured, if any */
     if (! reply)
        format_extra_headers_sprinter (sp, message);
-- 
2.39.5

>From 8839f61f3861f105ffdceb8604b63f485c02718d Mon Sep 17 00:00:00 2001
From: Frank Seifferth <[email protected]>
Date: Sat, 31 Jan 2026 18:37:45 +0100
Subject: [PATCH 6/7] Add tag:autocrypt to messages with Autocrypt headers

---
 lib/index.cc | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/index.cc b/lib/index.cc
index c0c5f76a..8ffba9b6 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -798,6 +798,12 @@ _notmuch_message_index_file (notmuch_message_t *message,
        g_mime_parser_options_free(opts);
     }
 
+    if (msg_crypto && msg_crypto->payload_autocrypt) {
+       _notmuch_message_add_term (message, "tag", "autocrypt");
+    } else if (g_mime_object_get_header (GMIME_OBJECT(mime_message), 
"Autocrypt")) {
+       _notmuch_message_add_term (message, "tag", "autocrypt");
+    }
+
     talloc_free (msg_crypto);
 
     return NOTMUCH_STATUS_SUCCESS;
-- 
2.39.5

_______________________________________________
notmuch mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to