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

tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new 4e781e23d0 TIKA-4890: detect and parse Apple Mail emlx files (#3207)
4e781e23d0 is described below

commit 4e781e23d0991004d4cbb9e50e1450f284fd4e40
Author: Tim Allison <[email protected]>
AuthorDate: Sat Sep 19 07:29:43 2026 -0400

    TIKA-4890: detect and parse Apple Mail emlx files (#3207)
---
 CHANGES.txt                                        |   5 +
 docs/modules/ROOT/partials/supported-formats.adoc  |   1 +
 .../org/apache/tika/mime/tika-mimetypes.xml        |  19 ++--
 .../org/apache/tika/mime/EMLXDetectionTest.java    |  88 ++++++++++++++++++
 .../java/org/apache/tika/mime/TestMimeTypes.java   |   2 +
 .../org/apache/tika/parser/mail/RFC822Parser.java  |  49 +++++++++-
 .../java/org/apache/tika/parser/mail/EMLXTest.java | 103 +++++++++++++++++++++
 .../test-documents/testEMLX_multipart_html.emlx    |  86 +++++++++++++++++
 .../test-documents/testEMLX_single_part_html.emlx  |  24 +++++
 9 files changed, 364 insertions(+), 13 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 014218bc0c..077021aee5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,10 @@
 Release 4.1.0 - unreleased
 
+   * Apple Mail emlx files are detected as message/x-emlx (real files pad the
+     byte-count line to 10 columns and were falling through to text/html or
+     message/rfc822), and RFC822Parser now parses them, dropping the byte-count
+     line and the trailing plist (TIKA-4890).
+
    * The tika-server UAT gains an inference pass (TIKA-4913).
      
    * Calls to a hosted inference engine retry a 429, 502, 503 or 504 answer
diff --git a/docs/modules/ROOT/partials/supported-formats.adoc 
b/docs/modules/ROOT/partials/supported-formats.adoc
index c261b37641..e6b296902e 100644
--- a/docs/modules/ROOT/partials/supported-formats.adoc
+++ b/docs/modules/ROOT/partials/supported-formats.adoc
@@ -161,6 +161,7 @@
 ** `application/vnd.apple.pages.18`
 * `org.apache.tika.parser.mail.` 
link:{tika-javadoc-url}/org/apache/tika/parser/mail/RFC822Parser.html[RFC822Parser]
 ** `message/rfc822`
+** `message/x-emlx`
 * `org.apache.tika.parser.markdown.` 
link:{tika-javadoc-url}/org/apache/tika/parser/markdown/MarkdownParser.html[MarkdownParser]
 ** `text/markdown`
 * `org.apache.tika.parser.mat.` 
link:{tika-javadoc-url}/org/apache/tika/parser/mat/MatParser.html[MatParser]
diff --git 
a/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml 
b/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
index bd98b2ae40..e88e55adf0 100644
--- a/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
+++ b/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
@@ -3970,17 +3970,16 @@
   </mime-type>
 
   <mime-type type="message/x-emlx">
+    <_comment>Apple Mail message</_comment>
+    <!-- line 1 is the message's byte count, which Apple Mail pads with spaces 
to 10
+         columns; line 2 is the first RFC822 header. An XML plist follows the 
message,
+         but it is beyond the magic window -->
     <magic priority="70">
-      <match value="\nRelay-Version:" type="string" offset="2:9"/>
-      <match value="\n#!\ rnews" type="string" offset="2:9"/>
-      <match value="\nN#!\ rnews" type="string" offset="2:9"/>
-      <match value="\nForward\ to" type="string" offset="2:9"/>
-      <match value="\nPipe\ to" type="string" offset="2:9"/>
-      <match value="\nReturn-Path:" type="string" offset="2:9"/>
-      <match value="\nFrom:" type="string" offset="2:9"/>
-      <match value="\nReceived:" type="string" offset="2:9"/>
-      <match value="\nMessage-ID:" type="string" offset="2:9"/>
-      <match value="\nDate:" type="string" offset="2:9"/>
+      <!-- gate: the count line ends within the first 11 bytes; keeps the 
regex (an 8K
+           decode per evaluation) off files that cannot be emlx -->
+      <match value="\n" type="string" offset="1:10">
+        <match value="(?i)[0-9]{1,10} 
{0,9}\n((Authentication-Results|Content-Type|Date|Delivered-To|From|Message-ID|MIME-Version|Received|Received-SPF|Return-Path|Subject|To):|(X|DKIM|ARC)-)"
 type="regex" offset="0"/>
+      </match>
     </magic>
     <glob pattern="*.emlx"/>
     <sub-class-of type="text/x-tika-text-based-message"/>
diff --git 
a/tika-core/src/test/java/org/apache/tika/mime/EMLXDetectionTest.java 
b/tika-core/src/test/java/org/apache/tika/mime/EMLXDetectionTest.java
new file mode 100644
index 0000000000..caa909558e
--- /dev/null
+++ b/tika-core/src/test/java/org/apache/tika/mime/EMLXDetectionTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.tika.mime;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.jupiter.api.Test;
+
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.ParseContext;
+
+public class EMLXDetectionTest {
+
+    private static final MimeTypes MIME_TYPES = 
MimeTypes.getDefaultMimeTypes();
+
+    private static final String HEADERS = "From: [email protected]\nTo: 
[email protected]\n" +
+            "Subject: hi\nDate: Sat, 26 Sep 2015 09:30:20 -0700\n\nbody\n";
+
+    @Test
+    public void testByteCountLine() throws Exception {
+        // Apple Mail pads the count to 10 columns; an unpadded count is 
accepted too
+        assertMime("message/x-emlx", "1795      \n" + HEADERS);
+        assertMime("message/x-emlx", "1795\n" + HEADERS);
+        assertMime("message/x-emlx", "1\n" + HEADERS);
+        assertMime("message/x-emlx", "1234567890\n" + HEADERS);
+
+        // not a byte count
+        assertMime("message/rfc822", HEADERS);
+        assertMime("text/plain", "Hello\n" + HEADERS);
+        assertMime("text/plain", "17 95\n" + HEADERS);
+        assertMime("text/plain", "1795 \n\n" + HEADERS);
+        assertMime("text/plain", "12345678901\n" + HEADERS);
+    }
+
+    @Test
+    public void testFirstHeader() throws Exception {
+        for (String header : new String[]{"Delivered-To: [email protected]", 
"Return-Path: <[email protected]>",
+                "Received: from mx.example.com", "X-Original-To: 
[email protected]",
+                "DKIM-Signature: v=1; a=rsa-sha256", "ARC-Seal: i=1; 
a=rsa-sha256",
+                "Authentication-Results: mx.example.com; spf=pass",
+                "Received-SPF: pass (mx.example.com: ...)", "Subject: hi",
+                "Mime-Version: 1.0 (Mac OS X Mail 13.4 \\(3608.120.23.2.7\\))",
+                "Content-Type: text/html;", "Message-Id: <[email protected]>"}) 
{
+            assertMime("message/x-emlx", "701       \n" + header + "\n" + 
HEADERS);
+        }
+        assertMime("text/plain", "701       \nNot a header\n" + HEADERS);
+        assertMime("text/plain", "701       \n\n" + HEADERS);
+    }
+
+    @Test
+    public void testHtmlPartDoesNotWin() throws Exception {
+        // a long header block pushes Message-ID past the rfc822 window while
+        // an html part sits inside the html window
+        StringBuilder sb = new StringBuilder("4569      \nDelivered-To: 
[email protected]\n");
+        for (int i = 0; i < 12; i++) {
+            sb.append("Received: from relay").append(i)
+                    .append(".example.com by mx.example.com with ESMTP id 
abc").append(i)
+                    .append("; Sat, 26 Sep 2015 13:02:49 -0700 (PDT)\n");
+        }
+        sb.append(HEADERS.replace("\nbody\n", 
"\n<html><body>body</body></html>\n"));
+        assertMime("message/x-emlx", sb.toString());
+    }
+
+    private void assertMime(String expected, String txt) throws IOException {
+        try (TikaInputStream tis = 
TikaInputStream.get(txt.getBytes(StandardCharsets.UTF_8))) {
+            MediaType mediaType = MIME_TYPES.detect(tis, new Metadata(), new 
ParseContext());
+            assertEquals(expected, mediaType.toString(), txt);
+        }
+    }
+}
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypes.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypes.java
index 74c2035772..8ec7ae208d 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypes.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/mime/TestMimeTypes.java
@@ -1041,6 +1041,8 @@ public class TestMimeTypes {
     public void testEmail() throws IOException {
         // EMLX
         assertTypeDetection("testEMLX.emlx", "message/x-emlx");
+        assertTypeDetection("testEMLX_multipart_html.emlx", "message/x-emlx");
+        assertTypeDetection("testEMLX_single_part_html.emlx", 
"message/x-emlx");
 
         // Groupwise
         assertTypeDetection("testGroupWiseEml.eml", "message/rfc822");
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
index 0fe3ce1e4b..cee6a203b1 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/RFC822Parser.java
@@ -17,7 +17,10 @@
 package org.apache.tika.parser.mail;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.james.mime4j.MimeException;
@@ -34,6 +37,7 @@ import org.apache.tika.detect.Detector;
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.exception.ZeroByteFileException;
 import org.apache.tika.extractor.EmbeddedDocumentUtil;
+import org.apache.tika.io.BoundedInputStream;
 import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.mime.MediaType;
@@ -45,6 +49,9 @@ import org.apache.tika.sax.XHTMLContentHandler;
  * Uses apache-mime4j to parse emails. Each part is treated with the
  * corresponding parser and displayed within elements.
  * <p/>
+ * Also handles Apple Mail's emlx framing: a first line carrying the message's
+ * byte count, and an XML plist after the message. Both are dropped.
+ * <p/>
  * A {@link MimeConfig} object can be passed in the parsing context
  * to better control the parsing process.
  *
@@ -72,8 +79,12 @@ public class RFC822Parser implements Parser {
         }
     }
 
-    private static final Set<MediaType> SUPPORTED_TYPES =
-            Collections.singleton(MediaType.parse("message/rfc822"));
+    private static final Set<MediaType> SUPPORTED_TYPES = 
Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(MediaType.parse("message/rfc822"),
+                    MediaType.parse("message/x-emlx"))));
+
+    // digits, then Apple Mail's space padding to 10 columns, then the newline
+    private static final int EMLX_COUNT_LINE_MAX = 11;
 
     //rely on the detector to be thread-safe
     //built lazily and then reused
@@ -134,7 +145,12 @@ public class RFC822Parser implements Parser {
         xhtml.startDocument();
         checkForZeroByte(tis);//avoid stackoverflow
         try {
-            parser.parse(tis);
+            InputStream message = tis;
+            long emlxLength = readEmlxByteCount(tis);
+            if (emlxLength >= 0) {
+                message = new BoundedInputStream(emlxLength, tis);
+            }
+            parser.parse(message);
         } catch (IOException e) {
             tis.throwIfCauseOf(e);
             throw new TikaException("Failed to parse an email message", e);
@@ -152,6 +168,33 @@ public class RFC822Parser implements Parser {
         xhtml.endDocument();
     }
 
+    /**
+     * Consumes the emlx byte-count line if the stream starts with one.
+     *
+     * @return the message's length in bytes, or -1 if the stream is not emlx 
framed
+     */
+    private static long readEmlxByteCount(TikaInputStream tis) throws 
IOException {
+        tis.mark(EMLX_COUNT_LINE_MAX);
+        long count = 0;
+        int digits = 0;
+        boolean padding = false;
+        for (int i = 0; i < EMLX_COUNT_LINE_MAX; i++) {
+            int c = tis.read();
+            if (c >= '0' && c <= '9' && !padding) {
+                count = count * 10 + (c - '0');
+                digits++;
+            } else if (c == ' ' && digits > 0) {
+                padding = true;
+            } else if (c == '\n' && digits > 0) {
+                return count;
+            } else {
+                break;
+            }
+        }
+        tis.reset();
+        return -1;
+    }
+
     private void checkForZeroByte(TikaInputStream tstream) throws IOException, 
ZeroByteFileException {
         tstream.mark(1);
         try {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/java/org/apache/tika/parser/mail/EMLXTest.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/java/org/apache/tika/parser/mail/EMLXTest.java
new file mode 100644
index 0000000000..33a8fd4a25
--- /dev/null
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/java/org/apache/tika/parser/mail/EMLXTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.tika.parser.mail;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.nio.charset.StandardCharsets;
+
+import org.junit.jupiter.api.Test;
+
+import org.apache.tika.TikaTest;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.metadata.HttpHeaders;
+import org.apache.tika.metadata.Message;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaCoreProperties;
+import org.apache.tika.parser.AutoDetectParser;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.parser.Parser;
+
+/**
+ * Apple Mail emlx: a byte-count line, the RFC822 message, then an XML plist.
+ */
+public class EMLXTest extends TikaTest {
+
+    private static final String PLIST = "<?xml version=\"1.0\" 
encoding=\"UTF-8\"?>\n" +
+            "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" " +
+            "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\";>\n" +
+            "<plist version=\"1.0\">\n<dict>\n\t<key>date-received</key>\n" +
+            "\t<integer>1698393810</integer>\n</dict>\n</plist>\n";
+
+    @Test
+    public void testLongHeaderBlockWithHtmlAlternative() throws Exception {
+        XMLResult r = getXML("testEMLX_multipart_html.emlx");
+        assertEquals("message/x-emlx", 
r.metadata.get(HttpHeaders.CONTENT_TYPE));
+        assertEquals("Set the Foundation Straight", 
r.metadata.get(TikaCoreProperties.TITLE));
+        assertEquals("[email protected]", 
r.metadata.get(Message.MESSAGE_FROM_EMAIL));
+        assertEquals("2015-09-26T16:30:20Z", 
r.metadata.get(TikaCoreProperties.CREATED));
+        assertContains("The plan for the Foundation is in this message’s HTML 
part.", r.xml);
+        assertPlistAndCountDropped(r.xml, "2803");
+    }
+
+    @Test
+    public void testSinglePartHtml() throws Exception {
+        XMLResult r = getXML("testEMLX_single_part_html.emlx");
+        assertEquals("message/x-emlx", 
r.metadata.get(HttpHeaders.CONTENT_TYPE));
+        assertEquals("Trial balance", 
r.metadata.get(TikaCoreProperties.TITLE));
+        assertContains("The trial balance is ready for review.", r.xml);
+        assertPlistAndCountDropped(r.xml, "446");
+    }
+
+    @Test
+    public void testUnpaddedByteCount() throws Exception {
+        String message = "Subject: Unpadded\nFrom: [email protected]\nTo: 
[email protected]\n\n" +
+                "the body\n";
+        String emlx = message.length() + "\n" + message + PLIST;
+        try (TikaInputStream tis = 
TikaInputStream.get(emlx.getBytes(StandardCharsets.US_ASCII))) {
+            XMLResult r = getXML(tis, new AutoDetectParser(), new Metadata());
+            assertEquals("message/x-emlx", 
r.metadata.get(HttpHeaders.CONTENT_TYPE));
+            assertEquals("Unpadded", r.metadata.get(TikaCoreProperties.TITLE));
+            assertContains("the body", r.xml);
+            assertPlistAndCountDropped(r.xml, 
Integer.toString(message.length()));
+        }
+    }
+
+    @Test
+    public void testForcedTypeStillStripsFraming() throws Exception {
+        // an emlx handed to the parser as message/rfc822 must not leak the 
plist either
+        String message = "Subject: Forced\nFrom: [email protected]\n\nthe 
body\n";
+        String emlx = (message.length() + "      \n") + message + PLIST;
+        Metadata metadata = new Metadata();
+        metadata.set(HttpHeaders.CONTENT_TYPE, "message/rfc822");
+        ParseContext context = new ParseContext();
+        context.set(Parser.class, new AutoDetectParser());
+        try (TikaInputStream tis = 
TikaInputStream.get(emlx.getBytes(StandardCharsets.US_ASCII))) {
+            XMLResult r = getXML(tis, new RFC822Parser(), metadata, context);
+            assertEquals("Forced", r.metadata.get(TikaCoreProperties.TITLE));
+            assertContains("the body", r.xml);
+            assertPlistAndCountDropped(r.xml, 
Integer.toString(message.length()));
+        }
+    }
+
+    private static void assertPlistAndCountDropped(String xml, String 
byteCount) {
+        String body = xml.substring(xml.indexOf("<body"));
+        assertNotContained(byteCount, body);
+        assertNotContained("date-received", body);
+        assertNotContained("plist", body);
+    }
+}
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/resources/test-documents/testEMLX_multipart_html.emlx
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/resources/test-documents/testEMLX_multipart_html.emlx
new file mode 100644
index 0000000000..bc470cbaae
--- /dev/null
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/resources/test-documents/testEMLX_multipart_html.emlx
@@ -0,0 +1,86 @@
+2803      
+Delivered-To: [email protected]
+Received: by 10.0.0.1 with SMTP id a1csp000001abc; Sat, 26 Sep 2015
+ 13:02:49 -0700 (PDT)
+X-Received: by 10.0.0.2 with SMTP id b2mr000002pbc.10.1443297769000;
+ Sat, 26 Sep 2015 13:02:49 -0700 (PDT)
+Return-Path: <[email protected]>
+Received: from mail.example.com (mail.example.com. [10.0.0.3]) by
+ mx.example.net with ESMTP id c3si000003abc.10.2015.09.26.13.02.48 for
+ <[email protected]>; Sat, 26 Sep 2015 13:02:49 -0700 (PDT)
+Received-SPF: pass (example.net: domain of [email protected]
+ designates 10.0.0.3 as permitted sender) client-ip=10.0.0.3;
+Authentication-Results: mx.example.net; spf=pass (example.net: domain of
+ [email protected] designates 10.0.0.3 as permitted sender)
+ [email protected]; dkim=pass [email protected]
+DKIM-Signature: v=1; a=rsa-sha256; c=simple; d=example.com; s=selector;
+ t=1443297733; x=1443902533; q=dns/txt; h=From:To:
+ Subject:Date:MIME-Version:Content-Type:Reply-To:Message-ID; bh=
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=; b=BBBBBBBBBBBBBBBBBB
+ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+ BBBBBBBBBBBBBBBBBBBBBBBBBBBB=
+Received: from relay01 by mail.example.com (ExampleMTA v1.0) with
+ ESMTPA id d4msg000004.msg for <[email protected]>; Sat, 26 Sep 2015
+ 13:02:11 -0700
+X-Spam-Processed: mail.example.com, Sat, 26 Sep 2015 13:02:11 -0700 (not
+ processed: spam filter heuristic analysis disabled)
+X-MTA-Helo: relay01
+X-MTA-Arrival-Date: Sat, 26 Sep 2015 13:02:11 -0700
+X-Authenticated-Sender: [email protected]
+X-Return-Path: [email protected]
+X-Envelope-From: [email protected]
+X-MTA-Deliver-To: [email protected]
+From: Hari Seldon <[email protected]>
+To: "Venabili, Dors" <[email protected]>
+Subject: Set the Foundation Straight
+Date: Sat, 26 Sep 2015 09:30:20 -0700
+MIME-Version: 1.0
+X-Mailer: ExampleMailer 0.5.8b
+Content-Type: multipart/alternative;
+ boundary="_=ExampleMailer=_0123456789abcdef"
+Reply-To: Hari Seldon <[email protected]>
+Message-ID: <[email protected]>
+
+
+--_=ExampleMailer=_0123456789abcdef
+Content-Transfer-Encoding: QUOTED-PRINTABLE
+Content-Type: TEXT/PLAIN;
+       charset=utf-8
+
+Dear Dors Venabili,
+
+The plan for the Foundation is attached in this message=E2=80=99s HTML part.
+
+Best regards,
+Hari Seldon
+
+--_=ExampleMailer=_0123456789abcdef
+Content-Transfer-Encoding: QUOTED-PRINTABLE
+Content-Type: TEXT/HTML;
+       charset=utf-8
+
+<html><head><title>Set the Foundation Straight</title></head>
+<body><font face=3D"Arial" size=3D"2">
+Dear Dors Venabili,<br><br>
+The plan for the Foundation is in this message=E2=80=99s HTML part.<br><br>
+Best regards,<br>Hari Seldon<br>
+</font></body></html>
+
+--_=ExampleMailer=_0123456789abcdef--
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
+<plist version="1.0">
+<dict>
+       <key>conversation-id</key>
+       <integer>900001</integer>
+       <key>date-last-viewed</key>
+       <integer>0</integer>
+       <key>date-received</key>
+       <integer>1443297769</integer>
+       <key>flags</key>
+       <integer>25803619329</integer>
+       <key>remote-id</key>
+       <string>90002</string>
+</dict>
+</plist>
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/resources/test-documents/testEMLX_single_part_html.emlx
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/resources/test-documents/testEMLX_single_part_html.emlx
new file mode 100644
index 0000000000..2cd779cf58
--- /dev/null
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/test/resources/test-documents/testEMLX_single_part_html.emlx
@@ -0,0 +1,24 @@
+446       
+Subject: Trial balance
+Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.7\))
+Content-Type: text/html;
+       charset=utf-8
+Message-Id: <[email protected]>
+Date: Fri, 27 Oct 2023 10:03:30 +0200
+To: [email protected]
+Content-Transfer-Encoding: 7bit
+From: Hari Seldon <[email protected]>
+
+<html><head></head><body dir="auto" style="word-wrap: break-word;">The trial 
balance is ready for review.</body></html>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
+<plist version="1.0">
+<dict>
+       <key>date-last-viewed</key>
+       <integer>1698393810</integer>
+       <key>date-received</key>
+       <integer>1698393810</integer>
+       <key>flags</key>
+       <integer>8623685697</integer>
+</dict>
+</plist>

Reply via email to