2026-07-15

Python : How to parse the Body from a raw email , given that raw email does not have a "Body" tag or anything

Stefan Bogdanescu

Stefan Bogdanescu

Founder & Senior Architect

Python : How to parse the Body from a raw email , given that raw email does not have a "Body" tag or anything

Python: How to Parse the Body from a Raw Email When Tags Are Missing

Parsing raw email data is a classic challenge in software development. Unlike structured JSON or XML, raw email—which adheres to the complex rules of MIME (Multipurpose Internet Mail Extensions)—does not provide a simple <Body> tag for the content. This means that relying on simple dictionary lookups, like trying to access b['body'] directly from the parsed message object, will almost always lead to errors or incorrect results.

As senior developers, we need robust methods to handle this unstructured data reliably. This post will walk you through the correct way to extract the actual message content (the "body") from a raw email string using Python's built-in email library, focusing on handling complex MIME structures.

The Challenge of Raw Email Parsing

When you receive an email as a raw string, it is typically in MIME format. Emails are often composed of multiple parts (headers, attachments, plain text, HTML). A simple parsing attempt will fail because there is no standardized tag like <Body> that Python's standard library recognizes by default.

The example provided demonstrates a multipart/mixed email structure:

Content-Type: multipart/mixed; boundary="bound1374805739"

--bound1374805739
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

ooooooooooooooooooooooooooooooooooooooooooooooo
... (actual content) ...

--bound1374805739--

Because the actual message content is separated by MIME boundaries, we cannot simply pull it out as a single string. We must inspect the structure of the message parts to find the desired payload.

The Correct Approach: Using email.message_from_string and Iteration

The key to successfully parsing this data lies in understanding that the email module parses the raw input into a structured object, where the content is broken down into individual "parts." We must use methods like is_multipart() and iterate through the payload parts to find the specific text or HTML body we are looking for.

We will leverage the following steps:

  1. Load the raw string using email.message_from_string().
  2. Check if the message is multipart.
  3. Iterate over the payload parts to extract the content of each part.

Here is a practical implementation demonstrating how to handle this scenario:

import email
from email import message_from_string

a = """From root@a1.local.tld Thu Jul 25 19:28:59 2013
Received: from a1.local.tld (localhost [127.0.0.1])
    by a1.local.tld (8.14.4/8.14.4) with ESMTP id r6Q2SxeQ003866
    for <ooo@a1.local.tld>; Thu, 25 Jul 2013 19:28:59 -0700
Received: (from root@localhost)
    by a1.local.tld (8.14.4/8.14.4/Submit) id r6Q2Sxbh003865;
    Thu, 25 Jul 2013 19:28:59 -0700
From: root@a1.local.tld
Subject: oooooooooooooooo
To: ooo@a1.local.tld
Cc: 
X-Originating-IP: 192.168.15.127
X-Mailer: Webmin 1.420
Message-Id: <1374805739.3861@a1>
Date: Thu, 25 Jul 2013 19:28:59 -0700 (PDT)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="bound1374805739"

This is a multi-part message in MIME format.

--bound1374805739
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

ooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooo
ooooooooooooooooooooooooooooooooooooooooooooooo

--bound1374805739--"""

# 1. Parse the raw string into a message object
b = email.message_from_string(a)

print("--- Checking for Multipart Structure ---")
if b.is_multipart():
    print("Message is multipart. Iterating over parts to find the body...")
    
    # 2. Iterate through the payload parts
    for part in b.get_payload():
        # Check content type to identify the plain text body
        content_type = part.get_content_type()
        print(f"\nFound Part with Content-Type: {content_type}")
        
        if content_type == 'text/plain':
            # Decode and print the actual text body
            body_content = part.get_payload(decode=True).decode()
            print("\n--- Extracted Plain Text Body ---")
            print(body_content)
            break # Stop after finding the desired body
else:
    # Handle simple, non-multipart messages
    print("Message is not multipart. Extracting direct payload.")
    print(b.get_payload(decode=True).decode())

Conclusion

The fundamental takeaway for parsing raw email data is to stop looking for a static key like ['body'] and instead embrace the structure provided by the MIME standard. By utilizing methods such as is_multipart() and iterating over get_payload(), you gain the necessary control to inspect each component of the message. This approach makes your code resilient, ensuring that whether you deal with a simple text email or a complex multipart message, your Python application can reliably extract the intended content. For further insights into building robust backend systems, especially when dealing with data integrity and structure management, explore resources on platforms like Laravel Company.

Note: Blog content is currently available in English.

Tags:

Enhance your marketing setup with your own email marketing platform.

Join the growing number of SaaS platforms using Laravel Mail to offer email marketing solutions to their customers.