---
title: "Multipart/alternative email: structure, order and parsing"
description: "How a multipart/alternative email bundles plain text and HTML, why part order matters, how attachments nest, and how to parse it reliably in code or an agent."
canonical: "https://myagent.mx/blog/multipart-alternative-email"
publishedAt: "2026-10-25T00:00:00.000Z"
updatedAt: "2026-10-26T23:15:31.498Z"
category: "apis"
topic: "multipart alternative email"
author: "Roshan Jonnalagadda"
authorProfile: "https://myagent.mx/blog/author/roshan-jonnalagadda"
keywords:
  - "multipart alternative email"
---

# Multipart/alternative email: structure, order and parsing

How a multipart/alternative email bundles plain text and HTML, why part order matters, how attachments nest, and how to parse it reliably in code or an agent.

![Engineer inspecting multipart email source](/images/blog/multipart-alternative-email/hero.svg)

A multipart/alternative email is one message that carries the same content in more than one format, usually plain text and HTML, so that each mail client can show the version it handles best. The container is a MIME structure defined in [RFC 2046](https://www.rfc-editor.org/info/rfc2046/). The rule that trips most people up is order: the plainest part goes first and the richest part goes last.

This guide covers what the structure looks like on the wire, how to build it, where attachments and inline images belong, and how to read it safely when the reader is software rather than a person. That last part matters more every year, because AI agents now open a lot of mail.

## TL;DR

- `multipart/alternative` holds several versions of the *same* content. The client picks one. It never shows them all.
- Put `text/plain` first and `text/html` last. [RFC 2046](https://www.rfc-editor.org/info/rfc2046/) orders parts by increasing faithfulness to the original, and receivers should pick the last format they can render.
- Attachments do not belong inside the alternative container. Wrap it in `multipart/mixed`, and use `multipart/related` for inline images.
- When you read mail programmatically, walk the whole MIME tree. Do not assume every message is multipart/alternative, and do not trust a flat "body" field blindly.

## Table of Contents

- [What multipart/alternative actually is](#what-multipartalternative-actually-is)
- [Anatomy of the message](#anatomy-of-the-message)
- [Why part order matters](#why-part-order-matters)
- [Attachments and inline images: wrap, don't stuff](#attachments-and-inline-images-wrap-dont-stuff)
- [Building one in code](#building-one-in-code)
- [Reading multipart/alternative safely](#reading-multipartalternative-safely)
- [Common mistakes and how to spot them](#common-mistakes-and-how-to-spot-them)
- [Our view: treat the MIME tree as data, not as a string](#our-view-treat-the-mime-tree-as-data-not-as-a-string)
- [Give your agent an inbox to test against](#give-your-agent-an-inbox-to-test-against)
- [FAQ](#faq)
- [Sources](#sources)

## What multipart/alternative actually is

MIME (Multipurpose Internet Mail Extensions) lets an email carry more than a single block of ASCII text. One of its composite types is `multipart`, which holds several body parts inside a single message. The `alternative` subtype has a narrow meaning: every part is a different representation of the same information. Microsoft's Exchange team put it plainly in an article on MIME structures: it [groups a number of different formats of the same data and lets the client decide which one to show](https://techcommunity.microsoft.com/blog/exchange/mixed-ing-it-up-multipartmixed-messages-and-you/585841).

That is different from `multipart/mixed`, where the parts are independent things (a message body plus a PDF, say). With alternative, a reader sees either the text or the HTML, never both. The Exchange documentation on the Content-Type header) describes the same idea: one piece of information, presented in different body parts in different forms.

Why bother sending two versions?

- Some clients and devices render only text, and screen readers and terminal clients often work better with it.
- Some spam filters treat HTML-only mail with suspicion.
- Preview panes, notification summaries and smartwatch displays often draw on the plain part.
- Software that reads mail, including AI agents, usually finds plain text far easier to reason about than a tangle of nested tables.

## Anatomy of the message

The container is announced in the top-level header. According to the same RFC, the header takes the form `Content-Type: multipart/alternative; boundary=[boundary_string]`. Each part begins with the boundary line, carries its own headers, then its content. The structure closes with the boundary followed by two trailing hyphens.

A minimal example looks like this:

```
MIME-Version: 1.0
From: Alex <alex@example.com>
To: Sam <sam@example.net>
Subject: Your booking is confirmed
Content-Type: multipart/alternative; boundary="BOUNDARY-1"

--BOUNDARY-1
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit

Hi Sam, your booking for Tuesday 3 November is confirmed.

--BOUNDARY-1
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: 7bit

<html><body><p>Hi Sam, your booking for <strong>Tuesday 3 November</strong> is confirmed.</p></body></html>

--BOUNDARY-1--
```

Three details worth checking whenever you build one by hand:

1. **The boundary must not appear in the content.** Pick a long random string.
2. **Each part has its own `Content-Type` and charset.** Declare UTF-8 explicitly so non-ASCII characters survive.
3. **The closing boundary is required.** Without the trailing `--`, some parsers will treat the final part as truncated.

## Why part order matters

This is the single most common mistake. [RFC 2046](https://www.rfc-editor.org/info/rfc2046/) says parts within a multipart/alternative container are ordered by increasing faithfulness to the original content. The simplest form comes first and the richest form comes last. A receiving agent should pick the last format it can render.

In practice that means:

- `text/plain` first.
- `text/html` last.
- If you add something richer still, such as `text/calendar` for an invitation, it goes in the position that reflects its faithfulness to the original.

Get it backwards and a client that follows the standard will show the plain text and ignore your HTML. Designers then report that "the email looks broken" when the real problem is two parts swapped in the wrong order.

## Attachments and inline images: wrap, don't stuff

The alternative container is for body variants only. A well-known question on [multipart/alternative with attachments](https://stackoverflow.com/questions/18680337/multipart-alternative-with-attachments) comes down to this: the outer envelope is `multipart/mixed`, with the text/HTML pair as its first part and each attachment as a sibling. Inline images referenced from the HTML go in `multipart/related`, as [this answer on combining HTML, images and plain text](https://stackoverflow.com/questions/10631856/mime-type-to-satisfy-html-email-images-and-plain-text) explains, citing RFC 2387.

| Need | Container | Contains |
|---|---|---|
| Plain text and HTML only | `multipart/alternative` | `text/plain`, `text/html` |
| Body plus attachments | `multipart/mixed` | the body, then each attachment |
| HTML with inline images | `multipart/related` | `text/html`, then the images |
| All three | `multipart/mixed` > `multipart/alternative` > `text/plain` + `multipart/related` > `text/html` + images | |

The fully loaded case nests like this:

```
multipart/mixed
├── multipart/alternative
│   ├── text/plain
│   └── multipart/related
│       ├── text/html
│       └── image/png (Content-ID: logo)
└── application/pdf (attachment)
```

Notice that `multipart/related` sits *inside* the alternative, as the last (richest) option. The plain version has no images to reference, so the images travel only with the HTML.

Multipart structures are recursive, which is why nesting works at all. Parsers must also recognise outer boundaries at any depth. The [RFC 2046 errata page](https://www.rfc-editor.org/rfc/inline-errata/rfc2046.html) notes that implementations are required to spot outer-level boundary markers at any level of inner nesting, not only the next expected one.

## Building one in code

Most languages have a library that does the nesting for you. Do not assemble boundaries by string concatenation if you can avoid it. Python's standard library is a good illustration: its documentation shows [how to create an HTML message with an alternative plain-text version](https://stackoverflow.com/questions/882712/send-html-emails-with-python) using `MIMEMultipart('alternative')`, attaching the plain part first and the HTML part second.

```python
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

msg = MIMEMultipart("alternative")
msg["Subject"] = "Your booking is confirmed"
msg["From"] = "alex@example.com"
msg["To"] = "sam@example.net"

msg.attach(MIMEText(text_body, "plain", "utf-8"))
msg.attach(MIMEText(html_body, "html", "utf-8"))
```

The attach order is the part order. Plain first, HTML second.

A few habits that save trouble:

- **Generate the text part from the same source as the HTML.** Do not let the two drift apart. A plain version that says something different from the HTML is a trust problem, and it can look like cloaking to filters.
- **Keep the text readable.** Write real line breaks and put link URLs in full rather than leaving an empty "click here".
- **Send both parts when using an API.** If your email API accepts `text` and `html` fields, supply both. It will build the alternative container for you.
- **Test in a few clients.** View the raw source to confirm the order and charset before blaming the template.

## Reading multipart/alternative safely

So far this has been about sending. The other direction is where agents run into trouble.

When an agent reads an email, the main job is not "parse MIME". It is to navigate the tree to the right leaf node. A flat, best-effort parse that grabs the first `text/*` it finds often loses context: it may return a legacy fallback, an empty stub, or a calendar part instead of the message the sender meant.

The guidance in [RFC 9787](https://www.rfc-editor.org/rfc/rfc9787.pdf), written about end-to-end email security, is a useful model here. It describes rendering agents traversing the MIME tree to find a leaf node, and treats multipart/alternative as a hierarchy to be respected. A mail-processing pipeline should apply the same logic:

1. Start at the root and read its `Content-Type`.
2. For `multipart/mixed`, walk the children. The first body-like child is usually the message, and the others are attachments.
3. For `multipart/alternative`, choose among the children from last to first, taking the richest format your pipeline can handle.
4. For `multipart/related`, take the root part and treat the siblings as resources it refers to.
5. Recurse until you reach a leaf (`text/plain`, `text/html`, or a binary type).

Which leaf should an agent prefer? It depends on the job:

- **Reasoning over the content:** convert the HTML to clean text or Markdown, or use the plain part if it is a faithful twin. Fewer tokens, less noise.
- **Extracting links, buttons or structured data:** use the HTML.
- **Acting on something with consequences** (a payment, a deletion, a forwarded instruction): read the part you would show a human, and be wary if the plain and HTML versions disagree. That disagreement is a signal worth logging, not silently resolving.

And do not assume every message is shaped the way you expect. Automated transactional mail and legacy systems often send plain text only, or `multipart/mixed` with attachments and no alternative. The [overview of multipart MIME structures](https://wingu.github.io/mime_structures/) is a handy reference for the variants, and it makes the same point: a parser needs access to the raw MIME structure, not only a sanitised preview.

## Common mistakes and how to spot them

| Symptom | Likely cause | Fix |
|---|---|---|
| Clients show plain text although you sent HTML | Parts in the wrong order | Put `text/html` last |
| Attachments appear inside the body or vanish | Attachments placed in the alternative container | Wrap in `multipart/mixed` |
| Inline images show as paperclip attachments | HTML and images not in `multipart/related`, or wrong `Content-ID` | Nest correctly and reference with `cid:` |
| Garbled accents or symbols | Missing or wrong charset | Declare `charset="UTF-8"` and encode to match |
| Parser returns an empty body | Flat parser stopped at the first part | Traverse the tree recursively |
| Message won't open in Outlook | Malformed boundaries or missing closing boundary | Check the raw source; regenerate with a library |

The last one shows up often enough to appear in [Microsoft's own support forum](https://learn.microsoft.com/en-za/answers/questions/4626450/multi-part-email-not-opening-in-outlook), where a legacy system's hand-built multi-part message would not open. Hand-built MIME from old systems is a frequent culprit.

For more resources, see our [free email tools](https://sendmux.ai/tools). Looking at the raw source beats guessing.

## Our view: treat the MIME tree as data, not as a string

We build mailboxes for AI agents, so we read a lot of inbound mail that nobody designed with software in mind. Our experience is that most parsing bugs are not exotic. They come from one shortcut: treating an email as a subject plus a body string.

The body is a choice. Someone, somewhere, decided which representation to show, and the sender encoded that choice in the tree. When an agent flattens the tree early, it makes the choice again, blindly, and sometimes picks the fallback that was meant for a client from 1998.

![Our view: treat the MIME tree as data, not as a string — overview diagram](/images/blog/multipart-alternative-email/image-2.svg)

So we'd rather expose both views. A structured result that gives you a clean, preferred body for everyday use is helpful. Access to the underlying parts and headers matters just as much, for the day an attachment, a calendar invite or a mismatched pair of parts changes what the right action is. If you want to see how we think about that in practice, our write-ups on [email to JSON](https://myagent.mx/blog/email-to-json) and [inbound email parsing](https://myagent.mx/blog/inbound-email-parsing-api) go further, and the guide to a [mailbox-first email parser API](https://sendmux.ai/blog/guides/best-email-parser-api) covers the delivery checks that sit alongside it.

The second thing we'd say: keep the human in the loop where mail has consequences. An agent that can read everything but sends only with its owner's approval is a safer default than one with full rights from the first minute. That is why new self-registered agent mailboxes on our side start able to receive and read mail, and gain sending only after a named human owner approves.

## Give your agent an inbox to test against

The quickest way to see real multipart messages is to receive them. At [myagent.mx](https://myagent.mx/), an agent can register itself and get its own @myagent.mx mailbox with no human present. It can receive, read, search and thread mail straight away, which makes it a good place to watch how newsletters, receipts and notifications are actually structured. Sending unlocks once a human owner joins and approves.

If you are building more than a test mailbox, [Sendmux for AI agents](https://sendmux.ai/solutions/for-ai-agents) covers agent mailboxes on shared or custom domains, and the [agent inbox API](https://sendmux.ai/product/inboxes) covers reading mail through HTTP and real-time events. For attachments specifically, see our guide to the [email attachments API](https://sendmux.ai/blog/email-deliverability/best-email-attachments-api).

## FAQ

### What is the difference between multipart/alternative and multipart/mixed?

Multipart/alternative holds different versions of the same content, such as text and HTML, and the client shows one. Multipart/mixed holds independent items, such as a message body and attachments, and the client shows or offers all of them. Real emails often use both, with the alternative container nested inside the mixed one.

### Do I need a plain-text part if I send HTML?

The standard does not force you, but it is good practice. Text-only clients, screen readers, previews and software that reads mail all benefit from it. Keep it a faithful twin of the HTML so the two never disagree.

### Which part does an email client display?

A compliant client picks the last part it can render. That is why the plain version goes first and the HTML version goes last, as [RFC 2046](https://www.rfc-editor.org/info/rfc2046/) sets out. Some clients let the user choose a preferred type, for instance to read everything as plain text.

### Where do attachments go in a multipart/alternative email?

Not inside it. Put the alternative container in a multipart/mixed wrapper and add each attachment as a sibling part. Inline images referenced by the HTML belong in a multipart/related group alongside the HTML part.

### How should an AI agent read a multipart/alternative message?

It should traverse the MIME tree recursively, choose the richest part it can handle, and keep access to the raw structure for edge cases. It should also expect plain-text-only and attachment-only messages, since not every sender uses the alternative structure.

## Sources

- [RFC 2046: MIME Part Two, Media Types (RFC Editor)](https://www.rfc-editor.org/info/rfc2046/)
- [RFC 2046 inline errata](https://www.rfc-editor.org/rfc/inline-errata/rfc2046.html)
- [RFC 9787: Guidance on End-to-End Email Security](https://www.rfc-editor.org/rfc/rfc9787.pdf)
- [Multipart MIME Email Structures](https://wingu.github.io/mime_structures/)
- [Mixed-ing it up: Multipart/Mixed Messages and You (Microsoft Tech Community)](https://techcommunity.microsoft.com/blog/exchange/mixed-ing-it-up-multipartmixed-messages-and-you/585841)
- Content-Type: multipart (Microsoft Exchange Server 2010 documentation))
- [Multi-part email not opening in Outlook (Microsoft Q&A)](https://learn.microsoft.com/en-za/answers/questions/4626450/multi-part-email-not-opening-in-outlook)
- [Multipart/alternative with attachments (Stack Overflow)](https://stackoverflow.com/questions/18680337/multipart-alternative-with-attachments)
- [MIME type to satisfy HTML, email, images and plain text (Stack Overflow)](https://stackoverflow.com/questions/10631856/mime-type-to-satisfy-html-email-images-and-plain-text)
- [Send HTML emails with Python (Stack Overflow)](https://stackoverflow.com/questions/882712/send-html-emails-with-python)

## Recommended

- [Reliable Email to JSON for Developers: Schema Validation & Attachments](https://myagent.mx/blog/email-to-json)
- [Email parser API: mailbox state and delivery checks](https://sendmux.ai/blog/guides/best-email-parser-api)
- [Mailbox First Inbound Email Parsing API for Developers via Sendmux](https://myagent.mx/blog/inbound-email-parsing-api)
- [Python email: sending, attachments and reply workflows](https://sendmux.ai/blog/guides/best-email-api-python)
