WSS
Web Specification Studio Home
On this page
FoundationsRequiredUpdated

Internet Message Format (RFC 5322)

Construct structurally valid email messages adhering to RFC 5322 grammar, strict CRLF line endings, 998-character line limits, and standard header folding rules.

What it is

RFC 5322 specifies the syntactic grammar, structural constraints, and serialization format of an Internet email message.

At the byte level, every RFC 5322 message consists of three distinct components:

  1. Header Section: A sequence of field names and field values delimited by colons (:), terminated by carriage-return line-feed (CRLF / \r\n).
  2. Header-Body Separator: Exactly one empty line consisting of a solitary CRLF sequence (\r\n\r\n).
  3. Body Section: The message payload (plain text or formatted MIME parts), where lines are separated by CRLF.
From: "Alice Smith" <[email protected]>\r\n
To: "Bob Jones" <[email protected]>\r\n
Subject: Project Status Update\r\n
Date: Tue, 25 Aug 2026 14:30:00 +0000\r\n
Message-ID: <[email protected]>\r\n
MIME-Version: 1.0\r\n
Content-Type: text/plain; charset=utf-8\r\n
\r\n
Hello Bob,\r\n
\r\n
Here is the weekly update.\r\n

Why it matters

  • Prevents Silent Message Truncation: Line length limits are strictly enforced by SMTP relays (RFC 5321 §4.5.3.1.6). Lines exceeding 998 characters without line breaks will be forcibly wrapped, split, or rejected with a 500 Line too long error by receiving MTAs.
  • Header Injection Defense: Failure to validate and normalize CRLF sequences in header inputs allows attackers to inject arbitrary headers (such as Bcc:, Cc:, or malicious Subject:) or split the header section early to forge body text.
  • DKIM Verification Stability: Inconsistent line endings (\n vs \r\n) cause MTA canonicalization layers to reformat the raw bytes in transit, breaking cryptographic DKIM signature verification.

How to implement

1. Enforce strict CRLF (\r\n) wire format line endings. Every line in the header and body must terminate with the two-byte sequence ASCII 13 (CR) followed by ASCII 10 (LF). Never transmit bare LF (\n) or bare CR (\r) over SMTP.

2. Adhere to the 78/998 line length rules.

  • Recommended Maximum Line Length: 78 characters (excluding CRLF) for optimal readability and client compatibility.
  • Hard Technical Maximum: 998 characters (excluding CRLF). Any line longer than 998 bytes must be wrapped or encoded using Quoted-Printable (Content-Transfer-Encoding: quoted-printable) or Base64.

3. Implement Proper Header Folding (Folding White Space - FWS). When a header field exceeds 78 characters, fold the line immediately following a delimiter by inserting a CRLF followed by at least one space or horizontal tab (WSP):

Subject: This is a very long subject line that exceeds the standard
 line length recommendation and has been folded cleanly\r\n

4. Encode non-ASCII characters in headers using RFC 2047. Header field names and raw values must contain only US-ASCII characters (33–126). Non-ASCII characters (such as accents, emojis, or international alphabets) in headers (Subject, From, To) must be encoded using Q-encoding or B-encoding:

Subject: =?utf-8?B?U3RhdHVzIFVwZGF0ZTog8J+agA==?=\r\n
From: =?utf-8?Q?H=C3=A9l=C3=A8ne_Martin?= <[email protected]>\r\n

Common mistakes

  • Omitting the Empty Separator Line: Forgetting the empty \r\n line between headers and body causes the first lines of the body to be parsed as malformed headers.
  • Sending Bare LF over SMTP: Transmitting UNIX-style \n line endings causes some MTAs (such as Postfix with strict_smtputf8 or Microsoft Exchange) to reject the message or inject unpredictable carriage returns that break DKIM body hashes (bh=).
  • Raw UTF-8 in RFC 5322 Headers without SMTPUTF8 Negotiation: Emitting raw UTF-8 bytes in header lines without verifying that the receiving server advertises SMTPUTF8 (RFC 6531) in its EHLO response.
  • String Concatenation in Header Construction: Building headers via simple string interpolation ("Subject: " + userInput) rather than using a standard MIME builder library, exposing the application to CRLF injection attacks.

Verification

1. Inspect raw message stream for byte-level CRLF compliance:

# Verify \r\n line endings in raw message file
file raw_message.eml
# Output: ASCII text, with CRLF line terminators

# Verify no lines exceed 998 bytes
awk 'length > 998' raw_message.eml
# Output must be empty

2. Validate with standard parser libraries: Test message generation against strict standards parsers (such as Python email.parser.BytesParser(policy=email.policy.strict) or Go net/mail.ReadMessage).

Related topics

Sources & further reading