RFC 2646

The Text/Plain Format Parameter

πŸ“… published August 1999, from ietf

RFC 2646: The Text/Plain Format Parameter πŸŽ€

okay bestie, this one is a Standards Track doc 🧚 Its editor is R. Gellens from Qualcomm, and it's dated August 1999. It updates RFC 2046 (that's the header saying so, and it doesn't list anything it obsoletes). It's a whole vibe about making plain text email feel less cursed when it gets flowed, quoted, and forwarded. πŸ’–

Status of This Memo πŸ“œ

This is an Internet standards track protocol for the Internet community, and the authors are literally asking for discussion and suggestions for improvements 🫢 For where this protocol sits in standardization and its current status, check the current edition of "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited, so share it with everyone 🌈

Copyright (C) The Internet Society (1999). All Rights Reserved. πŸ’œ

Table of Contents πŸ—‚οΈ

    1.  Abstract . . . . . . . . . . . . . . . . . . . . . . . . . .  2
    2.  Conventions Used in this Document . . . . . . . . . . . . .   2
    3.  The Problem  . . . . . . . . . . . . . . . . . . . . . . . .  2
      3.1.  Paragraph Text  . . . . . . . . . . . . . . . . . . . .   3
      3.2.  Embarrassing Line Wrap . . . . . . . . . . . . . . . . .  3
      3.3.  New Media Types . . . . . . . . . . . . . . . . . . . .   4
    4.  The Format Parameter to the Text/Plain Media Type  . . . . .  4
      4.1.  Generating Format=Flowed  . . . . . . . . . . . . . . .   5
      4.2.  Interpreting Format=Flowed . . . . . . . . . . . . . . .  6
      4.3.  Usenet Signature Convention . . . . . . . . . . . . . .   7
      4.4.  Space-Stuffing . . . . . . . . . . . . . . . . . . . . .  7
      4.5.  Quoting . . . . . . . . . . . . . . . . . . . . . . . .   8
      4.6.  Digital Signatures and Encryption  . . . . . . . . . . .  9
      4.7.  Line Analysis Table . . . . . . . . . . . . . . . . . .  10
      4.8.  Examples . . . . . . . . . . . . . . . . . . . . . . . . 10
    5.  ABNF  . . . . . . . . . . . . . . . . . . . . . . . . . . .  11
    6.  Failure Modes  . . . . . . . . . . . . . . . . . . . . . . . 11
      6.1.  Trailing White Space Corruption . . . . . . . . . . . .  11
    7.  Security Considerations  . . . . . . . . . . . . . . . . . . 12
    8.  IANA Considerations . . . . . . . . . . . . . . . . . . . .  12
    9.  Internationalization Considerations  . . . . . . . . . . . . 12
   10.  Acknowledgments . . . . . . . . . . . . . . . . . . . . . .  12
   11.  References . . . . . . . . . . . . . . . . . . . . . . . . . 13
   12.  Editor's Address  . . . . . . . . . . . . . . . . . . . . .  13
   13.  Full Copyright Statement . . . . . . . . . . . . . . . . . . 14

1. Abstract ✨

okay so the problem is that people keep mislabeling paragraph text as Text/Plain, and there's this whole "embarrassing line wrap" situation where replies get weirder every time they're quoted 😭 (See section 3.)

Fancier media types like Text/Enriched [RICH] and Text/HTML [HTML] have had a rough time too. They weren't backwards compatible, and the people on the receiving end were not into it πŸ’€

So what we actually need is a format that's basically Text/Plain in every way that matters, so it still displays fine as Text/Plain, but that also lets the sender tell the receiver which lines belong to the same logical paragraph and can be flowed (wrapped and joined) as needed πŸ¦‹

This memo proposes a new parameter for Text/Plain. When that parameter is present, trailing whitespace is used to mark lines that are flowed. Older implementations see normal Text/Plain, because that's exactly what it is, so it just works 🌸

2. Conventions Used in this Document πŸ“–

The key words "REQUIRED", "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in "Key words for use in RFCs to Indicate Requirement Levels" [KEYWORDS]. πŸ”₯

3. The Problem 🫠

Text/Plain is the lowest common denominator of Internet email. Lines can be up to 997 characters, though by convention they're usually kept to 80 or fewer, and a CRLF sequence means a line break [MIME-IMT]. Simple, classic, iconic πŸ’…

Text/Plain is usually shown as preformatted text in a fixed font. Characters start at the left margin and keep going right until a CRLF shows up, and then a new line starts back at the left margin. When a line is too long for the window, some clients wrap it and others give you a horizontal scroll bar πŸ™ƒ

This memo calls text that fits this description "fixed". 🧱

Some interoperability problems have been spotted with this media type:

3.1. Paragraph Text πŸ“

Lots of modern programs use a proportional font and a CRLF for paragraph breaks. Line breaks are "soft" here, so they happen as needed when the text is displayed. Characters pile up into a paragraph until a CRLF shows up, and then a new paragraph starts. Each paragraph starts at the left margin (or its paragraph indent) and keeps going right until a word doesn't fit in the leftover width. That word drops to the left margin of the next line, and this repeats until the paragraph ends at a CRLF. Extra vertical space goes between paragraphs 🌷

This memo calls text that works like this "flowed". 🌊

The problem is that plenty of software labels this media type as Text/Plain by mistake, and users end up really uncomfortable about it 😩

3.2. Embarrassing Line Wrap πŸ™ˆ

When Text/Plain messages get quoted in replies or forwarded, every line gets a little longer each time, and that's the "embarrassing line wrap" 😭 The result is text that's hard to read at best, and it often makes attributions super confusing.

Example:

      >>>>>>This is a comment from the first message to show a
      >quoting example.
      >>>>>This is a comment from the second message to show a
      >quoting example.
      >>>>This is a comment from the third message.
      >>>This is a comment from the fourth message.

It can be confusing to figure out who said lines 2 and 4 above. πŸ’€

Also, devices with screens narrower than 80 characters are getting more popular, so embarrassing line wrap happens even with text that isn't quoted at all πŸ“±

Example:

      This is paragraph text that is
      meant to be flowed across
      several lines.
      However, the sending mailer is
      converting it to fixed text at
      a width of 72
      characters, which causes it to
      look like this when shown on a
      PDA with only
      30 character lines.

3.3. New Media Types πŸ¦‹

Fancier media types like Text/Enriched [RICH] and Text/HTML [HTML] have had a rough time, since they weren't backwards compatible and the people on the receiving end were not happy about it 😭

Specifically, Text/Enriched needs open angle brackets ("<") and hard line breaks doubled, and users were not thrilled to see that when it displayed as Text/Plain. Text/HTML changes the text even more, and the complaints piled up right along with it πŸ™ƒ

A proposal to define a brand new media type just for the paragraph form ran into interoperability trouble with software that's already out there. Some programs treat unknown subtypes of Text as an attachment, which is a whole mess πŸ’…

So again, what's wanted is a format that's basically Text/Plain in every significant way, so it still displays as Text/Plain, and that also lets the sender say which lines form a logical paragraph and can be flowed (wrapped and joined) as needed πŸ’–

4. The Format Parameter to the Text/Plain Media Type πŸ‘‘

This document defines a new MIME parameter for use with Text/Plain:

      Name:  Format
      Value:  Fixed, Flowed

(The parameter name and its value are both case insensitive. πŸŽ€)

If it's not specified, the value is assumed to be Fixed. The meaning of Fixed is the usual one for Text/Plain [MIME-IMT]. 🧱

A value of Flowed means the sender generated the text using the definition of flowed text in this memo, and a receiver MAY use that knowledge when it receives the text. ✨

This section talks about flowed text, and section 5 has the formal definition 🧚

Here's the lowkey genius part: flowed lines are almost indistinguishable from fixed lines, so software that's already deployed just treats them as normal Text/Plain, which is exactly what they are. That means no interoperability problems are expected 🌈

Also, be aware that this memo describes an on-the-wire format. It doesn't cover formats for local file storage πŸ“

4.1. Generating Format=Flowed ✨

Okay so when you're generating Format=Flowed text, your lines SHOULD be shorter than 80 characters πŸŽ€. As suggested numbers, any paragraph longer than 79 characters in total could get wrapped into lines of 72 or fewer characters πŸ’…. The exact length is basically preference, but longer lines need rewrapping more often and can be rough on older mailers 😭. Apparently someone suggested that 66 character lines are the most readable πŸ“–.

(The reason for keeping it to 79 or fewer characters between CRLFs on the wire is so every line, even in a program that doesn't know about flowed text, fits on a standard 80-column screen without wrapping πŸ–₯️. It's 79 and not 80 because the last column is usually saved for a line-wrap indicator πŸ™ˆ.)

When creating flowed text, the generating agent wraps, which means it inserts 'soft' line breaks as needed. Soft line breaks go between words. Since a soft line break is a SP CRLF sequence, the generating agent makes one by inserting a CRLF right after a space πŸ¦‹.

A generating agent SHOULD NOT insert white space into a word (a sequence of printable characters not containing spaces) 🚫. If the agent runs into a word longer than 79 characters (but shorter than 998 characters, which is the [SMTP] limit on line length), it SHOULD send the word as is and go past the 79-character limit πŸ’œ.

A generating agent SHOULD:

  1. Ensure all lines (fixed and flowed) are 79 characters or fewer in length, counting the trailing space but not counting the CRLF, unless a word by itself exceeds 79 characters.
  2. Trim spaces before user-inserted hard line breaks.
  3. Space-stuff lines which start with a space, From , or >.

If you want messages that don't need space-stuffing (and that look nicer when viewed as Format=Fixed), a generating agent MAY avoid wrapping immediately before >, From , or a space ✨.

(See sections 4.4 and 4.5 for more information on space-stuffing and quoting, respectively.)

A Format=Flowed message is made of zero or more paragraphs. Each paragraph has one or more flowed lines followed by one fixed line 🌸. The usual vibe is a run of flowed text lines with blank (empty) fixed lines between them πŸ“.

Any number of fixed lines can show up between paragraphs 🧚.

[Quoted-Printable] encoding SHOULD NOT be used with Format=Flowed unless it's absolutely necessary, like non-US-ASCII (8-bit) characters going over a strictly 7-bit transport such as unextended SMTP 😀. Specifically, a message SHOULD NOT be encoded in Quoted-Printable just to protect the trailing spaces on flowed lines, unless the body part is cryptographically signed or encrypted (see Section 4.6) πŸ”.

The whole point of Format=Flowed is that user agents can generate flowed text that doesn't look messy when you read it as pure, raw Text/Plain (no decoding needed) πŸ‘€. Quoted-Printable gets in the way of that and may cause Format=Flowed to be rejected by end users πŸ’€.


4.2. Interpreting Format=Flowed

If the first character of a line is a quote mark (>), the line counts as quoted (see section 4.5) πŸ’¬. Logically, every quote mark gets counted and deleted, leaving a line with a non-zero quote depth and some content. The agent is totally free to display the content with quote marks, excerpt bars, or anything else it likes ✨. This quoted-line check happens before any other test (so before checking for space-stuffed and flowed) 🎯.

If the first character of a line is a space, the line has been space-stuffed (see section 4.4) 🧽. Logically, that leading space gets deleted before you look at the line any further, which means before checking for flowed 🫧.

If the line ends in one or more spaces, it's flowed. Otherwise it's fixed. Trailing spaces are part of the line's content, but the CRLF of a soft line break is not πŸŽ€.

A series of one or more flowed lines followed by one fixed line counts as a paragraph, and it MAY be flowed (wrapped and unwrapped) as needed for display and when building new messages (see section 4.5) 🌈.

A line made of one or more spaces (after deleting a stuffed space) counts as a flowed line 🫢.


4.3. Usenet Signature Convention

Usenet has a convention of using "-- " as the separator line between the body of a message and its signature πŸ“°. When a Format=Flowed message has a Usenet-style separator before the signature, that separator line gets sent as-is. This is a special case: an (optionally quoted) line made of DASH DASH SP is not considered flowed πŸ™Œ.


4.4. Space-Stuffing

Space-stuffing is how Format=Flowed handles unquoted lines that start with >, and it also protects against systems that "From-munge" messages in transit (changing any line starting with From into >From ) πŸ›‘οΈ.

Space-stuffing adds a single space to the start of any line that needs protecting when the message gets generated. When a message comes in, if the first character of a line is a space, that space gets logically deleted. This happens after the quoted-line test and before the flowed-line test 🧼.

When generating, any unquoted lines starting with >, and any lines starting with a space or From , SHOULD be space-stuffed. Other lines MAY be space-stuffed if you want πŸ’….

(Space-stuffing is similar to dot-stuffing as specified in [SMTP] πŸ€“.)

If a Format=Flowed-aware agent gets a space-stuffed message, it reverses the space-stuffing, so the message looks exactly like it did before πŸͺ„. An agent that doesn't know about Format=Flowed won't undo any space-stuffing, so Format=Flowed messages may show a leading space on some lines (the ones that start with a space, a > that isn't a quote indicator, or From ) πŸ™ˆ. Lines that need space-stuffing don't come up very often, and the look of unreversed space-stuffing is pretty minimal, so this isn't expected to be a big deal πŸ€·β€β™€οΈ.


4.5. Quoting

In Format=Flowed, the canonical quote indicator (or quote mark) is one or more close angle bracket (>) characters πŸ‘‘. Lines that start with the quote indicator count as quoted. The number of > characters at the start of a line sets the quote depth. Flowed lines that are also quoted might need special handling when displayed or copied into new messages πŸ’­.

When you create quoted flowed lines, each one starts with the quote indicator πŸ“.

Space-stuffing means these lines are semantically identical, both with a quote depth of two and content of "Exit, Stage Left" 🎭:

>> Exit, Stage Left

and

>>Exit, Stage Left

But this line is different. It has a quote depth of one and content of "> Exit, Stage Left" 😳:

> > Exit, Stage Left

When generating quoted flowed lines, an agent has to keep an eye on changes in quote depth πŸ‘€. A run of quoted lines with the same quote depth SHOULD be encoded as a paragraph, where the last line is generated as fixed and the earlier lines are generated as flowed 🌟.

If a receiving agent wants to reformat flowed quoted lines (joining and/or wrapping them) for display or when generating new messages, the lines SHOULD be de-quoted, reformatted, and then re-quoted πŸ”„. To de-quote, you count the close angle brackets in the quote indicator at the start of each line. Consecutive lines with the same quoting depth count as one paragraph and get reformatted together. To re-quote after reformatting, you put a quote indicator with the same number of close angle brackets as the original in front of each line πŸŽ€.

When a receiver gets a flowed line where the quoting depth changes, that's an improperly formatted message 🚨. The receiver SHOULD handle this error with the 'quote-depth-wins' rule, which means ignoring the flowed indicator and treating the line as fixed. In other words, the change in quote depth ends the paragraph πŸ›‘.

Here's an example sequence of lines. Using '*' to show a soft line break (SP CRLF) and '#' to show a hard line break (CRLF):

> Thou villainous ill-breeding spongy dizzy-eyed*
> reeky elf-skinned pigeon-egg!*     <--- problem ---<
>> Thou artless swag-bellied milk-livered*
>> dismal-dreaming idle-headed scut!#
>>> Thou errant folly-fallen spleeny reeling-ripe*
>>> unmuzzled ratsbane!#
>>>> Henceforth, the coding style is to be strictly*
>>>> enforced, including the use of only upper case.#
>>>>> I've noticed a lack of adherence to the coding*
>>>>> styles, of late.#
>>>>>> Any complaints?#

The second line ends in a soft line break even though it's the last line of the one-deep quote block 😬. So the question is how that line should be read, given that the next line is the first line of the two-deep quote block πŸ€”.

Processed with quote-depth wins, the example above gives you the first two lines as one quoted, flowed section with a quote depth of 1. The third and fourth lines become a quoted, flowed section with a quote depth of 2 πŸ’….

A generating agent SHOULD NOT create this situation, and a receiving agent SHOULD handle it using quote-depth wins 🫢.


4.6. Digital Signatures and Encryption

If a message is digitally signed or encrypted, it's really important that the cryptographic processing uses the on-the-wire Format=Flowed format πŸ”βœ¨. So when generating, the message SHOULD be prepared for transmission first, which means adding soft line breaks, space-stuffing, and [Quoted-Printable] encoding (to protect soft line breaks), and only then getting digitally signed or encrypted 🧁. On the receiving end, the message SHOULD have its signature verified or be decrypted before [Quoted-Printable] decoding, removing stuffed spaces, soft line breaks, and quote marks, and reflowing πŸ’–.


4.7. Line Analysis Table

You can analyze lines in a Text/Plain body part with Format=Flowed by looking at how each line starts and ends πŸ”. If the line starts with the quote indicator, it's quoted. If it ends with one or more space characters, it's flowed. Here's the whole thing in one table πŸ“Š:

      Starts          Ends in
      with            One or             Line
      Quote           More Spaces        Type
      ------          -----------        ---------------
      no              no                 unquoted, fixed
      yes             no                 quoted,   fixed
      no              yes                unquoted, flowed
      yes             yes                quoted,   flowed

4.8. Examples πŸ’–

okay, examples time, and this one is SO fun because it's the Mad Hatter's tea party πŸ«–πŸŽ© Alice gets three paragraphs of chaos:

`Take some more tea,' the March Hare said to Alice, very
earnestly.

`I've had nothing yet,' Alice replied in an offended tone, `so I
can't take more.'

`You mean you can't take LESS,' said the Hatter: `it's very easy
to take MORE than nothing.'

Now here's how it gets encoded 🧩. Using * for a soft line break (that's SP CRLF, a space then CRLF) and # for a hard line break (that's just CRLF), it looks like this:

`Take some more tea,' the March Hare said to Alice, very*
earnestly.*
#
`I've had nothing yet,' Alice replied in an offended tone, `so*
I can't take more.'*
#
`You mean you can't take LESS,' said the Hatter: `it's very*
easy to take MORE than nothing.'#

Bestie, look at that blank paragraph break πŸ₯Ή. It's just a lone #, so the hard break does the work, and the soft breaks keep each line flowing into the next one ✨.

We're not done, because there's also a quoting example, same exchange, but now it's the direct quotes that get the glow-up πŸ’…:

              >>>Take some more tea.#
              >>I've had nothing yet, so I can't take more.#
              >You mean you can't take LESS, it's very easy to take*
              >MORE than nothing.#

5. ABNF πŸŽ€

okay so the grammar stuff is written in [ABNF], and it pulls in the Core Rules too. Here's the whole thing, no cap, copied exactly:

paragraph     = 1*flowed-line fixed-line
fixed-line    = fixed / sig-sep
fixed         = [quote] [stuffing] *text-char non-sp CRLF
flowed-line   = flow-qt / flow-unqt
flow-qt       = quote [stuffing] *text-char 1*SP CRLF
flow-unqt     = [stuffing] *text-char 1*SP CRLF
non-sp        = %x01-09 / %x0B / %x0C / %x0E-1F / %x21-7F
                   ; any 7-bit US-ASCII character, excluding
                   ; NUL, CR, LF, and SP
quote         = 1*">"
sig-sep       = [quote] "--" SP CRLF
stuffing      = [SP] ; space-stuffed, added on generation if
                     ; needed, deleted on reception
text-char     = non-sp / SP

6. Failure Modes πŸ’€

6.1. Trailing White Space Corruption πŸ™ˆ

okay so there are real systems out there that mess with trailing whitespace on messages passing through them 😭. Some strip it, and in rarer cases they add it, and that's a violation of RFC 821 [SMTP] section 4.5.2.

Stripping is actually the lowkey least dramatic outcome 🌸. When trailing whitespace gets stripped, your flowed lines turn into fixed lines, and the message ends up no worse than if Format=Flowed had never been used. Not the end of the world!

Adding trailing whitespace is the real drama ⚠️. A Format=Flowed message can end up with a malformed display or reply. Iykyk πŸ’….

Here's the tea 🍡: most systems that add trailing white space are doing it to fill up an internal record format, so the line ends up almost always having an even number of characters (counting the added trailing white space).

One possible avoidance would be to define Format=Flowed lines to use either one or two trailing space characters to indicate a flowed line, so that the total line length is odd. BUT, considering how scarce these systems are today, it's just not worth the extra complexity 🫢.

(Quick note: that "BUT" is just me being dramatic, it's not a keyword thing. Nothing in there is a BCP 14 key word, it's all lowercase in the spec. Lol.)


7. Security Considerations πŸ”

this parameter introduces no security considerations beyond those which apply to Text/Plain. Honestly, that's a whole vibe of "nothing new to worry about here" 🧚.

Section 4.6 talks about how Format=Flowed plays with digital signatures or encryption, so go read that one if signing is part of your life πŸ”.


8. IANA Considerations πŸ“‹

IANA is requested to add a reference to this specification in the Text/Plain Media Type registration. Basically a little "hey, this spec exists" note in the Text/Plain registration ✨.


9. Internationalization Considerations 🌍

the line wrap and quoting specifications of Format=Flowed may not be suitable for certain charsets, like Arabic and Hebrew characters, which read from right to left. So be careful with format=flowed in those cases. format=fixed combined with quoted-printable encoding may be more suitable 🌈.


10. Acknowledgments 🫢

this proposal evolved from a discussion of Chris Newman's Text/Paragraph draft, which happened on the IETF 822 mailing list πŸ’Œ. Big thanks to Ian Bell, Steve Dorner, Brian Kelley, Dan Kohn, Laurence Lundblade, and Dan Wing for their reviews, comments, suggestions, and discussions. You are all iconic πŸ‘‘.


11. References πŸ“š

these are the sources, with every detail kept:

  • [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", RFC 2234, November 1997.
  • [KEYWORDS] S. Bradner, "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [RICH] Resnick, P. and A. Walker, "The text/enriched MIME Content-type", RFC 1896, February 1996.
  • [MIME-IMT] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, November 1996.
  • [Quoted-Printable] Freed, N. and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
  • [SMTP] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC 821, August 1982.
  • [HTML] Berners-Lee, T. and D. Connolly, "Hypertext Markup Language -- 2.0", RFC 1866, November 1995.

12. Editor's Address ✏️

the editor, with the contact details exactly as they are:

Randall Gellens
QUALCOMM Incorporated
5775 Morehouse Dr.
San Diego, CA  92121-2779
USA

Phone: +1 619 651 5115
EMail: randy@qualcomm.com

here's the legal stuff, kept complete πŸŽ€.

Copyright (C) The Internet Society (1999). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Acknowledgement 🌸

funding for the RFC Editor function is currently provided by the Internet Society. Thank you, Internet Society, you're the real MVP πŸ’œ.

πŸ“¦ where this page comes from