You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2023/04/13 10:01:05 UTC

[james-project] branch master updated: JAMES-2080 Allow turning off header indexing in OpenSearch (#1516)

This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git


The following commit(s) were added to refs/heads/master by this push:
     new 3217d0c06a JAMES-2080 Allow turning off header indexing in OpenSearch (#1516)
3217d0c06a is described below

commit 3217d0c06ab9d25181d5d3a11d65356afebed354
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Thu Apr 13 17:00:59 2023 +0700

    JAMES-2080 Allow turning off header indexing in OpenSearch (#1516)
    
    * JAMES-2080 Allow turning off header indexing in OpenSearch
    
    Indicates if you wish to index headers or not (default: true).
    Note that specific headers (From, To, Cc, Bcc, Subject,
    Message-Id, Date, Content-Type) are still indexed in their
    dedicated type. Header indexing is expensive as each header
    currently need to be stored as a nested document but turning
    off headers indexing result in non-strict compliance with the
    IMAP / JMAP standards.
---
 .../james/mailbox/opensearch/IndexHeaders.java     | 24 +++++++++
 .../opensearch/OpenSearchMailboxConfiguration.java | 35 ++++++++++---
 .../mailbox/opensearch/json/IndexableMessage.java  | 19 ++++++-
 .../opensearch/json/MessageToOpenSearchJson.java   | 11 ++--
 .../opensearch/OpenSearchIntegrationTest.java      |  2 +-
 .../OpenSearchListeningMessageSearchIndexTest.java |  7 ++-
 .../opensearch/json/IndexableMessageTest.java      | 45 +++++++++++++++++
 .../json/MessageToOpenSearchJsonTest.java          | 58 +++++++++++++++-------
 .../opensearch/search/OpenSearchSearcherTest.java  |  3 +-
 .../src/test/resources/eml/spamMailNoHeaders.json  | 45 +++++++++++++++++
 .../elasticsearch/host/OpenSearchHostSystem.java   |  3 +-
 .../modules/ROOT/pages/configure/opensearch.adoc   |  6 +++
 .../modules/mailbox/OpenSearchMailboxModule.java   |  8 ++-
 .../james/webadmin/routes/MailboxesRoutesTest.java |  3 +-
 .../webadmin/routes/UserMailboxesRoutesTest.java   |  3 +-
 src/site/xdoc/server/config-opensearch.xml         |  5 ++
 16 files changed, 238 insertions(+), 39 deletions(-)

diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/IndexHeaders.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/IndexHeaders.java
new file mode 100644
index 0000000000..699f62cc59
--- /dev/null
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/IndexHeaders.java
@@ -0,0 +1,24 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.opensearch;
+
+public enum IndexHeaders {
+    NO, YES
+}
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/OpenSearchMailboxConfiguration.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/OpenSearchMailboxConfiguration.java
index a3a0f7144b..cfa20857f2 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/OpenSearchMailboxConfiguration.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/OpenSearchMailboxConfiguration.java
@@ -34,12 +34,14 @@ public class OpenSearchMailboxConfiguration {
         private Optional<ReadAliasName> readAliasMailboxName;
         private Optional<WriteAliasName> writeAliasMailboxName;
         private Optional<IndexAttachments> indexAttachment;
+        private Optional<IndexHeaders> indexHeaders;
 
         Builder() {
             indexMailboxName = Optional.empty();
             readAliasMailboxName = Optional.empty();
             writeAliasMailboxName = Optional.empty();
             indexAttachment = Optional.empty();
+            indexHeaders = Optional.empty();
         }
 
         Builder indexMailboxName(Optional<IndexName> indexMailboxName) {
@@ -57,20 +59,23 @@ public class OpenSearchMailboxConfiguration {
             return this;
         }
 
-
         Builder indexAttachment(IndexAttachments indexAttachment) {
             this.indexAttachment = Optional.of(indexAttachment);
             return this;
         }
 
-
+        Builder indexHeaders(IndexHeaders indexHeaders) {
+            this.indexHeaders = Optional.of(indexHeaders);
+            return this;
+        }
 
         public OpenSearchMailboxConfiguration build() {
             return new OpenSearchMailboxConfiguration(
                 indexMailboxName.orElse(MailboxOpenSearchConstants.DEFAULT_MAILBOX_INDEX),
                 readAliasMailboxName.orElse(MailboxOpenSearchConstants.DEFAULT_MAILBOX_READ_ALIAS),
                 writeAliasMailboxName.orElse(MailboxOpenSearchConstants.DEFAULT_MAILBOX_WRITE_ALIAS),
-                indexAttachment.orElse(IndexAttachments.YES));
+                indexAttachment.orElse(IndexAttachments.YES),
+                indexHeaders.orElse(IndexHeaders.YES));
         }
     }
 
@@ -85,7 +90,9 @@ public class OpenSearchMailboxConfiguration {
     private static final String OPENSEARCH_ALIAS_READ_MAILBOX_NAME = "opensearch.alias.read.mailbox.name";
     private static final String OPENSEARCH_ALIAS_WRITE_MAILBOX_NAME = "opensearch.alias.write.mailbox.name";
     private static final String OPENSEARCH_INDEX_ATTACHMENTS = "opensearch.indexAttachments";
+    private static final String OPENSEARCH_INDEX_HEADERS = "opensearch.indexHeaders";
     private static final boolean DEFAULT_INDEX_ATTACHMENTS = true;
+    private static final boolean DEFAULT_INDEX_HEADERS = true;
 
     public static final OpenSearchMailboxConfiguration DEFAULT_CONFIGURATION = builder().build();
 
@@ -95,6 +102,7 @@ public class OpenSearchMailboxConfiguration {
             .readAliasMailboxName(computeMailboxReadAlias(configuration))
             .writeAliasMailboxName(computeMailboxWriteAlias(configuration))
             .indexAttachment(provideIndexAttachments(configuration))
+            .indexHeaders(provideIndexHeaders(configuration))
             .build();
     }
 
@@ -119,29 +127,35 @@ public class OpenSearchMailboxConfiguration {
                 .map(ReadAliasName::new));
     }
 
-
     private static IndexAttachments provideIndexAttachments(Configuration configuration) {
         if (configuration.getBoolean(OPENSEARCH_INDEX_ATTACHMENTS, DEFAULT_INDEX_ATTACHMENTS)) {
             return IndexAttachments.YES;
         }
         return IndexAttachments.NO;
     }
-
+    
+    private static IndexHeaders provideIndexHeaders(Configuration configuration) {
+        if (configuration.getBoolean(OPENSEARCH_INDEX_HEADERS, DEFAULT_INDEX_HEADERS)) {
+            return IndexHeaders.YES;
+        }
+        return IndexHeaders.NO;
+    }
 
     private final IndexName indexMailboxName;
     private final ReadAliasName readAliasMailboxName;
     private final WriteAliasName writeAliasMailboxName;
     private final IndexAttachments indexAttachment;
+    private final IndexHeaders indexHeaders;
 
     private OpenSearchMailboxConfiguration(IndexName indexMailboxName, ReadAliasName readAliasMailboxName,
-                                           WriteAliasName writeAliasMailboxName, IndexAttachments indexAttachment) {
+                                           WriteAliasName writeAliasMailboxName, IndexAttachments indexAttachment, IndexHeaders indexHeaders) {
         this.indexMailboxName = indexMailboxName;
         this.readAliasMailboxName = readAliasMailboxName;
         this.writeAliasMailboxName = writeAliasMailboxName;
         this.indexAttachment = indexAttachment;
+        this.indexHeaders = indexHeaders;
     }
 
-
     public IndexName getIndexMailboxName() {
         return indexMailboxName;
     }
@@ -158,12 +172,17 @@ public class OpenSearchMailboxConfiguration {
         return indexAttachment;
     }
 
+    public IndexHeaders getIndexHeaders() {
+        return indexHeaders;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof OpenSearchMailboxConfiguration) {
             OpenSearchMailboxConfiguration that = (OpenSearchMailboxConfiguration) o;
 
             return Objects.equals(this.indexAttachment, that.indexAttachment)
+                && Objects.equals(this.indexHeaders, that.indexHeaders)
                 && Objects.equals(this.indexMailboxName, that.indexMailboxName)
                 && Objects.equals(this.readAliasMailboxName, that.readAliasMailboxName)
                 && Objects.equals(this.writeAliasMailboxName, that.writeAliasMailboxName);
@@ -173,6 +192,6 @@ public class OpenSearchMailboxConfiguration {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(indexMailboxName, readAliasMailboxName, writeAliasMailboxName, indexAttachment, writeAliasMailboxName);
+        return Objects.hash(indexMailboxName, readAliasMailboxName, writeAliasMailboxName, indexAttachment, indexHeaders, writeAliasMailboxName);
     }
 }
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/IndexableMessage.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/IndexableMessage.java
index 68725eff0f..be7e22b6d8 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/IndexableMessage.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/IndexableMessage.java
@@ -31,6 +31,7 @@ import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.mailbox.model.MessageAttachmentMetadata;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.store.search.SearchUtil;
 import org.apache.james.mime4j.MimeException;
@@ -56,9 +57,9 @@ public class IndexableMessage {
         }
 
         private IndexAttachments indexAttachments;
+        private IndexHeaders indexHeaders;
         private MailboxMessage message;
         private TextExtractor textExtractor;
-
         private ZoneId zoneId;
 
         private Builder() {
@@ -68,6 +69,7 @@ public class IndexableMessage {
             Preconditions.checkNotNull(message.getMailboxId());
             Preconditions.checkNotNull(textExtractor);
             Preconditions.checkNotNull(indexAttachments);
+            Preconditions.checkNotNull(indexHeaders);
             Preconditions.checkNotNull(zoneId);
 
             try {
@@ -87,6 +89,11 @@ public class IndexableMessage {
             return this;
         }
 
+        public Builder indexHeaders(IndexHeaders indexHeaders) {
+            this.indexHeaders = indexHeaders;
+            return this;
+        }
+
         public Builder message(MailboxMessage message) {
             this.message = message;
             return this;
@@ -149,7 +156,7 @@ public class IndexableMessage {
                         date,
                         from,
                         hasAttachment,
-                        headers,
+                        filterHeadersIfNeeded(headers),
                         isAnswered,
                         isDeleted,
                         isDraft,
@@ -173,6 +180,14 @@ public class IndexableMessage {
                 });
         }
 
+        private List<HeaderCollection.Header> filterHeadersIfNeeded(List<HeaderCollection.Header> headers) {
+            if (IndexHeaders.YES.equals(indexHeaders)) {
+                return headers;
+            } else {
+                return ImmutableList.of();
+            }
+        }
+
         private List<MimePart> setFlattenedAttachments(MimePart parsingResult, IndexAttachments indexAttachments) {
             if (IndexAttachments.YES.equals(indexAttachments)) {
                 return parsingResult.getAttachmentsStream()
diff --git a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJson.java b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJson.java
index fb7b97fdb1..4dfed28820 100644
--- a/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJson.java
+++ b/mailbox/opensearch/src/main/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJson.java
@@ -27,6 +27,7 @@ import javax.mail.Flags;
 import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.extractor.TextExtractor;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -44,19 +45,21 @@ public class MessageToOpenSearchJson {
     private final TextExtractor textExtractor;
     private final ZoneId zoneId;
     private final IndexAttachments indexAttachments;
+    private final IndexHeaders indexHeaders;
 
-    public MessageToOpenSearchJson(TextExtractor textExtractor, ZoneId zoneId, IndexAttachments indexAttachments) {
+    public MessageToOpenSearchJson(TextExtractor textExtractor, ZoneId zoneId, IndexAttachments indexAttachments, IndexHeaders indexHeaders) {
         this.textExtractor = textExtractor;
         this.zoneId = zoneId;
         this.indexAttachments = indexAttachments;
+        this.indexHeaders = indexHeaders;
         this.mapper = new ObjectMapper();
         this.mapper.registerModule(new GuavaModule());
         this.mapper.registerModule(new Jdk8Module());
     }
 
     @Inject
-    public MessageToOpenSearchJson(TextExtractor textExtractor, IndexAttachments indexAttachments) {
-        this(textExtractor, ZoneId.systemDefault(), indexAttachments);
+    public MessageToOpenSearchJson(TextExtractor textExtractor, IndexAttachments indexAttachments, IndexHeaders indexHeaders) {
+        this(textExtractor, ZoneId.systemDefault(), indexAttachments, indexHeaders);
     }
 
     public Mono<String> convertToJson(MailboxMessage message) {
@@ -67,6 +70,7 @@ public class MessageToOpenSearchJson {
             .extractor(textExtractor)
             .zoneId(zoneId)
             .indexAttachments(indexAttachments)
+            .indexHeaders(indexHeaders)
             .build()
             .map(Throwing.function(mapper::writeValueAsString));
     }
@@ -77,6 +81,7 @@ public class MessageToOpenSearchJson {
             .extractor(textExtractor)
             .zoneId(zoneId)
             .indexAttachments(IndexAttachments.NO)
+            .indexHeaders(indexHeaders)
             .build()
             .map(Throwing.function(mapper::writeValueAsString));
     }
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
index 4d6c23f7a1..66c25e9f46 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/OpenSearchIntegrationTest.java
@@ -135,7 +135,7 @@ class OpenSearchIntegrationTest extends AbstractMessageSearchIndexTest {
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_WRITE_ALIAS),
                 new OpenSearchSearcher(client, new QueryConverter(new CriterionConverter()), SEARCH_SIZE,
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_READ_ALIAS, routingKeyFactory),
-                new MessageToOpenSearchJson(textExtractor, ZoneId.of("Europe/Paris"), IndexAttachments.YES),
+                new MessageToOpenSearchJson(textExtractor, ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES),
                 preInstanciationStage.getSessionProvider(), routingKeyFactory, messageIdFactory))
             .noPreDeletionHooks()
             .storeQuotaManager()
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java
index c50e447cb6..22d9e723c8 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/events/OpenSearchListeningMessageSearchIndexTest.java
@@ -67,6 +67,7 @@ import org.apache.james.mailbox.model.ThreadId;
 import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.opensearch.MailboxIdRoutingKeyFactory;
 import org.apache.james.mailbox.opensearch.MailboxIndexCreationUtil;
 import org.apache.james.mailbox.opensearch.MailboxOpenSearchConstants;
@@ -188,7 +189,8 @@ class OpenSearchListeningMessageSearchIndexTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
             ZoneId.of("UTC"),
-            IndexAttachments.YES);
+            IndexAttachments.YES,
+            IndexHeaders.YES);
 
         InMemoryMessageId.Factory messageIdFactory = new InMemoryMessageId.Factory();
 
@@ -272,7 +274,8 @@ class OpenSearchListeningMessageSearchIndexTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new FailingTextExtractor(),
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.YES);
+            IndexAttachments.YES,
+            IndexHeaders.YES);
 
         testee = new OpenSearchListeningMessageSearchIndex(mapperFactory,
             ImmutableSet.of(), openSearchIndexer, openSearchSearcher,
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/IndexableMessageTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/IndexableMessageTest.java
index b477c69f49..96ff8a3a45 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/IndexableMessageTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/IndexableMessageTest.java
@@ -44,6 +44,7 @@ import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.ThreadId;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.james.mailbox.tika.TikaConfiguration;
@@ -112,6 +113,7 @@ class IndexableMessageTest {
                 .extractor(new DefaultTextExtractor())
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -145,6 +147,7 @@ class IndexableMessageTest {
                 .extractor(new DefaultTextExtractor())
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.NO)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -176,6 +179,7 @@ class IndexableMessageTest {
                 .extractor(new DefaultTextExtractor())
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.NO)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -183,6 +187,38 @@ class IndexableMessageTest {
         assertThat(indexableMessage.getAttachments()).isEmpty();
     }
 
+    @Test
+    void headersShouldNotBeenIndexedWhenAsked() throws Exception {
+        //Given
+        MailboxMessage mailboxMessage = mock(MailboxMessage.class);
+        TestId mailboxId = TestId.of(1);
+        when(mailboxMessage.getMailboxId())
+            .thenReturn(mailboxId);
+        when(mailboxMessage.getModSeq())
+            .thenReturn(ModSeq.first());
+        when(mailboxMessage.getMessageId())
+            .thenReturn(InMemoryMessageId.of(42));
+        when(mailboxMessage.getFullContent())
+            .thenReturn(ClassLoader.getSystemResourceAsStream("eml/mailWithHeaders.eml"));
+        when(mailboxMessage.createFlags())
+            .thenReturn(new Flags());
+        when(mailboxMessage.getUid())
+            .thenReturn(MESSAGE_UID);
+
+        // When
+        IndexableMessage indexableMessage = IndexableMessage.builder()
+                .message(mailboxMessage)
+                .extractor(new DefaultTextExtractor())
+                .zoneId(ZoneId.of("Europe/Paris"))
+                .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.NO)
+                .build()
+                .block();
+
+        // Then
+        assertThat(indexableMessage.getHeaders()).isEmpty();
+    }
+
     @Test
     void attachmentsShouldBeenIndexedWhenAsked() throws Exception {
         //Given
@@ -207,6 +243,7 @@ class IndexableMessageTest {
                 .extractor(new DefaultTextExtractor())
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -246,6 +283,7 @@ class IndexableMessageTest {
                 .extractor(textExtractor)
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -283,6 +321,7 @@ class IndexableMessageTest {
                 .extractor(textExtractor)
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -317,6 +356,7 @@ class IndexableMessageTest {
             .extractor(textExtractor)
             .zoneId(ZoneId.of("Europe/Paris"))
             .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
             .build()
             .block();
 
@@ -348,6 +388,7 @@ class IndexableMessageTest {
                 .extractor(textExtractor)
                 .zoneId(ZoneId.of("Europe/Paris"))
                 .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
                 .build()
                 .block();
 
@@ -381,6 +422,7 @@ class IndexableMessageTest {
             .extractor(textExtractor)
             .zoneId(ZoneId.of("Europe/Paris"))
             .indexAttachments(IndexAttachments.YES)
+                .indexHeaders(IndexHeaders.YES)
             .build()
             .block();
 
@@ -415,6 +457,7 @@ class IndexableMessageTest {
             .extractor(new DefaultTextExtractor())
             .zoneId(ZoneId.of("Europe/Paris"))
             .indexAttachments(IndexAttachments.NO)
+            .indexHeaders(IndexHeaders.YES)
             .build()
             .block();
 
@@ -451,6 +494,7 @@ class IndexableMessageTest {
             .extractor(new DefaultTextExtractor())
             .zoneId(ZoneId.of("Europe/Paris"))
             .indexAttachments(IndexAttachments.NO)
+            .indexHeaders(IndexHeaders.YES)
             .build()
             .block();
 
@@ -486,6 +530,7 @@ class IndexableMessageTest {
             .extractor(new DefaultTextExtractor())
             .zoneId(ZoneId.of("Europe/Paris"))
             .indexAttachments(IndexAttachments.NO)
+            .indexHeaders(IndexHeaders.YES)
             .build()
             .block();
 
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJsonTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJsonTest.java
index 5108af0739..ba3af351c0 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJsonTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/json/MessageToOpenSearchJsonTest.java
@@ -43,6 +43,7 @@ import org.apache.james.mailbox.model.TestId;
 import org.apache.james.mailbox.model.TestMessageId;
 import org.apache.james.mailbox.model.ThreadId;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.store.extractor.DefaultTextExtractor;
 import org.apache.james.mailbox.store.extractor.JsoupTextExtractor;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
@@ -95,7 +96,7 @@ class MessageToOpenSearchJsonTest {
     void spamEmailShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage spamMail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -112,11 +113,32 @@ class MessageToOpenSearchJsonTest {
             .isEqualTo(ClassLoaderUtils.getSystemResourceAsString("eml/spamMail.json"));
     }
 
+    @Test
+    void spamEmailShouldBeWellConvertedToJsonWhenNoHeaders() throws IOException {
+        MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
+            new DefaultTextExtractor(),
+            ZoneId.of("Europe/Paris"), IndexAttachments.NO, IndexHeaders.NO);
+        MailboxMessage spamMail = new SimpleMailboxMessage(MESSAGE_ID,
+                THREAD_ID,
+                date,
+                SIZE,
+                BODY_START_OCTET,
+                new ByteContent(IOUtils.toByteArray(ClassLoaderUtils.getSystemResourceAsSharedStream("eml/spamMail.eml"))),
+                new Flags(),
+                propertyBuilder.build(),
+                MAILBOX_ID);
+        spamMail.setUid(UID);
+        spamMail.setModSeq(MOD_SEQ);
+        assertThatJson(messageToOpenSearchJson.convertToJson(spamMail).block())
+            .when(IGNORING_ARRAY_ORDER)
+            .isEqualTo(ClassLoaderUtils.getSystemResourceAsString("eml/spamMailNoHeaders.json"));
+    }
+
     @Test
     void inlinedMultipartEmailShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage mail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -138,7 +160,7 @@ class MessageToOpenSearchJsonTest {
     void invalidCharsetShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage spamMail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -161,7 +183,7 @@ class MessageToOpenSearchJsonTest {
     void htmlEmailShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage htmlMail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -182,7 +204,7 @@ class MessageToOpenSearchJsonTest {
     void pgpSignedEmailShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage pgpSignedMail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -203,7 +225,7 @@ class MessageToOpenSearchJsonTest {
     void simpleEmailShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage mail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -224,7 +246,7 @@ class MessageToOpenSearchJsonTest {
     void recursiveEmailShouldBeWellConvertedToJson() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage recursiveMail = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 date,
@@ -245,7 +267,7 @@ class MessageToOpenSearchJsonTest {
     void emailWithNoInternalDateShouldUseNowDate() throws IOException {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage mailWithNoInternalDate = new SimpleMailboxMessage(MESSAGE_ID,
                 THREAD_ID,
                 null,
@@ -282,7 +304,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.YES);
+            IndexAttachments.YES, IndexHeaders.YES);
         String convertToJson = messageToOpenSearchJson.convertToJson(mailWithNoInternalDate).block();
 
         // Then
@@ -311,7 +333,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.NO);
+            IndexAttachments.NO, IndexHeaders.YES);
         String convertToJson = messageToOpenSearchJson.convertToJson(mailWithNoInternalDate).block();
 
         // Then
@@ -325,7 +347,7 @@ class MessageToOpenSearchJsonTest {
     void emailWithNoMailboxIdShouldThrow() throws Exception {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage mailWithNoMailboxId = new SimpleMailboxMessage(MESSAGE_ID, THREAD_ID, date,
             SIZE,
             BODY_START_OCTET,
@@ -346,7 +368,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.YES);
+            IndexAttachments.YES, IndexHeaders.YES);
         assertThatJson(messageToOpenSearchJson.getUpdatedJsonMessagePart(new Flags(), MOD_SEQ))
             .isEqualTo("{\"modSeq\":42,\"isAnswered\":false,\"isDeleted\":false,\"isDraft\":false,\"isFlagged\":false,\"isRecent\":false,\"userFlags\":[],\"isUnread\":true}");
     }
@@ -356,7 +378,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.YES);
+            IndexAttachments.YES, IndexHeaders.YES);
         assertThatJson(messageToOpenSearchJson.getUpdatedJsonMessagePart(new FlagsBuilder().add(Flags.Flag.DELETED, Flags.Flag.FLAGGED).add("user").build(), MOD_SEQ))
             .isEqualTo("{\"modSeq\":42,\"isAnswered\":false,\"isDeleted\":true,\"isDraft\":false,\"isFlagged\":true,\"isRecent\":false,\"userFlags\":[\"user\"],\"isUnread\":true}");
     }
@@ -366,7 +388,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.YES);
+            IndexAttachments.YES, IndexHeaders.YES);
 
         assertThatThrownBy(() -> messageToOpenSearchJson.getUpdatedJsonMessagePart(null, MOD_SEQ))
             .isInstanceOf(NullPointerException.class);
@@ -377,7 +399,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             textExtractor,
             ZoneId.of("Europe/Paris"),
-            IndexAttachments.YES);
+            IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage spamMail = new SimpleMailboxMessage(MESSAGE_ID, THREAD_ID, date,
             SIZE,
             BODY_START_OCTET,
@@ -413,7 +435,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
                 new DefaultTextExtractor(),
                 ZoneId.of("Europe/Paris"),
-                IndexAttachments.NO);
+                IndexAttachments.NO, IndexHeaders.YES);
         String convertToJsonWithoutAttachment = messageToOpenSearchJson.convertToJsonWithoutAttachment(message).block();
 
         // Then
@@ -442,7 +464,7 @@ class MessageToOpenSearchJsonTest {
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
                 new JsoupTextExtractor(),
                 ZoneId.of("Europe/Paris"),
-                IndexAttachments.NO);
+                IndexAttachments.NO, IndexHeaders.YES);
         String convertToJsonWithoutAttachment = messageToOpenSearchJson.convertToJsonWithoutAttachment(message).block();
 
         // Then
@@ -458,7 +480,7 @@ class MessageToOpenSearchJsonTest {
         Date saveDate = new Date(1433628000000L); // 2015/06/07 00:00:00 0200 (Paris time zone)
         MessageToOpenSearchJson messageToOpenSearchJson = new MessageToOpenSearchJson(
             new DefaultTextExtractor(),
-            ZoneId.of("Europe/Paris"), IndexAttachments.YES);
+            ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES);
         MailboxMessage mail = new SimpleMailboxMessage(MESSAGE_ID,
             THREAD_ID,
             date,
diff --git a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java
index 70fbde8e8b..42faa77a2d 100644
--- a/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java
+++ b/mailbox/opensearch/src/test/java/org/apache/james/mailbox/opensearch/search/OpenSearchSearcherTest.java
@@ -47,6 +47,7 @@ import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
 import org.apache.james.mailbox.model.SearchQuery;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.opensearch.MailboxIdRoutingKeyFactory;
 import org.apache.james.mailbox.opensearch.MailboxIndexCreationUtil;
 import org.apache.james.mailbox.opensearch.MailboxOpenSearchConstants;
@@ -124,7 +125,7 @@ class OpenSearchSearcherTest {
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_WRITE_ALIAS),
                 new OpenSearchSearcher(client, new QueryConverter(new CriterionConverter()), SEARCH_SIZE,
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_READ_ALIAS, routingKeyFactory),
-                new MessageToOpenSearchJson(textExtractor, ZoneId.of("Europe/Paris"), IndexAttachments.YES),
+                new MessageToOpenSearchJson(textExtractor, ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES),
                 preInstanciationStage.getSessionProvider(), routingKeyFactory, messageIdFactory))
             .noPreDeletionHooks()
             .storeQuotaManager()
diff --git a/mailbox/store/src/test/resources/eml/spamMailNoHeaders.json b/mailbox/store/src/test/resources/eml/spamMailNoHeaders.json
new file mode 100644
index 0000000000..6a9ca3f2f3
--- /dev/null
+++ b/mailbox/store/src/test/resources/eml/spamMailNoHeaders.json
@@ -0,0 +1,45 @@
+{
+  "messageId":"184",
+  "threadId": "184",
+  "uid":25,
+  "mailboxId": "18",
+  "modSeq": 42,
+  "size": 25,
+  "date": "2015-06-07T00:00:00+0200",
+  "saveDate": null,
+  "mediaType": "plain",
+  "subtype": "text",
+  "mimeMessageID": "<VA...@spam.minet.net>",
+  "userFlags": [],
+  "headers": [],
+  "from": [
+	{
+	  "name": "Content-filter at spam.minet.net",
+	  "address": "postmaster@minet.net",
+	  "domain": "minet"
+	}
+  ],
+  "to": [
+	{
+	  "name": null,
+	  "address": "root@listes.minet.net",
+      "domain": "listes.minet"
+	}
+  ],
+  "cc": [],
+  "bcc": [],
+  "subject": [
+	"[root] UNCHECKED contents in mail FROM <qu...@riseup.net>"
+  ],
+  "sentDate": "2015-06-03T09:05:46+0000",
+  "attachments": [],
+  "textBody": "No viruses were found.\r\n\r\nContent type: Unchecked\r\nInternal reference code for the message is 12583-16/Ss-IZaXqmZao\r\n\r\nAccording to a 'Received:' trace, the message apparently originated at:\r\n  [198.252.153.129], [127.0.0.1] localhost [127.0.0.1] Authenticated sender:\r\n  quentin.h\r\n\r\nReturn-Path: <qu...@riseup.net>\r\nFrom: Quentin <qu...@riseup.net>\r\nMessage-ID: <55...@riseup.net>\r\nSubject: =?UTF-8?B?UmU6IEZ3ZDogW1RtcGxhYl0gW0FQUEV [...]
+  "htmlBody": null,
+  "isAnswered": false,
+  "isDeleted": false,
+  "isDraft": false,
+  "isFlagged": false,
+  "isRecent": false,
+  "hasAttachment": false,
+  "isUnread": true
+}
diff --git a/mpt/impl/imap-mailbox/opensearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/OpenSearchHostSystem.java b/mpt/impl/imap-mailbox/opensearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/OpenSearchHostSystem.java
index a8dcfcf86b..9808814988 100644
--- a/mpt/impl/imap-mailbox/opensearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/OpenSearchHostSystem.java
+++ b/mpt/impl/imap-mailbox/opensearch/src/test/java/org/apache/james/mpt/imapmailbox/elasticsearch/host/OpenSearchHostSystem.java
@@ -38,6 +38,7 @@ import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.inmemory.InMemoryMessageId;
 import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.opensearch.MailboxIdRoutingKeyFactory;
 import org.apache.james.mailbox.opensearch.MailboxIndexCreationUtil;
 import org.apache.james.mailbox.opensearch.MailboxOpenSearchConstants;
@@ -103,7 +104,7 @@ public class OpenSearchHostSystem extends JamesImapHostSystem {
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_WRITE_ALIAS),
                 new OpenSearchSearcher(client, new QueryConverter(new CriterionConverter()), OpenSearchSearcher.DEFAULT_SEARCH_SIZE,
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_READ_ALIAS, routingKeyFactory),
-                new MessageToOpenSearchJson(new DefaultTextExtractor(), ZoneId.of("Europe/Paris"), IndexAttachments.YES),
+                new MessageToOpenSearchJson(new DefaultTextExtractor(), ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES),
                 preInstanciationStage.getSessionProvider(), routingKeyFactory, messageIdFactory))
             .noPreDeletionHooks()
             .storeQuotaManager()
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/opensearch.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/opensearch.adoc
index 80ddd1260e..85b289e8c8 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/opensearch.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/opensearch.adoc
@@ -85,6 +85,12 @@ The target of the alias is the index name configured above.
 
 | opensearch.indexAttachments
 | Indicates if you wish to index attachments or not (default: true).
+
+| opensearch.indexHeaders
+| Indicates if you wish to index headers or not (default: true). Note that specific headers
+(From, To, Cc, Bcc, Subject, Message-Id, Date, Content-Type) are still indexed in their dedicated type.
+Header indexing is expensive as each header currently need to be stored as a nested document but
+turning off headers indexing result in non-strict compliance with the IMAP / JMAP standards.
 |===
 
 === Quota search
diff --git a/server/container/guice/opensearch/src/main/java/org/apache/james/modules/mailbox/OpenSearchMailboxModule.java b/server/container/guice/opensearch/src/main/java/org/apache/james/modules/mailbox/OpenSearchMailboxModule.java
index 6f7e90bd04..c7aaa8e772 100644
--- a/server/container/guice/opensearch/src/main/java/org/apache/james/modules/mailbox/OpenSearchMailboxModule.java
+++ b/server/container/guice/opensearch/src/main/java/org/apache/james/modules/mailbox/OpenSearchMailboxModule.java
@@ -39,6 +39,7 @@ import org.apache.james.lifecycle.api.StartUpCheck;
 import org.apache.james.lifecycle.api.Startable;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.opensearch.MailboxIdRoutingKeyFactory;
 import org.apache.james.mailbox.opensearch.MailboxIndexCreationUtil;
 import org.apache.james.mailbox.opensearch.MailboxOpenSearchConstants;
@@ -180,11 +181,16 @@ public class OpenSearchMailboxModule extends AbstractModule {
         return configuration.getIndexAttachment();
     }
 
+    @Provides
+    @Singleton
+    public IndexHeaders provideIndexHeaders(OpenSearchMailboxConfiguration configuration) {
+        return configuration.getIndexHeaders();
+    }
+
     @ProvidesIntoSet
     InitializationOperation createIndex(MailboxIndexCreator instance) {
         return InitilizationOperationBuilder
             .forClass(MailboxIndexCreator.class)
             .init(instance::createIndex);
     }
-
 }
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
index d78b2899cd..376271045d 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MailboxesRoutesTest.java
@@ -67,6 +67,7 @@ import org.apache.james.mailbox.model.MessageResult;
 import org.apache.james.mailbox.model.ThreadId;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.opensearch.MailboxIdRoutingKeyFactory;
 import org.apache.james.mailbox.opensearch.MailboxIndexCreationUtil;
 import org.apache.james.mailbox.opensearch.MailboxOpenSearchConstants;
@@ -161,7 +162,7 @@ class MailboxesRoutesTest {
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_WRITE_ALIAS),
                 new OpenSearchSearcher(client, new QueryConverter(new CriterionConverter()), SEARCH_SIZE,
                     MailboxOpenSearchConstants.DEFAULT_MAILBOX_READ_ALIAS, routingKeyFactory),
-                new MessageToOpenSearchJson(new DefaultTextExtractor(), ZoneId.of("Europe/Paris"), IndexAttachments.YES),
+                new MessageToOpenSearchJson(new DefaultTextExtractor(), ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES),
                 preInstanciationStage.getSessionProvider(), routingKeyFactory, messageIdFactory))
             .noPreDeletionHooks()
             .storeQuotaManager()
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
index 9a818bc828..3fa93a7d3e 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/UserMailboxesRoutesTest.java
@@ -90,6 +90,7 @@ import org.apache.james.mailbox.model.UidValidity;
 import org.apache.james.mailbox.model.UpdatedFlags;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.opensearch.IndexAttachments;
+import org.apache.james.mailbox.opensearch.IndexHeaders;
 import org.apache.james.mailbox.opensearch.MailboxIdRoutingKeyFactory;
 import org.apache.james.mailbox.opensearch.MailboxIndexCreationUtil;
 import org.apache.james.mailbox.opensearch.MailboxOpenSearchConstants;
@@ -1479,7 +1480,7 @@ class UserMailboxesRoutesTest {
                         MailboxOpenSearchConstants.DEFAULT_MAILBOX_WRITE_ALIAS),
                     new OpenSearchSearcher(client, new QueryConverter(new CriterionConverter()), SEARCH_SIZE,
                         MailboxOpenSearchConstants.DEFAULT_MAILBOX_READ_ALIAS, routingKeyFactory),
-                    new MessageToOpenSearchJson(new DefaultTextExtractor(), ZoneId.of("Europe/Paris"), IndexAttachments.YES),
+                    new MessageToOpenSearchJson(new DefaultTextExtractor(), ZoneId.of("Europe/Paris"), IndexAttachments.YES, IndexHeaders.YES),
                     preInstanciationStage.getSessionProvider(), routingKeyFactory, messageIdFactory))
                 .noPreDeletionHooks()
                 .storeQuotaManager()
diff --git a/src/site/xdoc/server/config-opensearch.xml b/src/site/xdoc/server/config-opensearch.xml
index 09dedf2aac..bea64dc242 100644
--- a/src/site/xdoc/server/config-opensearch.xml
+++ b/src/site/xdoc/server/config-opensearch.xml
@@ -113,6 +113,11 @@
           <dd>Minimum delay between connection attempts</dd>
           <dt><strong>opensearch.indexAttachments</strong></dt>
           <dd>Indicates if you wish to index attachments or not (default: true).</dd>
+          <dt><strong>opensearch.indexHeaders</strong></dt>
+          <dd>Indicates if you wish to index headers or not (default: true). Note that specific headers
+              (From, To, Cc, Bcc, Subject, Message-Id, Date, Content-Type) are still indexed in their dedicated type.
+              Header indexing is expensive as each header currently need to be stored as a nested document but
+              turning off headers indexing result in non-strict compliance with the IMAP / JMAP standards.</dd>
           <dt><strong>opensearch.index.quota.ratio.name</strong></dt>
           <dd>Specify the OpenSearch alias name used for quotas</dd>
           <dt><strong>opensearch.alias.read.quota.ratio.name</strong></dt>


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org