Repository: Unstructured-IO/unstructured (language: python)

Issue:
bug/partition_msg halts for attachmentes with UNK type

Currently, the `attachment_partitioner` is hardcoded to `partition` in the following file:

https://github.com/Unstructured-IO/unstructured/blob/50d75c47d346413de8a6dbbcf72009871f7ecd56/unstructured/partition/msg.py#L259-L277

However, according to the [official documentation](https://docs.unstructured.io/open-source/core-functionality/partitioning#partition-msg), the `partition-msg` function accepts `attachment_partitioner` as an argument.


Discussion / hints:
#3605 PR (Draft)
@S1M0N38 that was removed on purpose. @Paul-Cornell can you remove that parameter from the docs for us?
When a .msg file contains an attachment of an unsupported type (UNK), the partition_msg function halts. I've implemented a custom attachment_partitioner to filter out unsupported types.

Is there another way to process the supported types and ignore the unsupported ones?

@scanny I'm not quite sure how to "remove" that parameter from the docs. Searching for `attachment_partitioner` across the docs returns four results, some in text, and some in code. I don't have enough context to know exactly what needs to be removed here. Could you please either advise, or create a PR in the docs repo? Thanks!
@S1M0N38 Ahh, okay, so that's a bug then. You shouldn't have to provide a custom partitioner for that :)

Shall we make this into a bug report for that or do you want to open a new one?

The correct behavior would be for `partition_msg()` to simply skip any attachments it doesn't know how to partition.
@Paul-Cornell it looks like the text is about the same for `partition_email()` and `partition_msg()` on that page:

---

> You can optionally partition e-mail attachments by setting process_attachments=True. If you set process_attachments=True, you’ll also need to pass in a partitioning function to attachment_partitioner. The following is an example of what the workflow looks like:
```python
from unstructured.partition.auto import partition
from unstructured.partition.email import partition_email

filename = "example-docs/eml/fake-email-attachment.eml"
elements = partition_email(
  filename=filename, process_attachments=True, attachment_partitioner=partition
)
```

---

You can change it like this in each case:

> You can optionally partition e-mail attachments by setting process_attachments=True. The following is an example of what the workflow looks like:
```python
from unstructured.partition.email import partition_email

filename = "example-docs/eml/fake-email-attachment.eml"
elements = partition_email(filename=filename, process_attachments=True)
```

So:
- get rid of the middle sentence
- remove the import of `partition`
- remove the `attachment_partitioner=partition` argument in the `partition_email()` call.
> @S1M0N38 Ahh, okay, so that's a bug then. You shouldn't have to provide a custom partitioner for that :)
> 
> Shall we make this into a bug report for that or do you want to open a new one?
> 
> The correct behavior would be for `partition_msg()` to simply skip any attachments it doesn't know how to partition.

let's make this issue into a bug report and modify the title accordingly. 

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 68ccf02a16..46862fbdfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 0.16.1-dev0
+
+### Enhancements
+
+### Features
+
+### Fixes
+
+* **Rewrite of `partition.email` module and tests.** Use modern Python stdlib `email` module interface to parse email messages and attachments. This change shortens and simplifies the code, and makes it more robust and maintainable. Several historical problems were remedied in the process.
+
 ## 0.16.0
 
 ### Enhancements
diff --git a/example-docs/eml/empty.eml b/example-docs/eml/empty.eml
new file mode 100644
index 0000000000..60aa8799ba
--- /dev/null
+++ b/example-docs/eml/empty.eml
@@ -0,0 +1,3 @@
+      
+
+    
diff --git a/example-docs/eml/mime-attach-mp3.eml b/example-docs/eml/mime-attach-mp3.eml
new file mode 100644
index 0000000000..35495746cb
--- /dev/null
+++ b/example-docs/eml/mime-attach-mp3.eml
@@ -0,0 +1,934 @@
+From: sender@example.com
+To: recipient@example.com
+Subject: Email with MP3 Attachment
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="===============6149310949458043093=="
+
+--===============6149310949458043093==
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 7bit
+
+This is an email with an MP3 attachment.
+
+--===============6149310949458043093==
+Content-Type: audio/mpeg
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename="sample-3s.mp3"
+MIME-Version: 1.0
+
+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
+K5iJxNSZIYVnD3h1EXNyePjKmReWtjQjh/NDKNApDtJUqH1EHSSdGlWSMtEytMxWRhqOhEmpsdqM
+iaRNUdZYoJOpbJFU6XzyzAtlI+fM0UVo1PWiipI3OrOHGQmamXRWQpDFDtOImxuWLLl5ZeXMqVFF
+lJJIomy5z///88dmf/51akxBTUUzLjEwMKqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+qv/7kmTsAAZ2bVAtamAAAAANIKAAARvV2UrZmQAAAAA0gwAAAKqqqqqqqqqqqqqqqqqqqqqqqqqq
+qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+qqqqqqqqqqqqqqqqqgCSMqgCgFHWAlKiqDVUciSYu40uXULCx0rRQtTNcqtfcqKqMBsAsaMFhYWs
+kFILbDkFoe0zat8M1//rXDcMzeq+qrWzbNfWzVs3yq8ip0RP5U7/Khsqdg0oO/iLlTpUFVA04Gjw
+lDYK1UxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVX/+5BkdY/zQTxClzEAAAAADSDgAAEAAAGkAAAAIAAANIAAAARV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=
+
+--===============6149310949458043093==--
diff --git a/example-docs/eml/mime-different-plain-html.eml b/example-docs/eml/mime-different-plain-html.eml
new file mode 100644
index 0000000000..625de87f2c
--- /dev/null
+++ b/example-docs/eml/mime-different-plain-html.eml
@@ -0,0 +1,34 @@
+From: sender@example.com
+To: recipient@example.com
+Date: Tue, 01 Oct 2024 12:34:56 -0500
+Subject: Example MIME Email
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="boundary123"
+
+--boundary123
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: 7bit
+
+This is the text/plain part.
+
+Did you know that the first email was sent by Ray Tomlinson in 1971? He used the "@" symbol to separate the user's name from the computer name, a practice that is still in use today.
+
+Another interesting fact is that the first known instance of email spam occurred in 1978. A marketing message was sent to 393 recipients on ARPANET, marking the beginning of what we now know as email spam.
+
+--boundary123
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: 7bit
+
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Example MIME Email</title>
+</head>
+<body>
+    <p>This is the <code>text/html</code> part.</p>
+    <p>Did you know that the first <b>networked email</b> was sent by Ray Tomlinson in 1971? He used the "@" symbol to separate the user's name from the computer name, a practice that is still in use today.</p>
+    <p>Another interesting fact is that the first known instance of <i>email spam</i> occurred in 1978. A marketing message was sent to 393 recipients on ARPANET, marking the beginning of what we now know as email spam.</p>
+</body>
+</html>
+
+--boundary123--
diff --git a/example-docs/eml/mime-html-only.eml b/example-docs/eml/mime-html-only.eml
new file mode 100644
index 0000000000..608770100e
--- /dev/null
+++ b/example-docs/eml/mime-html-only.eml
@@ -0,0 +1,14 @@
+MIME-Version: 1.0
+From: sender@example.com
+To: recipient@example.com
+Date: Tue, 01 Oct 2024 12:34:56 -0500
+Subject: Example HTML Only MIME Email
+Content-Type: text/html; charset="ISO-8859-1"
+Content-Transfer-Encoding: base64
+
+PHA+VGhpcyBpcyBhIHRleHQvaHRtbCBwYXJ0LjwvcD4KPGRpdiBpZD0iY29udGVudCI+PHA+VGhl
+IGZpcnN0IGVtb3RpY29uLCA6KSAsIHdhcyBwcm9wb3NlZCBieSBTY290dCBGYWhsbWFuIGluIDE5
+ODIgdG8gaW5kaWNhdGUganVzdCBvciBzYXJjYXNtIGluIHRleHQgZW1haWxzLjwvcD4KPHA+R21h
+aWwgd2FzIGxhdW5jaGVkIGJ5IEdvb2dsZSBpbiAyMDA0IHdpdGggMSBHQiBvZiBmcmVlIHN0b3Jh
+Z2UsIHNpZ25pZmljYW50bHkgbW9yZSB0aGFuIHdoYXQgb3RoZXIgc2VydmljZXMgb2ZmZXJlZCBh
+dCB0aGUgdGltZS48L3A+PC9kaXY+
diff --git a/example-docs/eml/mime-multi-to-cc-bcc.eml b/example-docs/eml/mime-multi-to-cc-bcc.eml
new file mode 100644
index 0000000000..1913659e20
--- /dev/null
+++ b/example-docs/eml/mime-multi-to-cc-bcc.eml
@@ -0,0 +1,10 @@
+From: sender@example.com
+To: Bob <bob@example.com>, Sue <sue@example.com>
+Cc: Tom <tom@example.com>, Alice <alice@example.com>
+Bcc: John <john@example.com>, Mary <mary@example.com>
+Subject: Example Plain-Text MIME Message
+Message-ID: <2143658709@example.com>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="UTF-8"
+
+This is a plain-text message.
diff --git a/example-docs/eml/mime-multipart-digest.eml b/example-docs/eml/mime-multipart-digest.eml
new file mode 100644
index 0000000000..c68aa369a2
--- /dev/null
+++ b/example-docs/eml/mime-multipart-digest.eml
@@ -0,0 +1,37 @@
+From: alice@example.com
+To: bob@example.com
+Cc: carol@example.com
+Bcc: dave@example.com
+Subject: Example Multipart Digest Email
+Message-ID: <1234567890@example.com>
+MIME-Version: 1.0
+Content-Type: multipart/digest; boundary="boundary123"
+
+--boundary123
+Content-Type: message/rfc822
+
+From: eve@example.com
+To: alice@example.com
+Subject: First Message
+
+This is the first message in the digest.
+
+--boundary123
+Content-Type: message/rfc822
+
+From: frank@example.com
+To: bob@example.com
+Subject: Second Message
+
+This is the second message in the digest.
+
+--boundary123
+Content-Type: message/rfc822
+
+From: grace@example.com
+To: carol@example.com
+Subject: Third Message
+
+This is the third message in the digest.
+
+--boundary123--
diff --git a/example-docs/eml/mime-no-body.eml b/example-docs/eml/mime-no-body.eml
new file mode 100644
index 0000000000..c4366ed6cb
--- /dev/null
+++ b/example-docs/eml/mime-no-body.eml
@@ -0,0 +1,22 @@
+From: sender@example.com
+To: recipient@example.com
+Date: Tue, 01 Oct 2024 12:34:56 -0500
+Subject: Image Only Email
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="boundary123"
+
+--boundary123
+Content-Type: image/jpeg
+Content-Disposition: attachment; filename="image.jpg"
+Content-Transfer-Encoding: base64
+
+/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxISEBAQEhISEBAWFRUVFhUVFRUWFRUWFhUWFhUV
+FRUYHSggGBolGxUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGhAQGi0fHx8rLS0rLS0rLS0t
+LS0rLS0rLS0rLS0rLS0rLS0rLS0rLS0rLS0tLS0rLS0rLS0rLS0rLf/AABEIAMgAyAMBIgACEQED
+EQH/xAAbAAEAAgMBAQAAAAAAAAAAAAAABAUCAwYBB//EAD0QAAIBAwMBBgQEBgIDCQAAAAECAwAE
+ERIhBTFBBhMiUWFxgZEykaGxFCNCUrHB0fAUM2JygpLwFySTwsL/xAAYAQEBAQEBAAAAAAAAAAAA
+AAAABQEDBP/EAB8RAQEBAQEBAQEBAQEAAAAAAAABEQIhEjEEQVFhcf/aAAwDAQACEQMRAD8A+6qK
+CiiggqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgq
+CiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCooIKgqCiiCo
+[Base64 encoded image data continues]
+--boundary123--
diff --git a/example-docs/eml/mime-no-subject.eml b/example-docs/eml/mime-no-subject.eml
new file mode 100644
index 0000000000..ee06ec5e38
--- /dev/null
+++ b/example-docs/eml/mime-no-subject.eml
@@ -0,0 +1,6 @@
+From: sender@example.com
+To: recipient@example.com
+MIME-Version: 1.0
+Content-Type: text/plain; charset="UTF-8"
+
+This is a simple email message without a subject.
diff --git a/example-docs/eml/mime-no-to.eml b/example-docs/eml/mime-no-to.eml
new file mode 100644
index 0000000000..d741d7f95d
--- /dev/null
+++ b/example-docs/eml/mime-no-to.eml
@@ -0,0 +1,8 @@
+From: sender@example.com
+Cc: Tom <tom@example.com>, Alice <alice@example.com>
+Bcc: John <john@example.com>, Mary <mary@example.com>
+Subject: Example Plain-Text MIME Message
+MIME-Version: 1.0
+Content-Type: text/plain; charset="UTF-8"
+
+This is a plain-text message.
diff --git a/example-docs/eml/mime-simple.eml b/example-docs/eml/mime-simple.eml
new file mode 100644
index 0000000000..e789b9fe38
--- /dev/null
+++ b/example-docs/eml/mime-simple.eml
@@ -0,0 +1,22 @@
+From: sender@example.com
+To: recipient@example.com
+Subject: Example Multipart/Alternative Email
+Message-ID: <1234567890@example.com>
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="boundary123"
+
+--boundary123
+Content-Type: text/plain; charset="UTF-8"
+
+This is a simple email message.
+
+--boundary123
+Content-Type: text/html; charset="UTF-8"
+
+<html>
+  <body>
+    <p>This is a simple email message.</p>
+  </body>
+</html>
+
+--boundary123--
diff --git a/example-docs/eml/mime-word-encoded-subject.eml b/example-docs/eml/mime-word-encoded-subject.eml
new file mode 100644
index 0000000000..a250826c00
--- /dev/null
+++ b/example-docs/eml/mime-word-encoded-subject.eml
@@ -0,0 +1,7 @@
+From: sender@example.com
+To: recipient@example.com
+Subject: =?UTF-8?B?U2ltcGxlIGVtYWlsIHdpdGgg4pi44pi/IFVuaWNvZGUgc3ViamVjdA==?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset="UTF-8"
+
+This is a simple email message with Unicode characters in the subject.
diff --git a/example-docs/eml/rfc822-no-date.eml b/example-docs/eml/rfc822-no-date.eml
new file mode 100644
index 0000000000..d8e2a9f8ab
--- /dev/null
+++ b/example-docs/eml/rfc822-no-date.eml
@@ -0,0 +1,5 @@
+From: sender@example.com
+To: recipient@example.com
+Subject: Example Email Without Date Header
+
+This is an example email message without a Date header. Note that this is non-standard and may be flagged or corrected by email servers.
diff --git a/example-docs/eml/simple-rfc-822.eml b/example-docs/eml/simple-rfc-822.eml
new file mode 100644
index 0000000000..ec103d2a84
--- /dev/null
+++ b/example-docs/eml/simple-rfc-822.eml
@@ -0,0 +1,10 @@
+From: sender@example.com
+To: recipient@example.com
+Date: Tue, 01 Oct 2024 12:34:56 -0500
+Subject: Example RFC 822 Email
+
+This is an RFC 822 email message.
+
+An RFC 822 message is characterized by its simple, text-based format, which includes a header and a body. The header contains structured fields such as "From", "To", "Date", and "Subject", each followed by a colon and the corresponding information. The body follows the header, separated by a blank line, and contains the main content of the email.
+
+The structure ensures compatibility and readability across different email systems and clients, adhering to the standards set by the Internet Engineering Task Force (IETF).
diff --git a/unstructured/__version__.py b/unstructured/__version__.py
index 65162b438a..d0af649106 100644
--- a/unstructured/__version__.py
+++ b/unstructured/__version__.py
@@ -1,1 +1,1 @@
-__version__ = "0.16.0"  # pragma: no cover
+__version__ = "0.16.1-dev0"  # pragma: no cover
diff --git a/unstructured/documents/email_elements.py b/unstructured/documents/email_elements.py
deleted file mode 100644
index e38bbe435f..0000000000
--- a/unstructured/documents/email_elements.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC
-from datetime import datetime
-from typing import Callable, Optional
-
-from unstructured.documents.elements import Text
-
-
-class NoDatestamp(ABC):
-    """Class to indicate that an element do not have a datetime stamp."""
-
-
-class EmailElement(Text):
-    """An email element is a section of the email."""
-
-
-class Name(EmailElement):
-    """Base element for capturing free text from within document."""
-
-    category = "Uncategorized"
-
-    def __init__(
-        self,
-        name: str,
-        text: str,
-        datestamp: datetime | NoDatestamp = NoDatestamp(),
-        element_id: Optional[str] = None,
-    ):
-        self.name: str = name
-
-        super().__init__(text=text, element_id=element_id)
-
-        if isinstance(datestamp, datetime):
-            self.datestamp: datetime = datestamp
-
-    def has_datestamp(self):
-        return "self.datestamp" in globals()
-
-    def __str__(self):
-        return f"{self.name}: {self.text}"
-
-    def __eq__(self, other) -> bool:
-        if self.has_datestamp():
-            return (
-                self.name == other.name
-                and self.text == other.text
-                and self.datestamp == other.datestamp
-            )
-        return self.name == other.name and self.text == other.text
-
-    def apply(self, *cleaners: Callable):
-        """Applies a cleaning brick to the text element. The function that's passed in
-        should take a string as input and produce a string as output."""
-        cleaned_text = self.text
-        cleaned_name = self.name
-
-        for cleaner in cleaners:
-            cleaned_text = cleaner(cleaned_text)
-            cleaned_name = cleaner(cleaned_name)
-
-        if not isinstance(cleaned_text, str) or not isinstance(cleaned_name, str):
-            raise ValueError("Cleaner produced a non-string output.")
-
-        self.text = cleaned_text
-        self.name = cleaned_name
-
-
-class BodyText(list[Text]):
-    """BodyText is an element consisting of multiple, well-formulated sentences. This
-    excludes elements such titles, headers, footers, and captions. It is the body of an email."""
-
-    category = "BodyText"
-
-
-class Recipient(Name):
-    """A text element for capturing the recipient information of an email"""
-
-    category = "Recipient"
-
-
-class Sender(Name):
-    """A text element for capturing the sender information of an email"""
-
-    category = "Sender"
-
-
-class Subject(EmailElement):
-    """A text element for capturing the subject information of an email"""
-
-    category = "Subject"
-
-
-class MetaData(Name):
-    """A text element for capturing header meta data of an email
-    (miscellaneous data in the email)."""
-
-    category = "MetaData"
-
-
-class ReceivedInfo(Name):
-    """A text element for capturing header information of an email (e.g. IP addresses, etc)."""
-
-    category = "ReceivedInfo"
-
-
-class Attachment(Name):
-    """A text element for capturing the attachment name in an email (e.g. documents,
-    images, etc)."""
-
-    category = "Attachment"
diff --git a/unstructured/partition/auto.py b/unstructured/partition/auto.py
index b5e95f2e85..7f3bb5e5b3 100644
--- a/unstructured/partition/auto.py
+++ b/unstructured/partition/auto.py
@@ -13,6 +13,7 @@
 from unstructured.file_utils.filetype import detect_filetype, is_json_processable
 from unstructured.file_utils.model import FileType
 from unstructured.logger import logger
+from unstructured.partition.common import UnsupportedFileFormatError
 from unstructured.partition.common.common import exactly_one
 from unstructured.partition.common.lang import check_language_args
 from unstructured.partition.utils.constants import PartitionStrategy
@@ -442,7 +443,9 @@ def partition(
         elements = []
     else:
         msg = "Invalid file" if not filename else f"Invalid file {filename}"
-        raise ValueError(f"{msg}. The {file_type} file type is not supported in partition.")
+        raise UnsupportedFileFormatError(
+            f"{msg}. The {file_type} file type is not supported in partition."
+        )
 
     for element in elements:
         element.metadata.url = url
diff --git a/unstructured/partition/common/__init__.py b/unstructured/partition/common/__init__.py
index e69de29bb2..04e20f9ef2 100644
--- a/unstructured/partition/common/__init__.py
+++ b/unstructured/partition/common/__init__.py
@@ -0,0 +1,6 @@
+class UnsupportedFileFormatError(Exception):
+    """File-type is not supported for this operation.
+
+    For example, when receiving a file for auto-partitioning where its file-formatt cannot be
+    identified or there is no partitioner available for that file-format.
+    """
diff --git a/unstructured/partition/email.py b/unstructured/partition/email.py
index 787387c5e6..d194e22d21 100644
--- a/unstructured/partition/email.py
+++ b/unstructured/partition/email.py
@@ -1,510 +1,429 @@
+"""Provides `partition_email()` function.
+
+Suitable for use with `.eml` files, which can be exported from many email clients.
+"""
+
 from __future__ import annotations
 
-import datetime
+import datetime as dt
 import email
+import email.policy
+import email.utils
+import io
 import os
-import re
-from email import policy
-from email.headerregistry import AddressHeader
-from email.message import EmailMessage
-from functools import partial
-from tempfile import TemporaryDirectory
-from typing import IO, Any, Callable, Final, Type, cast
-
-from unstructured.cleaners.core import clean_extra_whitespace, replace_mime_encodings
-from unstructured.cleaners.extract import (
-    extract_datetimetz,
-    extract_ip_address,
-    extract_ip_address_name,
-    extract_mapi_id,
-)
-from unstructured.documents.elements import (
-    Element,
-    ElementMetadata,
-    Image,
-    NarrativeText,
-    Text,
-    Title,
-)
-from unstructured.documents.email_elements import (
-    MetaData,
-    ReceivedInfo,
-    Recipient,
-    Sender,
-    Subject,
-)
-from unstructured.file_utils.encoding import (
-    COMMON_ENCODINGS,
-    format_encoding_str,
-    read_txt_file,
-    validate_encoding,
-)
+from email.message import EmailMessage, MIMEPart
+from typing import IO, Any, Final, Iterator, cast
+
+from unstructured.documents.elements import Element, ElementMetadata
 from unstructured.file_utils.model import FileType
-from unstructured.logger import logger
-from unstructured.nlp.patterns import EMAIL_DATETIMETZ_PATTERN_RE
-from unstructured.partition.common.common import convert_to_bytes, exactly_one
+from unstructured.partition.common import UnsupportedFileFormatError
 from unstructured.partition.common.metadata import get_last_modified_date
 from unstructured.partition.html import partition_html
 from unstructured.partition.text import partition_text
+from unstructured.utils import lazyproperty
 
-VALID_CONTENT_SOURCES: Final[list[str]] = ["text/html", "text/plain"]
-DETECTION_ORIGIN: str = "email"
+VALID_CONTENT_SOURCES: Final[tuple[str, ...]] = ("text/html", "text/plain")
 
 
 def partition_email(
     filename: str | None = None,
     *,
     file: IO[bytes] | None = None,
-    encoding: str | None = None,
-    text: str | None = None,
     content_source: str = "text/html",
-    include_headers: bool = False,
     metadata_filename: str | None = None,
     metadata_last_modified: str | None = None,
-    process_attachments: bool = False,
-    attachment_partitioner: Callable[..., list[Element]] | None = None,
+    process_attachments: bool = True,
     **kwargs: Any,
 ) -> list[Element]:
-    """Partitions an .eml documents into its constituent elements.
-
-    Parameters
-    ----------
-    filename
-        A string defining the target filename path.
-    file
-        A file-like object using "r" mode --> open(filename, "r").
-    encoding
-        The encoding method used to decode the input bytes when drawn from `filename` or `file`.
-        Defaults to "utf-8".
-    text
-        The string representation of the .eml document.
-    content_source
-        default: "text/html"
-        other: "text/plain"
-    metadata_filename
-        The filename to use for the metadata.
-    metadata_last_modified
-        The last modified date for the document.
-    process_attachments
-        If True, partition_email will process email attachments in addition to
-        processing the content of the email itself.
-    attachment_partitioner
-        The partitioning function to use to process attachments.
+    """Partitions an .eml file into document elements.
+
+    Args:
+        filename: str path of the target file.
+        file: A file-like object open for reading bytes (not str) e.g. --> open(filename, "rb").
+        content_source: The preferred message body. Many emails contain both a plain-text and an
+            HTML version of the message body. By default, the HTML version will be used when
+            available. Specifying "text/plain" will cause the plain-text version to be preferred.
+            When the preferred version is not available, the other version will be used.
+        metadata_filename: The file-path to use for metadata purposes. Useful when the target file
+            is specified as a file-like object or when `filename` is a temporary file and the
+            original file-path is known or a more meaningful file-path is desired.
+        metadata_last_modified: The last-modified timestamp to be applied in metadata. Useful when
+            a file-like object (which can have no last-modified date) target is used. The
+            last-modified metadata is otherwise drawn from the filesystem when a path is provided.
+        process_attachments: When True, also partition any attachments in the message after
+            partitioning the message body. All document elements appear in the single returned
+            element list. The filename of the attachment, when available, is used as the
+            `filename` metadata value for elements arising from the attachment.
+
+    Note that all global keyword arguments such as `unique_element_ids`, `language` and
+    `chunking_strategy` can be used and will be passed along to the decorators that implement
+    those functions. Further, any keyword arguments applicable to HTML will be passed along to the
+    HTML partitioner when processing an HTML message body.
     """
-    if content_source not in VALID_CONTENT_SOURCES:
-        raise ValueError(
-            f"{content_source} is not a valid value for content_source. "
-            f"Valid content sources are: {VALID_CONTENT_SOURCES}",
+    ctx = EmailPartitioningContext.load(
+        file_path=filename,
+        file=file,
+        content_source=content_source,
+        metadata_file_path=metadata_filename,
+        metadata_last_modified=metadata_last_modified,
+        process_attachments=process_attachments,
+        kwargs=kwargs,
+    )
+
+    return list(_EmailPartitioner.iter_elements(ctx=ctx))
+
+
+class EmailPartitioningContext:
+    """Encapsulates partitioning option validation, computation, and application of defaults."""
+
+    def __init__(
+        self,
+        file_path: str | None = None,
+        file: IO[bytes] | None = None,
+        content_source: str = "text/html",
+        metadata_file_path: str | None = None,
+        metadata_last_modified: str | None = None,
+        process_attachments: bool = False,
+        kwargs: dict[str, Any] = {},
+    ):
+        self._file_path = file_path
+        self._file = file
+        self._content_source = content_source
+        self._metadata_file_path = metadata_file_path
+        self._metadata_last_modified = metadata_last_modified
+        self._process_attachments = process_attachments
+        self._kwargs = kwargs
+
+    @classmethod
+    def load(
+        cls,
+        file_path: str | None,
+        file: IO[bytes] | None,
+        content_source: str,
+        metadata_file_path: str | None,
+        metadata_last_modified: str | None,
+        process_attachments: bool,
+        kwargs: dict[str, Any],
+    ) -> EmailPartitioningContext:
+        """Construct and validate an instance."""
+        return cls(
+            file_path=file_path,
+            file=file,
+            content_source=content_source,
+            metadata_file_path=metadata_file_path,
+            metadata_last_modified=metadata_last_modified,
+            process_attachments=process_attachments,
+            kwargs=kwargs,
+        )._validate()
+
+    @lazyproperty
+    def bcc_addresses(self) -> list[str] | None:
+        """The "blind carbon-copy" Bcc: addresses of the message."""
+        bccs = self.msg.get_all("Bcc")
+        if not bccs:
+            return None
+        addrs = email.utils.getaddresses(bccs)
+        return [email.utils.formataddr(addr) for addr in addrs]
+
+    @lazyproperty
+    def body_part(self) -> MIMEPart | None:
+        """The message part containing the actual textual email message.
+
+        This is as opposed to attachments or "related" parts like an image that appears in the
+        message etc.
+        """
+        return self.msg.get_body(preferencelist=self.content_type_preference)
+
+    @lazyproperty
+    def cc_addresses(self) -> list[str] | None:
+        """The "carbon-copy" Cc: addresses of the message."""
+        ccs = self.msg.get_all("Cc")
+        if not ccs:
+            return None
+        addrs = email.utils.getaddresses(ccs)
+        return [email.utils.formataddr(addr) for addr in addrs]
+
+    @lazyproperty
+    def content_type_preference(self) -> tuple[str, ...]:
+        """Whether to prefer HTML or plain-text body when message-body has both.
+
+        The default order of preference is `("html", "plain")`. The order can be switched by
+        specifying `"text/plain"` as the `content_source` arg value.
+        """
+        return ("plain", "html") if self._content_source == "text/plain" else ("html", "plain")
+
+    @lazyproperty
+    def email_metadata(self) -> ElementMetadata:
+        """The email-specific metadata fields for this message.
+
+        Suitable for use with `.metadata.update()` on the base metadata applied to message body
+        elements by delegate partitioners for text and HTML.
+        """
+        return ElementMetadata(
+            bcc_recipient=self.bcc_addresses,
+            cc_recipient=self.cc_addresses,
+            email_message_id=self.message_id,
+            sent_from=[self.from_address] if self.from_address else None,
+            sent_to=self.to_addresses,
+            subject=self.subject,
         )
 
-    if text is not None and text.strip() == "" and not file and not filename:
-        return []
+    @lazyproperty
+    def from_address(self) -> str | None:
+        """The address of the message sender."""
+        froms = self.msg.get_all("From")
+        if not froms:
+            # -- this should never occur because the From: header is mandatory per RFC 5322 --
+            return None
+        addrs = email.utils.getaddresses(froms)
+        formatted_addrs = [email.utils.formataddr(addr) for addr in addrs]
+        return formatted_addrs[0]
+
+    @lazyproperty
+    def message_id(self) -> str | None:
+        """The value of the Message-ID: header, when present."""
+        raw_id = self.msg.get("Message-ID")
+        if not raw_id:
+            return None
+        return raw_id.strip().strip("<>")
+
+    @lazyproperty
+    def metadata_file_path(self) -> str | None:
+        """The best available file-path information for this email message.
+
+        It's value is computed according to these rules, applied in order:
+
+          - The `metadata_filename` arg value when one was provided to `partition_email()`.
+          - The `file_path` value when one was provided.
+          - None otherwise.
+
+        This value is used as the `filename` metadata value for elements produced by partitioning
+        the email message (but not those from its attachments).
+        """
+        return self._metadata_file_path or self._file_path or None
+
+    @lazyproperty
+    def metadata_last_modified(self) -> str | None:
+        """The best available last-modified date for this message, as an ISO8601 string.
+
+        It's value is computed according to these rules, applied in order:
+
+          - The `metadata_last_modified` arg value when one was provided to `partition_email()`.
+          - The date-time in the `Sent:` header of the message, when present.
+          - The last-modified date recorded on the filesystem for `file_path` when it was provided.
+          - None otherwise.
+
+        This value is used as the `last_modified` metadata value for all elements produced by
+        partitioning this email message, including any attachments.
+        """
+        return self._metadata_last_modified or self._sent_date or self._filesystem_last_modified
+
+    @lazyproperty
+    def msg(self) -> EmailMessage:
+        """The Python stdlib `email.message.EmailMessage` object parsed from the EML file."""
+        if self._file_path is not None:
+            with open(self._file_path, "rb") as f:
+                return cast(
+                    EmailMessage, email.message_from_binary_file(f, policy=email.policy.default)
+                )
 
-    # Verify that only one of the arguments was provided
-    exactly_one(filename=filename, file=file, text=text)
-    detected_encoding = "utf-8"
-    if filename is not None:
-        extracted_encoding, msg = _parse_email(filename=filename)
-        if extracted_encoding:
-            detected_encoding = extracted_encoding
-        else:
-            detected_encoding, file_text = read_txt_file(
-                filename=filename,
-                encoding=encoding,
+        assert self._file is not None
+
+        file_bytes = self._file.read()
+
+        return cast(EmailMessage, email.message_from_bytes(file_bytes, policy=email.policy.default))
+
+    @lazyproperty
+    def partitioning_kwargs(self) -> dict[str, Any]:
+        """The "extra" keyword arguments received by `partition_email()`.
+
+        These are passed along to delegate partitioners which extract keyword args like
+        `chunking_strategy` etc. in their decorators to control metadata behaviors, etc.
+        """
+        return self._kwargs
+
+    @lazyproperty
+    def process_attachments(self) -> bool:
+        """When True, partition attachments in addition to the email message body.
+
+        Any attachment having file-format that cannot be partitioned by unstructured is silently
+        skipped.
+        """
+        return self._process_attachments
+
+    @lazyproperty
+    def subject(self) -> str | None:
+        """The value of the Subject: header, when present."""
+        subject = self.msg.get("Subject")
+        if not subject:
+            return None
+        return subject
+
+    @lazyproperty
+    def to_addresses(self) -> list[str] | None:
+        """The To: addresses of the message."""
+        tos = self.msg.get_all("To")
+        if not tos:
+            return None
+        addrs = email.utils.getaddresses(tos)
+        return [email.utils.formataddr(addr) for addr in addrs]
+
+    @lazyproperty
+    def _filesystem_last_modified(self) -> str | None:
+        """Last-modified retrieved from filesystem when a file-path was provided, None otherwise."""
+        return get_last_modified_date(self._file_path) if self._file_path else None
+
+    @lazyproperty
+    def _sent_date(self) -> str | None:
+        """ISO-8601 str representation of message sent-date, if available."""
+        date_str = self.msg.get("Date")
+        if not date_str:
+            return None
+        sent_date = email.utils.parsedate_to_datetime(date_str)
+        return sent_date.astimezone(dt.timezone.utc).isoformat(timespec="seconds")
+
+    def _validate(self) -> EmailPartitioningContext:
+        """Raise on first invalid option, return self otherwise."""
+        if not self._file_path and not self._file:
+            raise ValueError(
+                "no document specified; either a `filename` or `file` argument must be provided."
             )
-            msg = email.message_from_string(file_text, policy=policy.default)
-    elif file is not None:
-        extracted_encoding, msg = _parse_email(file=file)
-        if extracted_encoding:
-            detected_encoding = extracted_encoding
-        else:
-            detected_encoding, file_text = read_txt_file(file=file, encoding=encoding)
-            msg = email.message_from_string(file_text, policy=policy.default)
-    elif text is not None:
-        _text: str = str(text)
-        msg = email.message_from_string(_text, policy=policy.default)
-    else:
-        return []
-    if not encoding:
-        encoding = detected_encoding
-    msg = cast(EmailMessage, msg)
-
-    is_encrypted = False
-    content_map: dict[str, str] = {}
-    for part in msg.walk():
-        # NOTE(robinson) - content dispostiion is None for the content of the email itself.
-        # Other dispositions include "attachment" for attachments
-        if part.get_content_disposition() is not None:
-            continue
-        content_type = part.get_content_type()
-
-        # NOTE(robinson) - Per RFC 2015, the content type for emails with PGP encrypted
-        # content is multipart/encrypted
-        # ref: https://www.ietf.org/rfc/rfc2015.txt
-        if content_type.endswith("encrypted"):
-            is_encrypted = True
-
-        # NOTE(andymli) - we can determine if text is base64 encoded via the
-        # content-transfer-encoding property of a part
-        # https://www.w3.org/Protocols/rfc1341/5_Content-Transfer-Encoding.html
-        if (
-            part.get_content_maintype() == "text"
-            and part.get("content-transfer-encoding", None) == "base64"
-        ):
-            try:
-                content_map[content_type] = part.get_payload(decode=True).decode(  # type: ignore
-                    encoding
-                )
-            except (UnicodeDecodeError, UnicodeError):
-                content_map[content_type] = part.get_payload()  # type: ignore
-        else:
-            content_map[content_type] = part.get_payload()  # type: ignore
-
-    content = None
-    if content_source in content_map:
-        content = content_map.get(content_source)
-    # NOTE(robinson) - If the chosen content source is not available and there is
-    # another valid content source, fall back to the other valid source
-    else:
-        for _content_source in VALID_CONTENT_SOURCES:
-            content = content_map.get(_content_source, "")
-            if content:
-                logger.warning(
-                    f"{content_source} was not found. Falling back to {_content_source}."
-                )
-                break
 
-    elements: list[Element] = []
+        if self._file:
+            if not isinstance(  # pyright: ignore[reportUnnecessaryIsInstance]
+                self._file.read(0), bytes
+            ):
+                raise ValueError("file object must be opened in binary mode")
+            self._file.seek(0)
+
+        if self._content_source not in VALID_CONTENT_SOURCES:
+            raise ValueError(
+                f"{repr(self._content_source)} is not a valid value for content_source;"
+                f" must be one of: {VALID_CONTENT_SOURCES}",
+            )
 
-    if is_encrypted:
-        logger.warning(
-            "Encrypted email detected. Partition function will return an empty list.",
-        )
+        return self
 
-    elif not content:
-        pass
-
-    elif content_source == "text/html":
-        # NOTE(robinson) - In the .eml files, the HTML content gets stored in a format that
-        # looks like the following, resulting in extraneous "=" characters in the output if
-        # you don't clean it up
-        # <ul> =
-        #    <li>Item 1</li>=
-        #    <li>Item 2<li>=
-        # </ul>
-
-        content = content.replace("=\n", "").replace("=\r\n", "")
-        elements = partition_html(
-            text=content,
-            metadata_filename=metadata_filename,
-            metadata_file_type=FileType.EML,
-            detection_origin="email",
-            **kwargs,
-        )
-        for element in elements:
-            if isinstance(element, Text):
-                _replace_mime_encodings = partial(
-                    replace_mime_encodings,
-                    encoding=encoding,
-                )
-                try:
-                    element.apply(_replace_mime_encodings)
-                except (UnicodeDecodeError, UnicodeError):
-                    # If decoding fails, try decoding through common encodings
-                    common_encodings: list[str] = []
-                    for x in COMMON_ENCODINGS:
-                        _x = format_encoding_str(x)
-                        if _x != encoding:
-                            common_encodings.append(_x)
-
-                    for enc in common_encodings:
-                        try:
-                            _replace_mime_encodings = partial(
-                                replace_mime_encodings,
-                                encoding=enc,
-                            )
-                            element.apply(_replace_mime_encodings)
-                            break
-                        except (UnicodeDecodeError, UnicodeError):
-                            continue
-    elif content_source == "text/plain":
-        elements = partition_text(
-            text=content,
-            encoding=encoding,
-            metadata_file_type=FileType.EML,
-            detection_origin="email",
-            **kwargs,
-        )
-    else:
-        raise ValueError(
-            f"Invalid content source: {content_source}. "
-            f"Valid content sources are: {VALID_CONTENT_SOURCES}",
-        )
 
-    for idx, element in enumerate(elements):
-        indices = _has_embedded_image(element)
-        if (isinstance(element, (NarrativeText, Title))) and indices:
-            image_info, clean_element = _find_embedded_image(element, indices)
-            elements[idx] = clean_element
-            elements.insert(idx + 1, image_info)
+class _EmailPartitioner:
+    """Encapsulates the partitioning logic for email documents."""
 
-    header: list[Element] = []
-    if include_headers:
-        header = _partition_email_header(msg)
-    all_elements = header + elements
+    def __init__(self, ctx: EmailPartitioningContext):
+        self._ctx = ctx
 
-    last_modified = get_last_modified_date(filename) if filename else None
+    @classmethod
+    def iter_elements(cls, ctx: EmailPartitioningContext) -> Iterator[Element]:
+        """Generate the document elements for the email described by `ctx`."""
+        return cls(ctx=ctx)._iter_elements()
 
-    metadata = _build_email_metadata(
-        msg,
-        filename=metadata_filename or filename,
-        metadata_last_modified=metadata_last_modified,
-        last_modification_date=last_modified,
-    )
-    for element in all_elements:
-        element.metadata.update(metadata)
-
-    if process_attachments:
-        with TemporaryDirectory() as tmpdir:
-            _extract_attachment_info(msg, tmpdir)
-            attached_files = os.listdir(tmpdir)
-            for attached_file in attached_files:
-                attached_filename = os.path.join(tmpdir, attached_file)
-                if attachment_partitioner is None:
-                    raise ValueError(
-                        "Specify the attachment_partitioner kwarg to process attachments.",
-                    )
-                attached_elements = attachment_partitioner(
-                    filename=attached_filename, metadata_last_modified=metadata_last_modified
-                )
-                for element in attached_elements:
-                    element.metadata.filename = attached_file
-                    element.metadata.file_directory = None
-                    element.metadata.attached_to_filename = metadata_filename or filename
-                    all_elements.append(element)
+    def _iter_elements(self) -> Iterator[Element]:
+        """Generate the document elements for the email described in the partitioning context.
 
-    return all_elements
+        This optionally includes elements generated by partitioning any partitionable attachments
+        in the message as well.
+        """
+        for e in self._iter_email_body_elements():
+            e.metadata.update(self._ctx.email_metadata)
+            yield e
 
+        if not self._ctx.process_attachments:
+            return
 
-# ================================================================================================
-# HELPER FUNCTIONS
-# ================================================================================================
+        for attachment in self._ctx.msg.iter_attachments():
+            yield from _AttachmentPartitioner.iter_elements(attachment, self._ctx)
 
+    def _iter_email_body_elements(self) -> Iterator[Element]:
+        """Generate document elements from the email body."""
+        body_part = self._ctx.body_part
 
-def _build_email_metadata(
-    msg: EmailMessage,
-    filename: str | None,
-    metadata_last_modified: str | None = None,
-    last_modification_date: str | None = None,
-) -> ElementMetadata:
-    """Creates an ElementMetadata object from the header information in the email."""
-    signature = _find_signature(msg)
-
-    header_dict = dict(msg.raw_items())
-    email_date = header_dict.get("Date")
-
-    def parse_recipients(header_value: str | None) -> list[str] | None:
-        if header_value is not None:
-            return [recipient.strip() for recipient in header_value.split(",")]
-        return None
-
-    if email_date is not None:
-        email_date = _convert_to_iso_8601(email_date)
-
-    email_message_id = header_dict.get("Message-ID")
-    if email_message_id:
-        email_message_id = _strip_angle_brackets(email_message_id)
-
-    element_metadata = ElementMetadata(
-        bcc_recipient=parse_recipients(header_dict.get("Bcc")),
-        cc_recipient=parse_recipients(header_dict.get("Cc")),
-        email_message_id=email_message_id,
-        sent_to=parse_recipients(header_dict.get("To")),
-        sent_from=parse_recipients(header_dict.get("From")),
-        subject=msg.get("Subject"),
-        signature=signature,
-        last_modified=metadata_last_modified or email_date or last_modification_date,
-        filename=filename,
-    )
-    element_metadata.detection_origin = DETECTION_ORIGIN
-    return element_metadata
+        # -- it's possible to have no body part; that translates to zero elements --
+        if body_part is None:
+            return
 
+        content_type = body_part.get_content_type()
+        content = body_part.get_content()
+        assert isinstance(content, str)
 
-def _convert_to_iso_8601(time: str) -> str | None:
-    """Converts the datetime from the email output to ISO-8601 format."""
-    cleaned_time = clean_extra_whitespace(time)
-    regex_match = EMAIL_DATETIMETZ_PATTERN_RE.search(cleaned_time)
-    if regex_match is None:
-        logger.warning(
-            f"{time} did not match RFC-2822 format. Unable to extract the time.",
-        )
-        return None
-
-    start, end = regex_match.span()
-    dt_string = cleaned_time[start:end]
-    datetime_object = datetime.datetime.strptime(dt_string, "%a, %d %b %Y %H:%M:%S %z")
-    return datetime_object.isoformat()
-
-
-def _extract_attachment_info(
-    message: EmailMessage,
-    output_dir: str | None = None,
-) -> list[dict[str, str]]:
-    list_attachments: list[Any] = []
-
-    for part in message.walk():
-        if "content-disposition" in part:
-            cdisp = part["content-disposition"].split(";")
-            cdisp = [clean_extra_whitespace(item) for item in cdisp]
-
-            attachment_info: dict[str, Any] = {}
-            for item in cdisp:
-                if item.lower() in ("attachment", "inline"):
-                    continue
-                key, value = item.split("=", 1)
-                key = clean_extra_whitespace(key.replace('"', ""))
-                value = clean_extra_whitespace(value.replace('"', ""))
-                attachment_info[clean_extra_whitespace(key)] = clean_extra_whitespace(
-                    value,
-                )
-            attachment_info["payload"] = part.get_payload(decode=True)
-            list_attachments.append(attachment_info)
-
-            if output_dir:
-                for idx, attachment in enumerate(list_attachments):
-                    if "filename" in attachment:
-                        filename = output_dir + "/" + attachment["filename"]
-                        with open(filename, "wb") as f:
-                            # Note(harrell) mypy wants to just us `w` when opening the file but this
-                            # causes an error since the payloads are bytes not str
-                            f.write(attachment["payload"])
-                    else:
-                        filename = os.path.join(output_dir, f"attachment_{idx}")
-                        with open(filename, "wb") as f:
-                            list_attachments[idx]["filename"] = os.path.basename(filename)
-                            f.write(attachment["payload"])
-
-    return list_attachments
-
-
-def _find_embedded_image(
-    element: NarrativeText | Title, indices: re.Match[str]
-) -> tuple[Element, Element]:
-    start, end = indices.start(), indices.end()
-
-    image_raw_info = element.text[start:end]
-    image_info = clean_extra_whitespace(image_raw_info.split(":")[1])
-    element.text = element.text.replace("[image: " + image_info[:-1] + "]", "")
-    return Image(text=image_info[:-1], detection_origin="email"), element
-
-
-def _find_signature(msg: EmailMessage) -> str | None:
-    """Extracts the signature from an email message, if it's available."""
-    payload: Any = msg.get_payload()
-    if not isinstance(payload, list):
-        return None
-
-    payload = cast(list[EmailMessage], payload)
-    for item in payload:
-        if item.get_content_type().endswith("signature"):
-            return item.get_payload()
-
-    return None
-
-
-def _has_embedded_image(element: Element):
-    PATTERN = re.compile(r"\[image: .+\]")
-    return PATTERN.search(element.text)
-
-
-def _parse_email(
-    filename: str | None = None, file: IO[bytes] | None = None
-) -> tuple[str | None, EmailMessage]:
-    if filename is not None:
-        with open(filename, "rb") as f:
-            msg = email.message_from_binary_file(f, policy=policy.default)
-    elif file is not None:
-        f_bytes = convert_to_bytes(file)
-        msg = email.message_from_bytes(f_bytes, policy=policy.default)
-    else:
-        raise ValueError("Either 'filename' or 'file' must be provided.")
-
-    encoding = None
-    charsets = msg.get_charsets() or []
-    for charset in charsets:
-        if charset and charset.strip() and validate_encoding(charset):
-            encoding = charset
-            break
-
-    formatted_encoding = format_encoding_str(encoding) if encoding else None
-    msg = cast(EmailMessage, msg)
-    return formatted_encoding, msg
-
-
-def _parse_received_data(data: str) -> list[Element]:
-    ip_address_names = extract_ip_address_name(data)
-    ip_addresses = extract_ip_address(data)
-    mapi_id = extract_mapi_id(data)
-    datetimetz = extract_datetimetz(data)
-
-    elements: list[Element] = []
-    if ip_address_names and ip_addresses:
-        for name, ip in zip(ip_address_names, ip_addresses):
-            elements.append(ReceivedInfo(name=name, text=ip))
-    if mapi_id:
-        elements.append(ReceivedInfo(name="mapi_id", text=mapi_id[0]))
-    if datetimetz:
-        elements.append(
-            ReceivedInfo(
-                name="received_datetimetz",
-                text=str(datetimetz),
-                datestamp=datetimetz,
-            ),
-        )
-    return elements
+        if content_type == "text/html":
+            yield from partition_html(
+                text=content,
+                metadata_filename=self._ctx.metadata_file_path,
+                metadata_file_type=FileType.EML,
+                metadata_last_modified=self._ctx.metadata_last_modified,
+                **self._ctx.partitioning_kwargs,
+            )
+        else:
+            yield from partition_text(
+                text=content,
+                metadata_filename=self._ctx.metadata_file_path,
+                metadata_file_type=FileType.EML,
+                metadata_last_modified=self._ctx.metadata_last_modified,
+                **self._ctx.partitioning_kwargs,
+            )
 
 
-def _partition_email_header(msg: EmailMessage) -> list[Element]:
-    def append_address_header_elements(header: AddressHeader, element_type: Type[Element]):
-        for addr in header.addresses:
-            elements.append(
-                element_type(
-                    name=addr.display_name or addr.username,  # type: ignore
-                    text=addr.addr_spec,  # type: ignore
-                )
-            )
+class _AttachmentPartitioner:
+    """Partitions an attachment to a MSG file."""
 
-    elements: list[Element] = []
-
-    for msg_field, msg_value in msg.items():
-        if msg_field in {"To", "Bcc", "Cc"}:
-            append_address_header_elements(msg_value, Recipient)
-        elif msg_field == "From":
-            append_address_header_elements(msg_value, Sender)
-        elif msg_field == "Subject":
-            elements.append(Subject(text=msg_value))
-        elif msg_field == "Received":
-            elements += _parse_received_data(msg_value)
-        elif msg_field == "Message-ID":
-            elements.append(MetaData(name=msg_field, text=_strip_angle_brackets(str(msg_value))))
-        else:
-            elements.append(MetaData(name=msg_field, text=msg_value))
+    def __init__(self, attachment: EmailMessage, ctx: EmailPartitioningContext):
+        self._attachment = attachment
+        self._ctx = ctx
 
-    return elements
+    @classmethod
+    def iter_elements(
+        cls, attachment: EmailMessage, ctx: EmailPartitioningContext
+    ) -> Iterator[Element]:
+        """Partition an attachment MIME-part from a MIME email message (.eml file)."""
+        return cls(attachment, ctx)._iter_elements()
 
+    def _iter_elements(self) -> Iterator[Element]:
+        """Partition the byte-stream in the attachment MIME-part into elements.
 
-def _strip_angle_brackets(data: str) -> str:
-    """Remove angle brackets from the beginning and end of the string if they exist.
+        Generates zero elements if the attachment is not partitionable.
+        """
+        # -- `auto.partition()` imports this module, so we need to defer the import to here to
+        # -- avoid a circular import.
+        from unstructured.partition.auto import partition
 
-    Returns:
-    str: The string with surrounding angle brackets removed.
+        file = io.BytesIO(self._file_bytes)
 
-    Example:
-    >>> _strip_angle_brackets("<example>")
-    'example'
-    >>> _strip_angle_brackets("<another>test>")
-    'another>test'
-    >>> _strip_angle_brackets("<<edge>>")
-    '<edge>'
-    """
-    return re.sub(r"^<|>$", "", data)
+        # -- partition the attachment --
+        try:
+            elements = partition(
+                file=file,
+                metadata_filename=self._attachment_file_name,
+                metadata_last_modified=self._ctx.metadata_last_modified,
+                **self._ctx.partitioning_kwargs,
+            )
+        except UnsupportedFileFormatError:
+            # -- indicates `auto.partition()` has no partitioner for this file-format;
+            # -- silently skip the attachment
+            return
+
+        for e in elements:
+            e.metadata.attached_to_filename = self._attached_to_filename
+            yield e
+
+    @lazyproperty
+    def _attached_to_filename(self) -> str | None:
+        """The file-name (no path) of the message. `None` if not available."""
+        file_path = self._ctx.metadata_file_path
+        if file_path is None:
+            return None
+        return os.path.basename(file_path)
+
+    @lazyproperty
+    def _attachment_file_name(self) -> str | None:
+        """The original name of the attached file, `None` if not present in the MIME part."""
+        return self._attachment.get_filename()
+
+    @lazyproperty
+    def _file_bytes(self) -> bytes:
+        """The bytes of the attached file."""
+        content = self._attachment.get_content()
+
+        if isinstance(content, str):
+            return content.encode("utf-8")
+
+        assert isinstance(content, bytes)
+        return content
diff --git a/unstructured/partition/msg.py b/unstructured/partition/msg.py
index 5ef4c9e091..7c43f4667e 100644
--- a/unstructured/partition/msg.py
+++ b/unstructured/partition/msg.py
@@ -11,6 +11,7 @@
 from unstructured.documents.elements import Element, ElementMetadata
 from unstructured.file_utils.model import FileType
 from unstructured.logger import logger
+from unstructured.partition.common import UnsupportedFileFormatError
 from unstructured.partition.common.metadata import get_last_modified_date
 from unstructured.partition.html import partition_html
 from unstructured.partition.text import partition_text
@@ -23,7 +24,7 @@ def partition_msg(
     file: Optional[IO[bytes]] = None,
     metadata_filename: Optional[str] = None,
     metadata_last_modified: Optional[str] = None,
-    process_attachments: bool = False,
+    process_attachments: bool = True,
     **kwargs: Any,
 ) -> list[Element]:
     """Partitions a MSFT Outlook .msg file
@@ -259,14 +260,19 @@ def _iter_elements(self) -> Iterator[Element]:
                 f.write(self._file_bytes)
 
             # -- partition the attachment --
-            for element in partition(
-                detached_file_path,
-                metadata_filename=self._attachment_file_name,
-                metadata_last_modified=self._attachment_last_modified,
-                **self._opts.partitioning_kwargs,
-            ):
-                element.metadata.attached_to_filename = self._opts.metadata_file_path
-                yield element
+            try:
+                elements = partition(
+                    detached_file_path,
+                    metadata_filename=self._attachment_file_name,
+                    metadata_last_modified=self._attachment_last_modified,
+                    **self._opts.partitioning_kwargs,
+                )
+            except UnsupportedFileFormatError:
+                return
+
+            for e in elements:
+                e.metadata.attached_to_filename = self._opts.metadata_file_path
+                yield e
 
     @lazyproperty
     def _attachment_file_name(self) -> str:


Test patch:
diff --git a/test_unstructured/documents/test_email_elements.py b/test_unstructured/documents/test_email_elements.py
deleted file mode 100644
index 58989f0903..0000000000
--- a/test_unstructured/documents/test_email_elements.py
+++ /dev/null
@@ -1,96 +0,0 @@
-from functools import partial
-
-import pytest
-
-from unstructured.cleaners.core import clean_prefix
-from unstructured.cleaners.translate import translate_text
-from unstructured.documents.email_elements import EmailElement, Name, Subject
-
-
-@pytest.mark.parametrize(
-    "element", [EmailElement(text=""), Name(text="", name=""), Subject(text="")]
-)
-def test_EmailElement_autoassigns_a_UUID_then_becomes_an_idempotent_and_deterministic_hash(
-    element: EmailElement,
-):
-    # -- element self-assigns itself a UUID --
-    assert isinstance(element.id, str)
-    assert len(element.id) == 36
-    assert element.id.count("-") == 4
-
-    expected_hash = "5336294a19f32ff03ef80066fbc3e0f7"
-    # -- calling `.id_to_hash()` changes the element's id-type to hash --
-    assert element.id_to_hash(0) == expected_hash
-    assert element.id == expected_hash
-
-    # -- `.id_to_hash()` is idempotent --
-    assert element.id_to_hash(0) == expected_hash
-
-
-def test_Name_should_assign_a_deterministic_and_an_idempotent_hash():
-    element = Name(name="Example", text="hello there!")
-    expected_hash = "7d191bcecf80c122578c497de5f0dae7"
-
-    assert element._element_id is None, "Element should not have an ID yet"
-
-    # -- calculating hash for the first time --
-    assert element.id_to_hash(0) == expected_hash
-    assert element.id == expected_hash
-
-    # -- `.id_to_hash()` is idempotent --
-    assert element.id_to_hash(0) == expected_hash
-    assert element.id == expected_hash
-
-
-@pytest.mark.parametrize(
-    "element",
-    [
-        EmailElement(text=""),  # -- the default `element_id` is None --
-        Name(name="Example", text="hello there!"),  # -- the default `element_id` is None --
-        Name(name="Example", text="hello there!", element_id=None),
-    ],
-)
-def test_EmailElement_assigns_a_UUID_only_once_and_only_at_the_first_id_request(
-    element: EmailElement,
-):
-    assert element._element_id is None, "Element should not have an ID yet"
-
-    # -- this should generate and assign a fresh UUID --
-    id_value = element.id
-
-    # -- check that the UUID is valid --
-    assert element._element_id is not None, "Element should already have an ID"
-    assert isinstance(id_value, str)
-    assert len(id_value) == 36
-    assert id_value.count("-") == 4
-
-    assert element.id == id_value, "UUID assignment should happen only once"
-
-
-def test_text_element_apply_cleaners():
-    name_element = Name(name="[2] Example docs", text="[1] A Textbook on Crocodile Habitats")
-
-    name_element.apply(partial(clean_prefix, pattern=r"\[\d{1,2}\]"))
-    assert str(name_element) == "Example docs: A Textbook on Crocodile Habitats"
-
-
-def test_name_element_apply_multiple_cleaners():
-    cleaners = [
-        partial(clean_prefix, pattern=r"\[\d{1,2}\]"),
-        partial(translate_text, target_lang="ru"),
-    ]
-    name_element = Name(
-        name="[1] A Textbook on Crocodile Habitats",
-        text="[1] A Textbook on Crocodile Habitats",
-    )
-    name_element.apply(*cleaners)
-    assert (
-        str(name_element)
-        == "Учебник по крокодильным средам обитания: Учебник по крокодильным средам обитания"
-    )
-
-
-def test_apply_raises_if_func_does_not_produce_string():
-    name_element = Name(name="Example docs", text="[1] A Textbook on Crocodile Habitats")
-    with pytest.raises(ValueError):
-        name_element.apply(lambda s: 1)
diff --git a/test_unstructured/partition/test_auto.py b/test_unstructured/partition/test_auto.py
index eacdcef8c9..8d6670fd34 100644
--- a/test_unstructured/partition/test_auto.py
+++ b/test_unstructured/partition/test_auto.py
@@ -45,6 +45,7 @@
 )
 from unstructured.file_utils.model import FileType
 from unstructured.partition.auto import _PartitionerLoader, partition
+from unstructured.partition.common import UnsupportedFileFormatError
 from unstructured.partition.utils.constants import PartitionStrategy
 from unstructured.staging.base import elements_from_json, elements_to_dicts, elements_to_json
 
@@ -200,14 +201,6 @@ def test_auto_partition_email_from_file():
     assert elements == EXPECTED_EMAIL_OUTPUT
 
 
-def test_auto_partition_eml_add_signature_to_metadata():
-    elements = partition(example_doc_path("eml/signed-doc.p7s"))
-
-    assert len(elements) == 1
-    assert elements[0].text == "This is a test"
-    assert elements[0].metadata.signature == "<SIGNATURE>\n"
-
-
 # ================================================================================================
 # EPUB
 # ================================================================================================
@@ -911,7 +904,10 @@ def test_auto_partition_raises_with_bad_type(request: FixtureRequest):
         request, "unstructured.partition.auto.detect_filetype", return_value=FileType.UNK
     )
 
-    with pytest.raises(ValueError, match="Invalid file made-up.fake. The FileType.UNK file type "):
+    with pytest.raises(
+        UnsupportedFileFormatError,
+        match="Invalid file made-up.fake. The FileType.UNK file type is not supported in partiti",
+    ):
         partition(filename="made-up.fake", strategy=PartitionStrategy.HI_RES)
 
     detect_filetype_.assert_called_once_with(
@@ -1239,7 +1235,7 @@ def test_auto_partition_applies_the_correct_filetype_for_all_filetypes(
     partition_fn = getattr(module, partition_fn_name)
 
     # -- partition the example-doc for this filetype --
-    elements = partition_fn(file_path)
+    elements = partition_fn(file_path, process_attachments=False)
 
     assert elements
     assert all(
diff --git a/test_unstructured/partition/test_email.py b/test_unstructured/partition/test_email.py
index 2512e5c1ff..eb34d499ca 100644
--- a/test_unstructured/partition/test_email.py
+++ b/test_unstructured/partition/test_email.py
@@ -1,51 +1,32 @@
 """Test suite for `unstructured.partition.email` module."""
 
-# pyright: reportPrivateUsage=false
-
 from __future__ import annotations
 
-import datetime
-import email
-import os
-import pathlib
+import io
 import tempfile
-from email import policy
 from email.message import EmailMessage
-from typing import cast
+from typing import Any
 
 import pytest
-from pytest_mock import MockFixture
 
 from test_unstructured.unit_utils import (
-    LogCaptureFixture,
+    FixtureRequest,
+    Mock,
     assert_round_trips_through_JSON,
     example_doc_path,
-    parse_optional_datetime,
+    function_mock,
 )
 from unstructured.chunking.title import chunk_by_title
 from unstructured.documents.elements import (
-    Element,
-    ElementMetadata,
-    Image,
+    CompositeElement,
     ListItem,
     NarrativeText,
+    Table,
+    TableChunk,
     Text,
     Title,
 )
-from unstructured.documents.email_elements import (
-    MetaData,
-    ReceivedInfo,
-    Recipient,
-    Sender,
-    Subject,
-)
-from unstructured.partition.email import (
-    _convert_to_iso_8601,
-    _extract_attachment_info,
-    _partition_email_header,
-    partition_email,
-)
-from unstructured.partition.text import partition_text
+from unstructured.partition.email import EmailPartitioningContext, partition_email
 
 EXPECTED_OUTPUT = [
     NarrativeText(text="This is a test email to use for unit tests."),
@@ -54,565 +35,578 @@
     ListItem(text="Violets are blue"),
 ]
 
-IMAGE_EXPECTED_OUTPUT = [
-    NarrativeText(text="This is a test email to use for unit tests."),
-    Title(text="Important points:"),
-    NarrativeText(text="hello this is our logo."),
-    Image(text="unstructured_logo.png"),
-    ListItem(text="Roses are red"),
-    ListItem(text="Violets are blue"),
-]
 
-RECEIVED_HEADER_OUTPUT = [
-    ReceivedInfo(name="ABCDEFG-000.ABC.guide", text="00.0.0.00"),
-    ReceivedInfo(name="ABCDEFG-000.ABC.guide", text="ba23::58b5:2236:45g2:88h2"),
-    ReceivedInfo(
-        name="received_datetimetz",
-        text="2023-02-20 10:03:18+12:00",
-        datestamp=datetime.datetime(
-            2023,
-            2,
-            20,
-            10,
-            3,
-            18,
-            tzinfo=datetime.timezone(datetime.timedelta(seconds=43200)),
+def test_partition_email_from_filename_can_partition_an_RFC_822_email():
+    assert partition_email(example_doc_path("eml/simple-rfc-822.eml")) == [
+        NarrativeText("This is an RFC 822 email message."),
+        NarrativeText(
+            "An RFC 822 message is characterized by its simple, text-based format, which includes"
+            ' a header and a body. The header contains structured fields such as "From", "To",'
+            ' "Date", and "Subject", each followed by a colon and the corresponding information.'
+            " The body follows the header, separated by a blank line, and contains the main"
+            " content of the email."
         ),
-    ),
-    MetaData(name="MIME-Version", text="1.0"),
-    MetaData(name="Date", text="Fri, 16 Dec 2022 17:04:16 -0500"),
-    Recipient(name="Hello", text="hello@unstructured.io"),
-    MetaData(
-        name="Message-ID",
-        text="CADc-_xaLB2FeVQ7mNsoX+NJb_7hAJhBKa_zet-rtgPGenj0uVw@mail.gmail.com",
-    ),
-    Subject(text="Test Email"),
-    Sender(name="Matthew Robinson", text="mrobinson@unstructured.io"),
-    Recipient(name="Matthew Robinson", text="mrobinson@unstructured.io"),
-    Recipient(name="Fake Email", text="fake-email@unstructured.io"),
-    Recipient(name="test", text="test@unstructured.io"),
-    MetaData(
-        name="Content-Type",
-        text='multipart/alternative; boundary="00000000000095c9b205eff92630"',
-    ),
-]
-
-HEADER_EXPECTED_OUTPUT = [
-    MetaData(name="MIME-Version", text="1.0"),
-    MetaData(name="Date", text="Fri, 16 Dec 2022 17:04:16 -0500"),
-    MetaData(
-        name="Message-ID",
-        text="CADc-_xaLB2FeVQ7mNsoX+NJb_7hAJhBKa_zet-rtgPGenj0uVw@mail.gmail.com",
-    ),
-    Subject(text="Test Email"),
-    Sender(name="Matthew Robinson", text="mrobinson@unstructured.io"),
-    Recipient(name="Matthew Robinson", text="mrobinson@unstructured.io"),
-    MetaData(
-        name="Content-Type",
-        text='multipart/alternative; boundary="00000000000095c9b205eff92630"',
-    ),
-]
+        NarrativeText(
+            "The structure ensures compatibility and readability across different email systems"
+            " and clients, adhering to the standards set by the Internet Engineering Task Force"
+            " (IETF)."
+        ),
+    ]
 
-ALL_EXPECTED_OUTPUT = HEADER_EXPECTED_OUTPUT + EXPECTED_OUTPUT
 
-ATTACH_EXPECTED_OUTPUT = [
-    {"filename": "fake-attachment.txt", "payload": b"Hey this is a fake attachment!"},
-]
+def test_partition_email_from_file_can_partition_an_email():
+    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
+        assert partition_email(file=f) == EXPECTED_OUTPUT
 
 
-def test_partition_email_from_filename():
-    elements = partition_email(filename=example_doc_path("eml/fake-email.eml"))
+def test_partition_email_from_spooled_temp_file_can_partition_an_email():
+    with tempfile.SpooledTemporaryFile() as file:
+        with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
+            file.write(f.read())
+        file.seek(0)
 
-    assert len(elements) > 0
-    assert elements == EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename == "fake-email.eml"
+        assert partition_email(file=file) == EXPECTED_OUTPUT
 
 
-def test_partition_email_from_filename_malformed_encoding():
-    elements = partition_email(filename=example_doc_path("eml/fake-email-malformed-encoding.eml"))
+def test_partition_email_can_partition_an_HTML_only_email_with_Base64_ISO_8859_1_charset():
+    assert partition_email(example_doc_path("eml/mime-html-only.eml")) == [
+        NarrativeText("This is a text/html part."),
+        NarrativeText(
+            "The first emoticon, :) , was proposed by Scott Fahlman in 1982 to indicate just or"
+            " sarcasm in text emails."
+        ),
+        NarrativeText(
+            "Gmail was launched by Google in 2004 with 1 GB of free storage, significantly more"
+            " than what other services offered at the time."
+        ),
+    ]
 
-    assert len(elements) > 0
-    assert elements == EXPECTED_OUTPUT
 
+def test_extract_email_from_text_plain_matches_elements_extracted_from_text_html():
+    file_path = example_doc_path("eml/fake-email.eml")
 
-@pytest.mark.parametrize(
-    ("filename", "expected_output"),
-    [
-        ("fake-email-utf-16.eml", EXPECTED_OUTPUT),
-        ("fake-email-utf-16-be.eml", EXPECTED_OUTPUT),
-        ("fake-email-utf-16-le.eml", EXPECTED_OUTPUT),
-        ("fake-email-b64.eml", EXPECTED_OUTPUT),
-        ("email-no-utf8-2008-07-16.062410.eml", None),
-        ("email-no-utf8-2014-03-17.111517.eml", None),
-        ("email-replace-mime-encodings-error-1.eml", None),
-        ("email-replace-mime-encodings-error-2.eml", None),
-        ("email-replace-mime-encodings-error-3.eml", None),
-        ("email-replace-mime-encodings-error-4.eml", None),
-        ("email-replace-mime-encodings-error-5.eml", None),
-    ],
-)
-def test_partition_email_from_filename_default_encoding(
-    filename: str, expected_output: Element | None
-):
-    elements = partition_email(example_doc_path("eml/" + filename))
+    elements_from_text = partition_email(file_path, content_source="text/plain")
+    elements_from_html = partition_email(file_path, content_source="text/html")
 
-    assert len(elements) > 0
-    if expected_output:
-        assert elements == expected_output
-    for element in elements:
-        assert element.metadata.filename == filename
+    assert elements_from_text == EXPECTED_OUTPUT
+    assert elements_from_html == EXPECTED_OUTPUT
+    assert elements_from_html == elements_from_text
 
 
-def test_partition_email_from_file():
-    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
-        elements = partition_email(file=f)
+def test_partition_email_round_trips_via_json():
+    elements = partition_email(example_doc_path("eml/fake-email.eml"))
+    assert_round_trips_through_JSON(elements)
 
-    assert len(elements) > 0
-    assert elements == EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename is None
-
-
-@pytest.mark.parametrize(
-    ("filename", "expected_output"),
-    [
-        ("fake-email-utf-16.eml", EXPECTED_OUTPUT),
-        ("fake-email-utf-16-be.eml", EXPECTED_OUTPUT),
-        ("fake-email-utf-16-le.eml", EXPECTED_OUTPUT),
-        ("fake-email-b64.eml", EXPECTED_OUTPUT),
-        ("email-no-utf8-2008-07-16.062410.eml", None),
-        ("email-no-utf8-2014-03-17.111517.eml", None),
-        ("email-replace-mime-encodings-error-1.eml", None),
-        ("email-replace-mime-encodings-error-2.eml", None),
-        ("email-replace-mime-encodings-error-3.eml", None),
-        ("email-replace-mime-encodings-error-4.eml", None),
-        ("email-replace-mime-encodings-error-5.eml", None),
-    ],
-)
-def test_partition_email_from_file_default_encoding(filename: str, expected_output: Element | None):
-    with open(example_doc_path("eml/" + filename), "rb") as f:
-        elements = partition_email(file=f)
 
-    assert len(elements) > 0
-    if expected_output:
-        assert elements == expected_output
-    for element in elements:
-        assert element.metadata.filename is None
+# -- transfer-encodings --------------------------------------------------------------------------
 
 
-def test_partition_email_from_file_rb():
-    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
-        elements = partition_email(file=f)
+def test_partition_email_partitions_an_HTML_part_with_Base64_encoded_UTF_8_charset():
+    assert partition_email(example_doc_path("eml/fake-email-b64.eml")) == EXPECTED_OUTPUT
 
-    assert len(elements) > 0
-    assert elements == EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename is None
-
-
-@pytest.mark.parametrize(
-    ("filename", "expected_output"),
-    [
-        ("fake-email-utf-16.eml", EXPECTED_OUTPUT),
-        ("fake-email-utf-16-be.eml", EXPECTED_OUTPUT),
-        ("fake-email-utf-16-le.eml", EXPECTED_OUTPUT),
-        ("email-no-utf8-2008-07-16.062410.eml", None),
-        ("email-no-utf8-2014-03-17.111517.eml", None),
-        ("email-replace-mime-encodings-error-1.eml", None),
-        ("email-replace-mime-encodings-error-2.eml", None),
-        ("email-replace-mime-encodings-error-3.eml", None),
-        ("email-replace-mime-encodings-error-4.eml", None),
-        ("email-replace-mime-encodings-error-5.eml", None),
-    ],
-)
-def test_partition_email_from_file_rb_default_encoding(
-    filename: str, expected_output: Element | None
-):
-    with open(example_doc_path("eml/" + filename), "rb") as f:
-        elements = partition_email(file=f)
 
-    assert len(elements) > 0
-    if expected_output:
-        assert elements == expected_output
-    for element in elements:
-        assert element.metadata.filename is None
-
-
-def test_partition_email_from_spooled_temp_file():
-    filename = example_doc_path("eml/family-day.eml")
-    with open(filename, "rb") as test_file:
-        spooled_temp_file = tempfile.SpooledTemporaryFile()
-        spooled_temp_file.write(test_file.read())
-        spooled_temp_file.seek(0)
-        elements = partition_email(file=spooled_temp_file)
-        assert len(elements) == 9
-        assert elements[3].text == "Make sure to RSVP!"
+def test_partition_email_partitions_a_text_plain_part_with_Base64_encoded_windows_1255_charset():
+    elements = partition_email(
+        example_doc_path("eml/email-no-utf8-2008-07-16.062410.eml"),
+        content_source="text/plain",
+    )
 
+    assert len(elements) == 30
+    assert elements[1].text.startswith("אני חושב שזה לא יהיה מקצועי והוגן שאני אראה לך היכן")
 
-def test_partition_email_from_text_file():
-    with open(example_doc_path("eml/fake-email.txt"), "rb") as f:
-        elements = partition_email(file=f, content_source="text/plain")
 
-    assert len(elements) > 0
-    assert elements == EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename is None
+def test_partition_email_partitions_an_html_part_with_quoted_printable_encoded_ISO_8859_1_charset():
+    elements = partition_email(
+        example_doc_path("eml/email-no-utf8-2014-03-17.111517.eml"),
+        content_source="text/html",
+        process_attachments=False,
+    )
 
+    assert len(elements) == 1
+    assert isinstance(elements[0], Table)
+    assert elements[0].text.startswith("Slava Gxyzxyz Hi Slava, The password for your Google")
 
-def test_partition_email_from_text_file_with_headers():
-    with open(example_doc_path("eml/fake-email.txt"), "rb") as f:
-        elements = partition_email(file=f, content_source="text/plain", include_headers=True)
 
-    assert len(elements) > 0
-    assert elements == ALL_EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename is None
+# -- edge-cases ----------------------------------------------------------------------------------
 
 
-def test_partition_email_from_text():
-    with open(example_doc_path("eml/fake-email.eml")) as f:
-        text = f.read()
+def test_partition_email_accepts_a_whitespace_only_file():
+    """Should produce no elements but should not raise an exception."""
+    assert partition_email(example_doc_path("eml/empty.eml")) == []
 
-    elements = partition_email(text=text)
 
-    assert len(elements) > 0
-    assert elements == EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename is None
+def test_partition_email_can_partition_an_empty_email():
+    assert (
+        partition_email(example_doc_path("eml/mime-no-body.eml"), process_attachments=False) == []
+    )
 
 
-def test_partition_email_from_text_work_with_empty_string():
-    assert partition_email(text="") == []
+def test_partition_email_does_not_break_on_an_encrypted_message():
+    assert (
+        partition_email(example_doc_path("eml/fake-encrypted.eml"), process_attachments=False) == []
+    )
 
 
-def test_partition_email_from_filename_with_embedded_image():
+def test_partition_email_finds_content_when_it_is_marked_with_content_disposition_inline():
     elements = partition_email(
-        example_doc_path("eml/fake-email-image-embedded.eml"), content_source="text/plain"
+        example_doc_path("eml/email-inline-content-disposition.eml"), process_attachments=False
     )
 
-    assert len(elements) > 0
-    assert elements == IMAGE_EXPECTED_OUTPUT
-    for element in elements:
-        assert element.metadata.filename == "fake-email-image-embedded.eml"
+    assert len(elements) == 1
+    e = elements[0]
+    assert isinstance(e, Text)
+    assert e.text == "This is a test of inline"
 
 
-def test_partition_email_from_file_with_header():
-    with open(example_doc_path("eml/fake-email-header.eml")) as f:
-        msg = email.message_from_file(f, policy=policy.default)
+def test_partition_email_from_filename_malformed_encoding():
+    elements = partition_email(filename=example_doc_path("eml/fake-email-malformed-encoding.eml"))
+    assert elements == EXPECTED_OUTPUT
 
-    msg = cast(EmailMessage, msg)
-    elements = _partition_email_header(msg)
 
-    assert len(elements) > 0
-    assert elements == RECEIVED_HEADER_OUTPUT
-    all(element.metadata.filename is None for element in elements)
+# -- error behaviors -----------------------------------------------------------------------------
 
 
-def test_extract_email_text_matches_html():
-    filename = example_doc_path("eml/fake-email-attachment.eml")
-    elements_from_text = partition_email(filename, content_source="text/plain")
-    elements_from_html = partition_email(filename, content_source="text/html")
+def test_partition_email_raises_when_no_message_source_is_specified():
+    with pytest.raises(ValueError, match="no document specified; either a `filename` or `file`"):
+        partition_email()
 
-    assert len(elements_from_text) == len(elements_from_html)
-    # NOTE(robinson) - checking each individually is necessary because the text/html returns
-    # HTMLTitle, HTMLNarrativeText, etc
-    for i, element in enumerate(elements_from_text):
-        assert element == elements_from_text[i]
-        assert element.metadata.filename == "fake-email-attachment.eml"
 
+def test_partition_email_raises_with_invalid_content_type():
+    with pytest.raises(ValueError, match="'application/json' is not a valid value for content_s"):
+        partition_email(example_doc_path("eml/fake-email.eml"), content_source="application/json")
 
-def test_extract_base64_email_text_matches_html():
-    filename = example_doc_path("eml/fake-email-b64.eml")
-    elements_from_text = partition_email(filename, content_source="text/plain")
-    elements_from_html = partition_email(filename, content_source="text/html")
 
-    assert len(elements_from_text) == len(elements_from_html)
-    for i, element in enumerate(elements_from_text):
-        assert element == elements_from_text[i]
-        assert element.metadata.filename == "fake-email-b64.eml"
+# -- .metadata -----------------------------------------------------------------------------------
 
 
-def test_partition_email_processes_fake_email_with_header():
-    elements = partition_email(example_doc_path("eml/fake-email-header.eml"))
+def test_partition_email_augments_message_body_elements_with_email_metadata():
+    elements = partition_email(example_doc_path("eml/mime-multi-to-cc-bcc.eml"))
 
-    assert len(elements) > 0
-    assert all(element.metadata.filename == "fake-email-header.eml" for element in elements)
     assert all(
-        element.metadata.bcc_recipient == ["Hello <hello@unstructured.io>"] for element in elements
+        e.metadata.bcc_recipient == ["John <john@example.com>", "Mary <mary@example.com>"]
+        for e in elements
     )
     assert all(
-        element.metadata.cc_recipient
-        == ["Fake Email <fake-email@unstructured.io>", "test@unstructured.io"]
-        for element in elements
+        e.metadata.cc_recipient == ["Tom <tom@example.com>", "Alice <alice@example.com>"]
+        for e in elements
     )
-    assert all(element.metadata.email_message_id is not None for element in elements)
+    assert all(e.metadata.email_message_id == "2143658709@example.com" for e in elements)
+    assert all(e.metadata.sent_from == ["sender@example.com"] for e in elements)
+    assert all(
+        e.metadata.sent_to == ["Bob <bob@example.com>", "Sue <sue@example.com>"] for e in elements
+    )
+    assert all(e.metadata.subject == "Example Plain-Text MIME Message" for e in elements)
 
 
-@pytest.mark.parametrize(
-    (("time", "expected")),
-    [
-        ("Thu,  4 May 2023 02:32:49 +0000", "2023-05-04T02:32:49+00:00"),
-        ("Thu, 4 May 2023 02:32:49 +0000", "2023-05-04T02:32:49+00:00"),
-        ("Thu, 4 May 2023 02:32:49 +0000 (UTC)", "2023-05-04T02:32:49+00:00"),
-        ("Thursday 5/3/2023 02:32:49", None),
-    ],
-)
-def test_convert_to_iso_8601(time: str, expected: str | None):
-    iso_time = _convert_to_iso_8601(time)
+# -- .metadata.filename --------------------------------------------------------------------------
 
-    assert iso_time == expected
 
+def test_partition_email_from_filename_gets_filename_metadata_from_file_path():
+    elements = partition_email(example_doc_path("eml/fake-email.eml"))
 
-def test_partition_email_still_works_with_no_content(caplog: LogCaptureFixture):
-    elements = partition_email(example_doc_path("eml/email-no-html-content-1.eml"))
+    assert all(e.metadata.filename == "fake-email.eml" for e in elements)
+    assert all(e.metadata.file_directory == example_doc_path("eml") for e in elements)
 
-    assert len(elements) == 1
-    assert elements[0].text.startswith("Hey there")
-    assert "text/html was not found. Falling back to text/plain" in caplog.text
 
+def test_partition_email_from_file_gets_filename_metadata_None():
+    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
+        elements = partition_email(file=f)
+
+    assert all(e.metadata.filename is None for e in elements)
+    assert all(e.metadata.file_directory is None for e in elements)
+
+
+def test_partition_email_from_filename_prefers_metadata_filename():
+    elements = partition_email(
+        example_doc_path("eml/fake-email.eml"), metadata_filename="a/b/c.eml"
+    )
+
+    assert all(e.metadata.filename == "c.eml" for e in elements)
+    assert all(e.metadata.file_directory == "a/b" for e in elements)
+
+
+def test_partition_email_from_file_prefers_metadata_filename():
+    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
+        elements = partition_email(file=f, metadata_filename="d/e/f.eml")
+
+    assert all(e.metadata.filename == "f.eml" for e in elements)
+    assert all(e.metadata.file_directory == "d/e" for e in elements)
 
-def test_partition_email_with_json():
+
+# -- .metadata.filetype --------------------------------------------------------------------------
+
+
+def test_partition_email_gets_the_EML_MIME_type_in_metadata_filetype_for_message_body_elements():
+    EML_MIME_TYPE = "message/rfc822"
     elements = partition_email(example_doc_path("eml/fake-email.eml"))
-    assert_round_trips_through_JSON(elements)
+    assert all(e.metadata.filetype == EML_MIME_TYPE for e in elements), (
+        f"Expected all elements to have '{EML_MIME_TYPE}' as their filetype, but got:"
+        f" {repr(elements[0].metadata.filetype)}"
+    )
+
+
+# -- .metadata.languages -------------------------------------------------------------------------
+
 
+def test_partition_email_element_metadata_has_languages():
+    elements = partition_email(example_doc_path("eml/fake-email.eml"))
+    assert all(e.metadata.languages == ["eng"] for e in elements)
 
-def test_partition_email_with_pgp_encrypted_message(caplog: LogCaptureFixture):
-    elements = partition_email(example_doc_path("eml/fake-encrypted.eml"))
 
-    assert elements == []
-    assert "WARNING" in caplog.text
-    assert "Encrypted email detected" in caplog.text
+def test_partition_email_respects_languages_arg():
+    elements = partition_email(example_doc_path("eml/fake-email.eml"), languages=["deu"])
+    assert all(element.metadata.languages == ["deu"] for element in elements)
 
 
-def test_partition_email_inline_content_disposition():
+def test_partition_eml_respects_detect_language_per_element():
     elements = partition_email(
-        example_doc_path("eml/email-inline-content-disposition.eml"),
-        process_attachments=True,
-        attachment_partitioner=partition_text,
+        example_doc_path("language-docs/eng_spa_mult.eml"),
+        detect_language_per_element=True,
     )
+    # languages other than English and Spanish are detected by this partitioner,
+    # so this test is slightly different from the other partition tests
+    langs = {e.metadata.languages[0] for e in elements if e.metadata.languages is not None}
 
-    assert isinstance(elements[0], Text)
-    assert isinstance(elements[1], Text)
+    assert "eng" in langs
+    assert "spa" in langs
 
 
-def test_add_chunking_strategy_on_partition_email():
-    chunk_elements = partition_email(
-        example_doc_path("eml/fake-email.txt"), chunking_strategy="by_title"
-    )
-    elements = partition_email(example_doc_path("eml/fake-email.txt"))
-    chunks = chunk_by_title(elements)
+# -- .metadata.last_modified ---------------------------------------------------------------------
 
-    assert chunk_elements != elements
-    assert chunk_elements == chunks
 
+def test_partition_email_from_file_path_gets_last_modified_from_Date_header():
+    elements = partition_email(example_doc_path("eml/fake-email.eml"))
+    assert all(e.metadata.last_modified == "2022-12-16T22:04:16+00:00" for e in elements)
 
-# -- raise error behaviors -----------------------------------------------------------------------
 
+def test_partition_email_from_file_gets_last_modified_from_Date_header():
+    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
+        elements = partition_email(file=f)
 
-def test_partition_msg_raises_with_no_partitioner():
-    with pytest.raises(ValueError):
-        partition_email(example_doc_path("eml/fake-email-attachment.eml"), process_attachments=True)
+    assert all(e.metadata.last_modified == "2022-12-16T22:04:16+00:00" for e in elements)
 
 
-def test_partition_email_raises_with_none_specified():
-    with pytest.raises(ValueError):
-        partition_email()
+def test_partition_email_from_file_path_prefers_metadata_last_modified():
+    metadata_last_modified = "2020-07-05T09:24:28"
 
+    elements = partition_email(
+        example_doc_path("eml/fake-email.eml"), metadata_last_modified=metadata_last_modified
+    )
 
-def test_partition_email_raises_with_too_many_specified():
-    with open(example_doc_path("eml/fake-email.eml")) as f:
-        text = f.read()
+    assert all(e.metadata.last_modified == metadata_last_modified for e in elements)
 
-    with pytest.raises(ValueError):
-        partition_email(example_doc_path("eml/fake-email.eml"), text=text)
 
+def test_partition_email_from_file_prefers_metadata_last_modified():
+    metadata_last_modified = "2020-07-05T09:24:28"
+    with open(example_doc_path("eml/fake-email.eml"), "rb") as f:
+        elements = partition_email(file=f, metadata_last_modified=metadata_last_modified)
 
-def test_partition_email_raises_with_invalid_content_type():
-    with pytest.raises(ValueError):
-        partition_email(example_doc_path("eml/fake-email.eml"), content_source="application/json")
+    assert all(e.metadata.last_modified == metadata_last_modified for e in elements)
 
 
-# -- metadata behaviors --------------------------------------------------------------------------
+# -- chunking ------------------------------------------------------------------------------------
 
 
-def test_partition_email_from_filename_with_metadata_filename():
-    elements = partition_email(example_doc_path("eml/fake-email.eml"), metadata_filename="test")
+def test_partition_email_chunks_when_so_instructed():
+    """Note it's actually the delegate partitioners that do the chunking."""
+    elements = partition_email(example_doc_path("eml/fake-email.txt"))
+    chunks = partition_email(example_doc_path("eml/fake-email.txt"), chunking_strategy="by_title")
+    separately_chunked_chunks = chunk_by_title(elements)
 
-    assert len(elements) > 0
-    assert all(element.metadata.filename == "test" for element in elements)
+    assert all(isinstance(c, (CompositeElement, Table, TableChunk)) for c in chunks)
+    assert chunks != elements
+    assert chunks == separately_chunked_chunks
 
 
-def test_partition_email_from_filename_has_metadata():
-    elements = partition_email(example_doc_path("eml/fake-email.eml"))
-    parent_id = elements[0].metadata.parent_id
+def test_partition_email_chunks_attachments_too():
+    chunks = partition_email(
+        example_doc_path("eml/fake-email-attachment.eml"),
+        chunking_strategy="by_title",
+        process_attachments=True,
+    )
 
-    assert len(elements) > 0
-    assert (
-        elements[0].metadata.to_dict()
-        == ElementMetadata(
-            coordinates=None,
-            filename=example_doc_path("eml/fake-email.eml"),
-            last_modified="2022-12-16T17:04:16-05:00",
-            page_number=None,
-            url=None,
-            sent_from=["Matthew Robinson <mrobinson@unstructured.io>"],
-            sent_to=["NotMatthew <NotMatthew@notunstructured.com>"],
-            subject="Test Email",
-            filetype="message/rfc822",
-            parent_id=parent_id,
-            languages=["eng"],
-            email_message_id="CADc-_xaLB2FeVQ7mNsoX+NJb_7hAJhBKa_zet-rtgPGenj0uVw@mail.gmail.com",
-        ).to_dict()
+    assert len(chunks) == 2
+    assert all(isinstance(c, CompositeElement) for c in chunks)
+    attachment_chunk = chunks[-1]
+    assert attachment_chunk.text == "Hey this is a fake attachment!"
+    assert attachment_chunk.metadata.filename == "fake-attachment.txt"
+    assert attachment_chunk.metadata.attached_to_filename == "fake-email-attachment.eml"
+    assert all(c.metadata.last_modified == "2022-12-23T18:08:48+00:00" for c in chunks)
+
+
+# -- attachments ---------------------------------------------------------------------------------
+
+
+def test_partition_email_also_partitions_attachments_when_so_instructed():
+    elements = partition_email(
+        example_doc_path("eml/email-equals-attachment-filename.eml"), process_attachments=True
     )
-    expected_dt = datetime.datetime.fromisoformat("2022-12-16T17:04:16-05:00")
-    assert parse_optional_datetime(elements[0].metadata.last_modified) == expected_dt
-    for element in elements:
-        assert element.metadata.filename == "fake-email.eml"
 
+    assert elements == [
+        NarrativeText("Below is an example of an odd filename"),
+        Title("Odd filename"),
+    ]
 
-# -- .metadata.filetype --------------------------------------------------------------------------
 
+def test_partition_email_can_process_attachments():
+    elements = partition_email(
+        example_doc_path("eml/fake-email-attachment.eml"), process_attachments=True
+    )
 
-def test_partition_email_gets_the_EMAIL_mime_type_in_metadata_filetype():
-    EMAIL_MIME_TYPE = "message/rfc822"
-    elements = partition_email(example_doc_path("fake-email.eml"))
-    assert all(e.metadata.filetype == EMAIL_MIME_TYPE for e in elements), (
-        f"Expected all elements to have '{EMAIL_MIME_TYPE}' as their filetype, but got:"
-        f" {repr(elements[0].metadata.filetype)}"
+    assert elements == [
+        Title("Hello!"),
+        NarrativeText("Here's the attachments!"),
+        NarrativeText("It includes:"),
+        ListItem("Lots of whitespace"),
+        ListItem("Little to no content"),
+        ListItem("and is a quick read"),
+        Text("Best,"),
+        Title("Mallori"),
+        NarrativeText("Hey this is a fake attachment!"),
+    ]
+    assert all(e.metadata.last_modified == "2022-12-23T18:08:48+00:00" for e in elements)
+    attachment_element = elements[-1]
+    assert attachment_element.text == "Hey this is a fake attachment!"
+    assert attachment_element.metadata.filename == "fake-attachment.txt"
+    assert attachment_element.metadata.attached_to_filename == "fake-email-attachment.eml"
+
+
+def test_partition_email_silently_skips_attachments_it_cannot_partition():
+    elements = partition_email(
+        example_doc_path("eml/mime-attach-mp3.eml"), process_attachments=True
     )
 
+    # -- no exception is raised --
+    assert elements == [
+        # -- the email body is partitioned --
+        NarrativeText("This is an email with an MP3 attachment."),
+        # -- no elements appear for the attachment --
+    ]
 
-# -- .metadata.last_modified ---------------------------------------------------------------------
 
+# ================================================================================================
+# ISOLATED UNIT TESTS
+# ================================================================================================
 
-def test_partition_email_metadata_date_from_header(mocker: MockFixture):
-    mocker.patch("unstructured.partition.email.get_last_modified_date", return_value=None)
 
-    elements = partition_email(example_doc_path("eml/fake-email-attachment.eml"))
+class DescribeEmailPartitionerOptions:
+    """Unit-test suite for `unstructured.partition.email.EmailPartitioningContext` objects."""
 
-    assert elements[0].metadata.last_modified == "2022-12-23T12:08:48-06:00"
+    # -- .load() ---------------------------------
 
+    def it_provides_a_validating_constructor(self, ctx_args: dict[str, Any]):
+        ctx_args["file_path"] = example_doc_path("eml/fake-email.eml")
 
-def test_partition_email_from_file_custom_metadata_date():
-    with open(example_doc_path("eml/fake-email-attachment.eml"), "rb") as f:
-        elements = partition_email(file=f, metadata_last_modified="2020-07-05T09:24:28")
+        ctx = EmailPartitioningContext.load(**ctx_args)
 
-    assert elements[0].metadata.last_modified == "2020-07-05T09:24:28"
+        assert isinstance(ctx, EmailPartitioningContext)
 
+    def but_it_raises_when_no_source_document_was_specified(self, ctx_args: dict[str, Any]):
+        with pytest.raises(ValueError, match="no document specified; either a `filename` or `fi"):
+            EmailPartitioningContext.load(**ctx_args)
 
-def test_partition_email_custom_metadata_date():
-    elements = partition_email(
-        example_doc_path("eml/fake-email-attachment.eml"),
-        metadata_last_modified="2020-07-05T09:24:28",
-    )
+    def and_it_raises_when_a_file_open_for_reading_str_is_used(self, ctx_args: dict[str, Any]):
+        ctx_args["file"] = io.StringIO("abcdefg")
+        with pytest.raises(ValueError, match="file object must be opened in binary mode"):
+            EmailPartitioningContext.load(**ctx_args)
 
-    assert elements[0].metadata.last_modified == "2020-07-05T09:24:28"
+    def and_it_raises_when_an_invalid_content_source_is_specified(self, ctx_args: dict[str, Any]):
+        ctx_args["file_path"] = example_doc_path("eml/fake-email.eml")
+        ctx_args["content_source"] = "application/json"
 
+        with pytest.raises(ValueError, match="'application/json' is not a valid value for conte"):
+            EmailPartitioningContext.load(**ctx_args)
 
-# ------------------------------------------------------------------------------------------------
+    # -- .bcc_addresses --------------------------
 
+    def it_provides_access_to_the_Bcc_addresses_when_present(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-multi-to-cc-bcc.eml"))
+        assert ctx.bcc_addresses == ["John <john@example.com>", "Mary <mary@example.com>"]
 
-def test_partition_eml_add_signature_to_metadata():
-    elements = partition_email(example_doc_path("eml/signed-doc.p7s"))
+    def but_it_returns_None_when_there_are_no_Bcc_addresses(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/simple-rfc-822.eml"))
+        assert ctx.bcc_addresses is None
 
-    assert len(elements) == 1
-    assert elements[0].text == "This is a test"
-    assert elements[0].metadata.signature == "<SIGNATURE>\n"
+    # -- .body_part ------------------------------
 
+    def it_returns_the_html_body_part_when_there_is_one_by_default(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-different-plain-html.eml"))
 
-# -- attachment behaviors ------------------------------------------------------------------------
+        body_part = ctx.body_part
 
+        assert isinstance(body_part, EmailMessage)
+        content = body_part.get_content()
+        assert isinstance(content, str)
+        assert content.startswith("<!DOCTYPE html>")
 
-def test_extract_attachment_info():
-    with open(example_doc_path("eml/fake-email-attachment.eml")) as f:
-        msg = email.message_from_file(f, policy=policy.default)
-        msg = cast(EmailMessage, msg)
-    attachment_info = _extract_attachment_info(msg)
+    def but_it_returns_the_plain_text_body_part_when_there_is_one_when_so_requested(self):
+        ctx = EmailPartitioningContext(
+            example_doc_path("eml/mime-different-plain-html.eml"), content_source="text/plain"
+        )
 
-    assert len(attachment_info) > 0
-    assert attachment_info == ATTACH_EXPECTED_OUTPUT
+        body_part = ctx.body_part
 
+        assert isinstance(body_part, EmailMessage)
+        content = body_part.get_content()
+        assert isinstance(content, str)
+        assert content.startswith("This is the text/plain part.")
 
-def test_partition_email_odd_attachment_filename():
-    elements = partition_email(
-        example_doc_path("eml/email-equals-attachment-filename.eml"),
-        process_attachments=True,
-        attachment_partitioner=partition_text,
-    )
+    def and_it_returns_None_when_the_email_has_no_body(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-no-body.eml"))
+        assert ctx.body_part is None
 
-    assert elements[1].metadata.filename == "odd=file=name.txt"
+    # -- .cc_addresses ---------------------------
 
+    def it_provides_access_to_the_Cc_addresses_when_present(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-multi-to-cc-bcc.eml"))
+        assert ctx.cc_addresses == ["Tom <tom@example.com>", "Alice <alice@example.com>"]
 
-def test_partition_email_can_process_attachments(tmp_path: pathlib.Path):
-    output_dir = tmp_path / "output"
-    output_dir.mkdir()
-    filename = example_doc_path("eml/fake-email-attachment.eml")
-    with open(filename) as f:
-        msg = email.message_from_file(f, policy=policy.default)
-        msg = cast(EmailMessage, msg)
-    _extract_attachment_info(msg, output_dir=str(output_dir))
+    def but_it_returns_None_when_there_are_no_Cc_addresses(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/simple-rfc-822.eml"))
+        assert ctx.cc_addresses is None
 
-    attachment_filename = os.path.join(
-        output_dir,
-        str(ATTACH_EXPECTED_OUTPUT[0]["filename"]),
+    # -- .content_type_preference ----------------
+
+    @pytest.mark.parametrize(
+        ("content_source", "expected_value"),
+        [
+            ("text/html", ("html", "plain")),
+            ("text/plain", ("plain", "html")),
+        ],
     )
+    def it_knows_whether_the_caller_prefers_the_HTML_or_plain_text_body(
+        self, content_source: str, expected_value: tuple[str, ...]
+    ):
+        ctx = EmailPartitioningContext(content_source=content_source)
+        assert ctx.content_type_preference == expected_value
 
-    mocked_last_modification_date = "0000-00-05T09:24:28"
+    def and_it_defaults_to_preferring_the_HTML_body(self):
+        ctx = EmailPartitioningContext()
+        assert ctx.content_type_preference == ("html", "plain")
 
-    attachment_elements = partition_text(
-        filename=attachment_filename,
-        metadata_filename=attachment_filename,
-        metadata_last_modified=mocked_last_modification_date,
-    )
-    expected_metadata = attachment_elements[0].metadata
-    expected_metadata.file_directory = None
-    expected_metadata.attached_to_filename = filename
+    # -- .from -----------------------------------
 
-    elements = partition_email(
-        filename=filename,
-        attachment_partitioner=partition_text,
-        process_attachments=True,
-        metadata_last_modified=mocked_last_modification_date,
-    )
+    def it_knows_the_From_address_of_the_email(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-simple.eml"))
+        assert ctx.from_address == "sender@example.com"
 
-    # This test does not need to validate if hierarchy is working
-    # Patch to nullify parent_id
-    expected_metadata.parent_id = None
-    elements[-1].metadata.parent_id = None
+    # -- .message_id -----------------------------
 
-    assert [a.name for a in os.scandir(output_dir) if a.is_file()] == ["fake-attachment.txt"]
-    assert elements[0].text.startswith("Hello!")
-    for element in elements[:-1]:
-        assert element.metadata.filename == "fake-email-attachment.eml"
-        assert element.metadata.subject == "Fake email with attachment"
-    assert elements[-1].text == "Hey this is a fake attachment!"
-    assert elements[-1].metadata == expected_metadata
+    def it_provides_access_to_the_Message_ID_when_present(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-simple.eml"))
+        assert ctx.message_id == "1234567890@example.com"
 
+    def but_it_returns_None_when_there_is_no_Message_ID_header(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/simple-rfc-822.eml"))
+        assert ctx.message_id is None
 
-# -- language behaviors --------------------------------------------------------------------------
+    # -- .metadata_file_path ---------------------
 
+    def it_uses_the_metadata_file_path_arg_value_when_one_was_provided(self):
+        ctx = EmailPartitioningContext(metadata_file_path="a/b/c.eml")
+        assert ctx.metadata_file_path == "a/b/c.eml"
 
-def test_partition_email_element_metadata_has_languages():
-    elements = partition_email(example_doc_path("eml/fake-email.eml"))
+    def and_it_uses_the_file_path_arg_value_when_metadata_file_path_was_not_provided(self):
+        ctx = EmailPartitioningContext(file_path="x/y/z.eml")
+        assert ctx.metadata_file_path == "x/y/z.eml"
 
-    assert elements[0].metadata.languages == ["eng"]
+    def and_it_returns_None_when_neither_file_path_was_provided(self):
+        ctx = EmailPartitioningContext()
+        assert ctx.metadata_file_path is None
 
+    # -- .metadata_last_modified -----------------
 
-def test_partition_email_respects_languages_arg():
-    elements = partition_email(example_doc_path("eml/fake-email.eml"), languages=["deu"])
+    def it_uses_the_metadata_last_modified_arg_value_when_one_was_provided(self):
+        metadata_last_modified = "2023-04-08T12:18:07"
+        ctx = EmailPartitioningContext(metadata_last_modified=metadata_last_modified)
+        assert ctx.metadata_last_modified == metadata_last_modified
 
-    assert all(element.metadata.languages == ["deu"] for element in elements)
+    def and_it_uses_the_msg_Date_header_date_when_metadata_last_modified_was_not_provided(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/simple-rfc-822.eml"))
+        assert ctx.metadata_last_modified == "2024-10-01T17:34:56+00:00"
 
+    def and_it_falls_back_to_filesystem_last_modified_when_no_Date_header_is_present(
+        self, get_last_modified_date_: Mock
+    ):
+        """Not an expected case as according to RFC 5322, the Date header is required."""
+        filesystem_last_modified = "2024-07-09T14:08:17"
+        get_last_modified_date_.return_value = filesystem_last_modified
 
-def test_partition_eml_respects_detect_language_per_element():
-    elements = partition_email(
-        example_doc_path("language-docs/eng_spa_mult.eml"),
-        detect_language_per_element=True,
-    )
-    # languages other than English and Spanish are detected by this partitioner,
-    # so this test is slightly different from the other partition tests
-    langs = {e.metadata.languages[0] for e in elements if e.metadata.languages is not None}
+        ctx = EmailPartitioningContext(example_doc_path("eml/rfc822-no-date.eml"))
 
-    assert "eng" in langs
-    assert "spa" in langs
+        assert ctx.metadata_last_modified == filesystem_last_modified
+
+    def and_it_returns_None_when_no_last_modified_is_available(self):
+        with open(example_doc_path("eml/rfc822-no-date.eml"), "rb") as f:
+            ctx = EmailPartitioningContext(file=f)
+            assert ctx.metadata_last_modified is None
+
+    # -- .msg ------------------------------------
+
+    def it_loads_the_email_message_from_the_filesystem_when_a_path_is_provided(self):
+        ctx = EmailPartitioningContext(file_path=example_doc_path("eml/simple-rfc-822.eml"))
+        assert isinstance(ctx.msg, EmailMessage)
+
+    def and_it_loads_the_email_message_from_a_file_like_object_when_one_is_provided(self):
+        with open(example_doc_path("eml/simple-rfc-822.eml"), "rb") as f:
+            ctx = EmailPartitioningContext(file=f)
+            assert isinstance(ctx.msg, EmailMessage)
+
+    # -- .partitioning_kwargs --------------------
+
+    def it_passes_along_the_kwargs_it_received_on_construction(self):
+        kwargs = {"foo": "bar", "baz": "qux"}
+        ctx = EmailPartitioningContext(kwargs=kwargs)
+
+        assert ctx.partitioning_kwargs == kwargs
+
+    # -- .process_attachments --------------------
+
+    @pytest.mark.parametrize("process_attachments", [True, False])
+    def it_knows_whether_the_caller_wants_to_also_partition_attachments(
+        self, process_attachments: bool
+    ):
+        ctx = EmailPartitioningContext(process_attachments=process_attachments)
+        assert ctx.process_attachments == process_attachments
+
+    def but_by_default_it_ignores_attachments(self):
+        ctx = EmailPartitioningContext()
+        assert ctx.process_attachments is False
+
+    # -- .subject --------------------------------
+
+    def it_provides_access_to_the_email_Subject_as_a_string(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-word-encoded-subject.eml"))
+        assert ctx.subject == "Simple email with ☸☿ Unicode subject"
+
+    def but_it_returns_None_when_there_is_no_Subject_header(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-no-subject.eml"))
+        assert ctx.subject is None
+
+    # -- .to_addresses ---------------------------
+
+    def it_provides_access_to_the_To_addresses_when_present(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-multi-to-cc-bcc.eml"))
+        assert ctx.to_addresses == ["Bob <bob@example.com>", "Sue <sue@example.com>"]
+
+    def but_it_returns_None_when_there_are_no_To_addresses(self):
+        ctx = EmailPartitioningContext(example_doc_path("eml/mime-no-to.eml"))
+        assert ctx.to_addresses is None
+
+    # -- fixtures --------------------------------------------------------------------------------
+
+    @pytest.fixture()
+    def ctx_args(self) -> dict[str, Any]:
+        return {
+            "file_path": None,
+            "file": None,
+            "content_source": "text/html",
+            "metadata_file_path": None,
+            "metadata_last_modified": None,
+            "process_attachments": False,
+            "kwargs": {},
+        }
+
+    @pytest.fixture()
+    def get_last_modified_date_(self, request: FixtureRequest) -> Mock:
+        return function_mock(request, "unstructured.partition.email.get_last_modified_date")
diff --git a/test_unstructured/partition/test_msg.py b/test_unstructured/partition/test_msg.py
index 02fc11b404..43f49a0108 100644
--- a/test_unstructured/partition/test_msg.py
+++ b/test_unstructured/partition/test_msg.py
@@ -14,6 +14,7 @@
     Mock,
     assert_round_trips_through_JSON,
     example_doc_path,
+    function_mock,
     property_mock,
 )
 from unstructured.chunking.title import chunk_by_title
@@ -21,8 +22,10 @@
     ElementMetadata,
     ListItem,
     NarrativeText,
+    Text,
     Title,
 )
+from unstructured.partition.common import UnsupportedFileFormatError
 from unstructured.partition.msg import MsgPartitionerOptions, partition_msg
 
 EXPECTED_MSG_OUTPUT = [
@@ -113,6 +116,9 @@ def test_partition_msg_raises_with_neither():
         partition_msg()
 
 
+# -- attachments ---------------------------------------------------------------------------------
+
+
 def test_partition_msg_can_process_attachments():
     elements = partition_msg(
         example_doc_path("fake-email-multiple-attachments.msg"), process_attachments=True
@@ -155,6 +161,27 @@ def test_partition_msg_can_process_attachments():
     ]
 
 
+def test_partition_msg_silently_skips_attachments_it_cannot_partition(request: FixtureRequest):
+    function_mock(
+        request, "unstructured.partition.auto.partition", side_effect=UnsupportedFileFormatError()
+    )
+
+    elements = partition_msg(
+        example_doc_path("fake-email-multiple-attachments.msg"), process_attachments=True
+    )
+
+    # -- no exception is raised --
+    assert elements == [
+        # -- the email body is partitioned --
+        NarrativeText("Here are those documents."),
+        Text("--"),
+        Title("Mallori Harrell"),
+        Title("Unstructured Technologies"),
+        Title("Data Scientist"),
+        # -- no elements appear for the attachment(s) --
+    ]
+
+
 # -- .metadata.filename --------------------------------------------------------------------------
 
 
diff --git a/test_unstructured_ingest/expected-structured-output/outlook/21be155fb0c95885.eml.json b/test_unstructured_ingest/expected-structured-output/outlook/21be155fb0c95885.eml.json
index 4304e214b3..2301c0f2e8 100644
--- a/test_unstructured_ingest/expected-structured-output/outlook/21be155fb0c95885.eml.json
+++ b/test_unstructured_ingest/expected-structured-output/outlook/21be155fb0c95885.eml.json
@@ -1,33 +1,33 @@
 [
   {
-    "element_id": "e482ff3e97d6318a4c0e00aea0adf544",
+    "type": "Title",
+    "element_id": "df08d0aeb11a34e75766d2d2008d73a6",
+    "text": "integration test email",
     "metadata": {
-      "data_source": {
-        "date_created": "2023-07-15T15:36:08",
-        "date_modified": "2023-07-15T15:38:57",
-        "record_locator": {
-          "message_id": "AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATaI_sAADZYn-lfnvLSqIcW-YsN8ebAAATaJ9PAAA=",
-          "user_email": "devops@unstructuredio.onmicrosoft.com"
-        },
-        "url": "https://outlook.office365.com/owa/?ItemID=AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn%2FlfnvLSqIcW%2FYsN8ebAAATaI%2BsAADZYn%2FlfnvLSqIcW%2FYsN8ebAAATaJ9PAAA%3D&exvsurl=1&viewmodel=ReadMessageItem",
-        "version": "CQAAABYAAADZYn/lfnvLSqIcW/YsN8ebAAATYGBM"
-      },
-      "email_message_id": "CAOvAh-6yWG99vvaoQ5niLgGTgpwe90LGiNPLvx7bAY3ZFyq54w@mail.gmail.com",
-      "filename": "21be155fb0c95885.eml",
-      "filetype": "message/rfc822",
       "languages": [
         "eng"
       ],
-      "last_modified": "2023-07-15T08:35:51-07:00",
+      "filename": "21be155fb0c95885.eml",
+      "filetype": "message/rfc822",
+      "last_modified": "2023-07-15T15:35:51+00:00",
+      "email_message_id": "CAOvAh-6yWG99vvaoQ5niLgGTgpwe90LGiNPLvx7bAY3ZFyq54w@mail.gmail.com",
       "sent_from": [
         "David Potter <potterdavidm@gmail.com>"
       ],
       "sent_to": [
         "devops@unstructuredio.onmicrosoft.com"
       ],
-      "subject": "integration test email 1"
-    },
-    "text": "integration test email",
-    "type": "Title"
+      "subject": "integration test email 1",
+      "data_source": {
+        "url": "https://graph.microsoft.com/v1.0/users/devops@unstructuredio.onmicrosoft.com/mailFolders/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MAAuAAAAAADc1MfJYetSQ6QZntYrI9k4AQDZYn-lfnvLSqIcW-YsN8ebAAATaI_sAAA=/messages/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATaI_sAADZYn-lfnvLSqIcW-YsN8ebAAATaJ9PAAA=",
+        "record_locator": {
+          "message_id": "AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATaI_sAADZYn-lfnvLSqIcW-YsN8ebAAATaJ9PAAA=",
+          "user_email": "devops@unstructuredio.onmicrosoft.com"
+        },
+        "date_created": "1689435368.0",
+        "date_modified": "1689435537.0",
+        "filesize_bytes": 9189
+      }
+    }
   }
 ]
\ No newline at end of file
diff --git a/test_unstructured_ingest/expected-structured-output/outlook/497eba8c81c801c6.eml.json b/test_unstructured_ingest/expected-structured-output/outlook/497eba8c81c801c6.eml.json
index bde3500e7c..d4beb7d76a 100644
--- a/test_unstructured_ingest/expected-structured-output/outlook/497eba8c81c801c6.eml.json
+++ b/test_unstructured_ingest/expected-structured-output/outlook/497eba8c81c801c6.eml.json
@@ -1,33 +1,33 @@
 [
   {
-    "element_id": "4a69e8fcddd4b6eff8488a34ba16b0dd",
+    "type": "NarrativeText",
+    "element_id": "e40af23706b4096145f1e4b007719aa5",
+    "text": "this is a message for the subfolder1_1",
     "metadata": {
-      "data_source": {
-        "date_created": "2023-07-25T01:26:22",
-        "date_modified": "2023-07-25T01:26:41",
-        "record_locator": {
-          "message_id": "AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATzq5tAADZYn-lfnvLSqIcW-YsN8ebAAAZT8XfAAA=",
-          "user_email": "devops@unstructuredio.onmicrosoft.com"
-        },
-        "url": "https://outlook.office365.com/owa/?ItemID=AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn%2FlfnvLSqIcW%2FYsN8ebAAATzq5tAADZYn%2FlfnvLSqIcW%2FYsN8ebAAAZT8XfAAA%3D&exvsurl=1&viewmodel=ReadMessageItem",
-        "version": "CQAAABYAAADZYn/lfnvLSqIcW/YsN8ebAAAZRQ8Y"
-      },
-      "email_message_id": "CAL=c59DZsEqq49DgVLQy=6v_WnxmkGfznjOoaGqqJb6VK-Mu=g@mail.gmail.com",
-      "filename": "497eba8c81c801c6.eml",
-      "filetype": "message/rfc822",
       "languages": [
         "eng"
       ],
-      "last_modified": "2023-07-24T18:25:52-07:00",
+      "filename": "497eba8c81c801c6.eml",
+      "filetype": "message/rfc822",
+      "last_modified": "2023-07-25T01:25:52+00:00",
+      "email_message_id": "CAL=c59DZsEqq49DgVLQy=6v_WnxmkGfznjOoaGqqJb6VK-Mu=g@mail.gmail.com",
       "sent_from": [
         "Ryan Nikolaidis <ryan@unstructured.io>"
       ],
       "sent_to": [
         "devops@unstructuredio.onmicrosoft.com"
       ],
-      "subject": "subfolder1_1"
-    },
-    "text": "this is a message for the subfolder1_1",
-    "type": "NarrativeText"
+      "subject": "subfolder1_1",
+      "data_source": {
+        "url": "https://graph.microsoft.com/v1.0/users/devops@unstructuredio.onmicrosoft.com/mailFolders/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MAAuAAAAAADc1MfJYetSQ6QZntYrI9k4AQDZYn-lfnvLSqIcW-YsN8ebAAATaI_sAAA=/childFolders/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MAAuAAAAAADc1MfJYetSQ6QZntYrI9k4AQDZYn-lfnvLSqIcW-YsN8ebAAATzq5sAAA=/childFolders/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MAAuAAAAAADc1MfJYetSQ6QZntYrI9k4AQDZYn-lfnvLSqIcW-YsN8ebAAATzq5tAAA=/messages/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATzq5tAADZYn-lfnvLSqIcW-YsN8ebAAAZT8XfAAA=",
+        "record_locator": {
+          "message_id": "AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATzq5tAADZYn-lfnvLSqIcW-YsN8ebAAAZT8XfAAA=",
+          "user_email": "devops@unstructuredio.onmicrosoft.com"
+        },
+        "date_created": "1690248382.0",
+        "date_modified": "1690248401.0",
+        "filesize_bytes": 9207
+      }
+    }
   }
 ]
\ No newline at end of file
diff --git a/test_unstructured_ingest/expected-structured-output/outlook/4a16a411f162ebbb.eml.json b/test_unstructured_ingest/expected-structured-output/outlook/4a16a411f162ebbb.eml.json
index 0bbcb8fd81..8906138fd6 100644
--- a/test_unstructured_ingest/expected-structured-output/outlook/4a16a411f162ebbb.eml.json
+++ b/test_unstructured_ingest/expected-structured-output/outlook/4a16a411f162ebbb.eml.json
@@ -1,33 +1,33 @@
 [
   {
-    "element_id": "4df3eedf1b6f98566fc40a132b48205f",
+    "type": "NarrativeText",
+    "element_id": "8488a63070421b09a14ad6078c2cec2a",
+    "text": "this is a message for the subfolder",
     "metadata": {
-      "data_source": {
-        "date_created": "2023-07-10T03:39:04",
-        "date_modified": "2023-07-15T22:36:12",
-        "record_locator": {
-          "message_id": "AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATzq5sAADZYn-lfnvLSqIcW-YsN8ebAAATzrolAAA=",
-          "user_email": "devops@unstructuredio.onmicrosoft.com"
-        },
-        "url": "https://outlook.office365.com/owa/?ItemID=AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn%2FlfnvLSqIcW%2FYsN8ebAAATzq5sAADZYn%2FlfnvLSqIcW%2FYsN8ebAAATzrolAAA%3D&exvsurl=1&viewmodel=ReadMessageItem",
-        "version": "CQAAABYAAADZYn/lfnvLSqIcW/YsN8ebAAATxicu"
-      },
-      "email_message_id": "CAOvAh-7KVeFHwtX20KVL=S4WgpWN91YzK11td4_W0Pv3cJ4jLQ@mail.gmail.com",
-      "filename": "4a16a411f162ebbb.eml",
-      "filetype": "message/rfc822",
       "languages": [
         "eng"
       ],
-      "last_modified": "2023-07-09T20:38:47-07:00",
+      "filename": "4a16a411f162ebbb.eml",
+      "filetype": "message/rfc822",
+      "last_modified": "2023-07-10T03:38:47+00:00",
+      "email_message_id": "CAOvAh-7KVeFHwtX20KVL=S4WgpWN91YzK11td4_W0Pv3cJ4jLQ@mail.gmail.com",
       "sent_from": [
         "David Potter <potterdavidm@gmail.com>"
       ],
       "sent_to": [
         "devops@unstructuredio.onmicrosoft.com"
       ],
-      "subject": "message for subfolder"
-    },
-    "text": "this is a message for the subfolder",
-    "type": "NarrativeText"
+      "subject": "message for subfolder",
+      "data_source": {
+        "url": "https://graph.microsoft.com/v1.0/users/devops@unstructuredio.onmicrosoft.com/mailFolders/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MAAuAAAAAADc1MfJYetSQ6QZntYrI9k4AQDZYn-lfnvLSqIcW-YsN8ebAAATaI_sAAA=/childFolders/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MAAuAAAAAADc1MfJYetSQ6QZntYrI9k4AQDZYn-lfnvLSqIcW-YsN8ebAAATzq5sAAA=/messages/AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATzq5sAADZYn-lfnvLSqIcW-YsN8ebAAATzrolAAA=",
+        "record_locator": {
+          "message_id": "AAMkAGE2MmEwNzFlLWVjYzAtNDNhZS04ZGM1LTFjYmMzZDhiMmI0MABGAAAAAADc1MfJYetSQ6QZntYrI9k4BwDZYn-lfnvLSqIcW-YsN8ebAAATzq5sAADZYn-lfnvLSqIcW-YsN8ebAAATzrolAAA=",
+          "user_email": "devops@unstructuredio.onmicrosoft.com"
+        },
+        "date_created": "1688960344.0",
+        "date_modified": "1689460572.0",
+        "filesize_bytes": 9254
+      }
+    }
   }
 ]
\ No newline at end of file
diff --git a/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErPIAU.eml.json b/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErPIAU.eml.json
index afbddc0989..d2aafacb85 100644
--- a/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErPIAU.eml.json
+++ b/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErPIAU.eml.json
@@ -1,7 +1,7 @@
 [
   {
     "type": "NarrativeText",
-    "element_id": "191e99ff4061730e85d9300183b4ccbe",
+    "element_id": "4196fe41da19e8657761ecffcafd3d2f",
     "text": "Jane. This is a test of sending you an email from Salesforce! _____________________________________________________________________ Powered by Salesforce http://www.salesforce.com/",
     "metadata": {
       "languages": [
diff --git a/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErQIAU.eml.json b/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErQIAU.eml.json
index 9fa9682805..44ea5eb7f8 100644
--- a/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErQIAU.eml.json
+++ b/test_unstructured_ingest/expected-structured-output/salesforce/EmailMessage/02sHu00001efErQIAU.eml.json
@@ -1,7 +1,7 @@
 [
   {
     "type": "NarrativeText",
-    "element_id": "f7d72e773a4c72747c88d8ea6e5d012a",
+    "element_id": "6f168cd430b41fc0d66a3691ef3caa0f",
     "text": "Hey Sean. Testing email parsing here. Type: email Just testing the email system _____________________________________________________________________ Powered by Salesforce http://www.salesforce.com/",
     "metadata": {
       "languages": [