Messages and MIME

Read an Internet message

Separate the RFC 5322 header section from the body and recognize continuation lines.

The bytes sent after DATA follow a format called RFC 5322. It has three pieces: a header section, one empty line, and the body. That’s the whole structure.

Each header field is a name, a colon, and a value. Here is a complete, valid message:

From: Flavio Copes <[email protected]>
To: Sara Rossi <[email protected]>
Subject: Project update
Date: Thu, 30 Jul 2026 10:00:00 +0200
Message-ID: <[email protected]>

The deployment is complete.

The empty line is the most important line in the file. Everything above it is headers. Everything below it is body.

Why the empty line matters

Once the parser crosses the empty line, it stops looking for headers. A body line that reads Subject: hello is just text. It doesn’t become a second subject.

This is also why a message with no blank line at all is broken. The parser treats the whole body as header lines and either rejects the message or shows it empty.

Folded fields

A header value can continue on the next line if that line starts with a space or tab. This is called folding:

Subject: Notes from the meeting about the new
 onboarding flow

Parsers unfold this back into one line before reading the value. Modern software should avoid folding unless a line would be very long, but you’ll see it in the wild constantly, especially in Received fields.

Case and repetition

Field names are case-insensitive. subject:, Subject:, and SUBJECT: are the same field. Whether a field can appear twice depends on its definition: Received repeats, From shouldn’t.

The injection trap

Here is a security failure that follows from this format. Suppose a contact form puts the user’s input straight into the Subject header. Someone submits:

Hello\r\nBcc: [email protected]

The line break ends the subject and starts a new header. Your form just became a spam relay. Any value coming from users must have \r and \n stripped before it goes into a header. Good mail libraries do this or throw an error. Check yours.

Line endings and raw source

On the wire, lines end with CRLF (\r\n). Libraries normalize this for you. When you’re investigating a broken message, always look at the raw source, not the rendered view. Mail apps repair or hide invalid structure, and you’d be debugging something that isn’t there.

One more thing. The message that arrives isn’t byte-for-byte the one you sent. Every server on the path adds Received fields on top, even when the body is untouched.

Try adding a folded Subject and a body line starting with From: to the example above. Mark the exact empty line where header parsing stops.

Lesson completed