RFC 1896

The text/enriched MIME Content-type

๐Ÿ“… published February 1996, from ietf

RFC 1896: The text/enriched MIME Content-type ๐ŸŽ€

Okay bestie, gather round because this is RFC 1896 and it is ICONIC ๐Ÿ’… It's from the Network Working Group, written by P. Resnick of QUALCOMM and A. Walker of InterCon. It's dated February 1996 and its category is Informational. It obsoletes RFC 1523 and RFC 1563 ๐Ÿฆ‹, so if you're still going off those, it's giving outdated, ngl.

Status of this Memo ๐Ÿ“‹

Real talk: this memo provides information for the Internet community ๐ŸŒธ. It does not specify an Internet standard of any kind, so it's info, not a standard โœจ. And distribution of this memo is unlimited ๐Ÿซถ.

Abstract ๐Ÿ’œ

MIME [RFC-1521] defines a format and general framework for representing a wide variety of data types in Internet mail. This document defines one particular type of MIME data, the text/enriched MIME type. The whole point of text/enriched is to help simple enriched text interoperate across a wide variety of hardware and software platforms ๐Ÿงš. This document is only a minor revision to the text/enriched MIME type that was first described in [RFC-1523] and [RFC-1563]. It's only meant for the short term, until other MIME types for text formatting in Internet mail get developed and deployed ๐Ÿ’–.

The text/enriched MIME type ๐ŸŒˆ

So the goal here is wider interoperability for simple formatted text, and this doc defines an extremely simple subtype of the MIME content-type "text" called the "text/enriched" subtype ๐ŸŽ€. The content-type line for this type may have one optional parameter, the "charset" parameter. It takes the same values that are permitted for the "text/plain" MIME content-type.

The text/enriched subtype was designed to meet the following criteria:

  1. The syntax must be extremely simple to parse, so that even teletype-oriented mail systems can easily strip away the formatting information and leave only the readable text.
  2. The syntax must be extensible to allow for new formatting commands that are deemed essential for some application.
  3. If the character set in use is ASCII or an 8-bit ASCII superset, then the raw form of the data must be readable enough to be largely unobjectionable in the event that it is displayed on the screen of the user of a non-MIME-conformant mail reader.
  4. The capabilities must be extremely limited, to ensure that it can represent no more than is likely to be representable by the user's primary word processor. While this limits what can be sent, it increases the likelihood that what is sent can be properly displayed.

Other text formatting standards hit some of these criteria, like HTML and SGML, which are super popular on the Internet ๐Ÿ‘€. But there are two big reasons this document pushes text/enriched for Internet mail over those other standards:

  1. Most MIME-aware Internet mail applications are already able to either properly format text/enriched mail or, at the very least, are able to strip out the formatting commands and display the readable text. The same is not true for HTML or SGML.
  2. The current RFC on HTML [RFC-1866] and Internet Drafts on SGML have many features which are not necessary for Internet mail, and are missing a few capabilities that text/enriched already has.

So this document is promoting text/enriched until other Internet standards come into more widespread use ๐Ÿ’…. For those who still want to use HTML, Appendix B of this document contains a very simple C program that converts text/enriched to HTML 2.0, which is described in [RFC-1866] ๐Ÿ“.

Syntax ๐Ÿงฉ

The syntax of "text/enriched" is very simple ๐Ÿฅฐ. It represents text in a single character set, US-ASCII by default, although a different character set can be specified with the "charset" parameter. (The semantics of text/enriched in non-ASCII character sets are discussed later in this document.) All characters represent themselves, except for the < character (ASCII 60), which marks the beginning of a formatting command. A literal less-than sign (<) can be represented by a sequence of two such characters, <<.

Formatting instructions consist of formatting commands surrounded by angle brackets (<>, ASCII 60 and 62). Each formatting command may be no more than 60 characters in length, all in US-ASCII, and restricted to the alphanumeric and hyphen (-) characters. Formatting commands may be preceded by a solidus (/, ASCII 47), which makes them negations, and such negations must always exist to balance the initial opening commands. So if the formatting command <bold> appears at some point, there must later be a </bold> to balance it. (NOTE: The 60 character limit on formatting commands does NOT include the <, >, or / characters that might be attached to such commands.)

Formatting commands are always case-insensitive. That means "bold" and "BoLd" are equivalent in effect, if not in good taste ๐Ÿ’€.

Line break rules ๐Ÿซง

Line breaks (CRLF pairs in standard network representation) are handled specially ๐Ÿฆ‹. In particular, isolated CRLF pairs are translated into a single SPACE character. Sequences of N consecutive CRLF pairs, however, are translated into N-1 actual line breaks. This lets long lines of data look natural despite how often Internet mailers wrap lines โœจ. When preparing the data for mail transport, isolated line breaks should be inserted wherever necessary to keep each line shorter than 80 characters. When preparing such data for presentation to the user, isolated line breaks should be replaced by a single SPACE character, and N consecutive CRLF pairs should be presented to the user as N-1 line breaks.

Thus text/enriched data that looks like this:

This is
a single
line

This is the
next line.


This is the
next section.

should be displayed by a text/enriched interpreter as follows:

This is a single line
This is the next line.

This is the next section.

The formatting commands are described in the following sections, and not all of them will be implemented by every implementation ๐ŸŒธ.

Formatting Commands ๐ŸŽจ

The text/enriched formatting commands all begin with <commandname> and end with </commandname>, and they affect the formatting of the text between those two tokens ๐Ÿ’œ. The commands are described here, grouped according to type.

Parameter Command ๐Ÿงš

Some of the formatting commands may require one or more associated parameters. The param command is a special formatting command used to include these parameters ๐Ÿ“.

param

Marks the affected text as command parameters. These are to be interpreted or ignored by the text/enriched interpreter, but not shown to the reader ๐Ÿ™ˆ. The param command always immediately follows some other formatting command, and the parameter data indicates some additional information about the formatting that is to be done. The syntax of the parameter data (whatever appears between the initial <param> and the terminating </param>) is defined for each command that uses it. However, it is always required that the format of such data must not contain nested param commands, and either must not use the < character or must use it in a way that is compatible with text/enriched parsing. That is, the end of the parameter data should be recognizable with either of two algorithms: simply searching for the first occurrence of </param>, or parsing until a balanced </param> command is found. In either case, however, the parameter data should not be shown to the human reader ๐Ÿซถ.

Font-Alteration Commands โœจ

okay bestie, these commands are all about the look of your text ๐Ÿ’… they change the font, but they do NOT touch the indentation or justification. the vibe shifts, the margins stay put ๐Ÿซถ

  • Bold: causes the affected text to be in a bold font ๐Ÿ’ช nested bold commands give the same effect as one single bold command.
  • Italic: causes the affected text to be in an italic font ๐Ÿฆ‹ nested italic commands give the same effect as one single italic command.
  • Underline: causes the affected text to be underlined โœ๏ธ nested underline commands give the same effect as one single underline command.
  • Fixed: causes the affected text to be in a fixed width font ๐ŸŽ€ nested fixed commands give the same effect as one single fixed command.
  • FontFamily: causes the affected text to be displayed in a specified typeface ๐ŸŒธ the fontfamily command needs a parameter, set using the param command. the parameter data is a case-insensitive string with the name of a font family. any currently available font family name (e.g. Times, Palatino, Courier, etc.) may be used, including font families from commercial type foundries like Adobe, BitStream, or any other such foundry. just note that implementations should only use the general font family name, not the specific font name (e.g. use Times, not TimesRoman nor TimesBoldItalic). when nested, the inner fontfamily command takes precedence. also, fontfamily is advisory only ๐Ÿ™ˆ it should not be expected that other implementations will honor the typeface info in this command, since font capabilities vary drastically from system to system.
  • Color: causes the affected text to be displayed in a specified color ๐ŸŒˆ the color command needs a parameter, set using the param command. the parameter data can be one of the following:
red
blue
green
yellow
cyan
magenta
black
white

or an RGB color value in the form:

####,####,####

where # is a hexadecimal digit 0 through 9, A through F, or a through f. the three 4-digit hexadecimal values are the RGB values for red, green, and blue respectively, where each component is an unsigned value between 0 (0000) and 65535 (FFFF). the default color for the message is unspecified, though black is a common choice in many environments. when nested, the inner color command takes precedence.

  • Smaller: causes the affected text to be in a smaller font ๐Ÿ“ it is recommended that the font size change by two points, but other amounts may be more appropriate in some environments. nested smaller commands make ever smaller fonts, up to the limits of what the implementation can reasonably display, and after that further smaller commands have no incremental effect.
  • Bigger: causes the affected text to be in a bigger font ๐ŸŒŸ it is recommended that the font size change by two points, but other amounts may be more appropriate in some environments. nested bigger commands make ever bigger fonts, up to the limits of what the implementation can reasonably display, and after that further bigger commands have no incremental effect.

while bigger and smaller are basically opposites, it is not recommended, for example, that <smaller> be used to end the effect of <bigger>. the proper way to end it is </bigger> ๐Ÿ’…

the capabilities of every implementation vary, so some implementations won't be able to act on some font-alteration commands ๐Ÿ˜ญ that's okay though! an implementation should still display the text to the user in a reasonable fashion. not being able to show a particular font family, color, or other text attribute does NOT mean the implementation should fail to display the text at all.

Fill/Justification/Indentation Commands ๐ŸŽ€

okay so by default, text/enriched text is meant to be displayed fully filled ๐Ÿซง (that means using the rules for replacing CRLF pairs with spaces or removing them as appropriate), with appropriate kerning and letter-tracking, and using the maximum available margins that suit the receiving user agent software.

these commands change that default ๐Ÿ’– each one forces a line break before and after the formatting environment if there isn't already one. for example, if one of these commands shows up anywhere other than the beginning of a line of text as presented, a new line is started.

  • Center: causes the affected text to be centered ๐Ÿงš
  • FlushLeft: causes the affected text to be left-justified with a ragged right margin ๐ŸŒฟ
  • FlushRight: causes the affected text to be right-justified with a ragged left margin ๐Ÿ‘
  • FlushBoth: causes the affected text to be filled and padded so it gets smooth left and right margins, aka fully justified โœจ
  • ParaIndent: causes the running margins of the affected text to be moved in ๐Ÿฉฐ the recommended indentation change is the width of four characters, but this may differ among implementations. the paraindent command needs a parameter, set using the param command. the parameter data is a comma-separated list of one or more of the following:
    • Left: causes the running left margin to be moved to the right.
    • Right: causes the running right margin to be moved to the left.
    • In: causes the first line of the affected paragraph to be indented in addition to the running margin. the remaining lines stay flush to the running margin.
    • Out: causes all lines except the first line of the affected paragraph to be indented in addition to the running margin. the first line stays flush to the running margin.
  • Nofill: causes the affected text to be displayed without filling ๐Ÿ™Œ that means the text is displayed without using the rules for replacing CRLF pairs with spaces or removing consecutive sequences of CRLF pairs. BUT the current state of the margins and justification is still honored, so any indentation or justification commands still apply to the text inside the nofill scope.

the center, flushleft, flushright, and flushboth commands are mutually exclusive, and when nested, the inner command takes precedence ๐Ÿ‘‘

the nofill command is mutually exclusive with the in and out parameters of the paraindent command. if they show up in the same scope, their behavior is undefined ๐Ÿ’€

the parameter data for paraindent can contain multiple occurrences of the same parameter (i.e. left, right, in, or out). each occurrence causes the text to be indented further in the manner that parameter indicates. nested paraindent commands also indent the affected text further according to their parameters. just remember that in and out are mutually exclusive ๐Ÿ™ˆ if they show up together, or if nested paraindent commands contain both of them, their behavior is undefined.

for the in and out parameters, a paragraph is text that's delimited by line breaks after applying the rules for replacing CRLF pairs with spaces or removing consecutive sequences of CRLF pairs. for example, inside an out, the line after each CRLF is made flush with the running margin, and the subsequent lines get indented. inside an in, the first line after each CRLF is indented, and the subsequent lines stay flush to the running margin ๐Ÿซถ

whether text is justified by default (that is, whether the default environment is flushleft, flushright, or flushboth) is unspecified ๐ŸŒธ it depends on the user's preferences, the capabilities of the local software and hardware, and the nature of the character set in use. on systems where full justification is considered undesirable, the flushboth environment may be identical to the default environment. and note that full justification should never be performed inside center, flushleft, flushright, or nofill environments. also, for some non-ASCII character sets, full justification may be fundamentally inappropriate ๐ŸŒ

one more tea โ˜• [RFC-1563] defined two extra indentation commands, "Indent" and "IndentRight". these didn't force a line break, so their behavior was unpredictable, since it depended on the margins and character sizes a particular implementation used. so their use is deprecated, and they should be ignored just like other unrecognized commands ๐Ÿฅ€

Markup Commands โœจ

Okay bestie, this section is different from the other text/enriched commands because these ones are declarative markup commands ๐ŸŽ€. text/enriched is not a full markup language, it's just a simple way to show common formatting. So the markup commands are kept to a bare minimum ๐Ÿ™ˆ. Each one only made the list because it was considered so prevalent or necessary in email that it deserved a spot ๐Ÿ’….

Excerpt ๐Ÿ’ฌ

The excerpt command makes the affected text get read as a textual excerpt from another source, probably a message someone is replying to. Usually this is shown with indentation and an alternate font, or by indenting the lines and putting > in front of them, but the choice is up to the implementation ๐Ÿซถ. Also, just like the justification commands, the excerpt command implicitly begins and ends with a line break if there isn't one already โœจ.

Nested excerpt commands are totally acceptable ๐ŸŒˆ and should be interpreted as meaning the excerpted text was taken from yet another source. Again, you can show this with extra indentation, different colors, etc. It's giving layers ๐Ÿ’œ.

Optionally, the excerpt command can take a parameter by using the param command. The format of the data is unspecified, but it's meant to uniquely identify the text the excerpt came from ๐Ÿ”. With that info, an implementation should be able to uniquely identify the source of any excerpt, especially if two or more excerpts in the message come from the same source, and show it in a way that makes that obvious to the user ๐Ÿฆ‹.

Lang ๐ŸŒ

The lang command makes the affected text get interpreted as belonging to a particular language. This is most useful when two different languages use the same character set but might need a different font or formatting depending on the language ๐Ÿ“. For instance, Chinese and Japanese have similar character glyphs, and in some character sets like UNICODE they share common code points. But it's considered super important that different fonts get used for the two languages, especially if they show up together, so the meaning doesn't get lost ๐Ÿ˜ญ. Language info can also allow fancier text handling, like spell checking or hyphenation ๐Ÿงš.

The lang command requires a parameter using the param command. The parameter data can be any of the language tags specified in [RFC-1766], "Tags for the Identification of Languages". These tags are the two letter language codes taken from [ISO-639], or can be other language codes that are registered according to the instructions in the Langauge Tags RFC. Consult that memo for further information ๐Ÿ“š.


Balancing and Nesting of Formatting Commands ๐Ÿงฉ

Pairs of formatting commands must be properly balanced and nested. So a proper way to describe text in bold italics is:

<bold><italic>the-text</italic></bold>

or, alternately,

<italic><bold>the-text</bold></italic>

but, in particular, the following is illegal text/enriched:

<bold><italic>the-text</bold></italic>

The nesting requirement puts a slightly higher burden on the composers of text/enriched bodies ๐Ÿ˜ค, but it potentially simplifies text/enriched displayers by letting them be stack-based ๐Ÿฅž. The main goal of text/enriched is to be simple enough to make multifont, formatted email widely readable, so that people with the capability to send it can do so with confidence ๐Ÿ’–. So a bit more complexity in the composing software was deemed a reasonable tradeoff for simpler reading software. Still, implementors of text/enriched readers are encouraged to follow the general Internet guidelines of being conservative in what you send and liberal in what you accept ๐Ÿซถ. Implementations that can do so are encouraged to deal reasonably with improperly nested text/enriched data.


Unrecognized formatting commands ๐Ÿคทโ€โ™€๏ธ

Implementations must regard any unrecognized formatting command as "no-op" commands, meaning commands that have no effect. This keeps things open for future extensions to text/enriched ๐Ÿ”ฎ. Private extensions may be defined using formatting commands that begin with X-, which is kind of like how Internet mail header field names work ๐Ÿ’Œ.

In order to formally define extended commands, a new Internet document should be published ๐Ÿ“„.


White Space in Text/enriched Data ๐ŸŒธ

No special behavior is required for the SPACE or TAB (HT) character. It is recommended, however, that, at least when fixed-width fonts are in use, the common semantics of the TAB (HT) character should be observed. That means it moves to the next column position that is a multiple of 8. (In other words, if a TAB (HT) occurs in column n, where the leftmost column is column 0, then that TAB (HT) should be replaced by 8-(n mod 8) SPACE characters.) ๐Ÿ“ It should also be noted that some mail gateways are notorious for losing (or, less commonly, adding) white space at the end of lines ๐Ÿ™ƒ. So reliance on SPACE or TAB characters at the end of a line is not recommended.


Initial State of a text/enriched interpreter ๐Ÿ

text/enriched is assumed to begin with filled text in a variable-width font, in a normal typeface, at a size that's average for the current display and user โœจ. The left and right margins are assumed to be maximal, which means at the leftmost and rightmost acceptable positions ๐Ÿ“.


Non-ASCII character sets ๐ŸŒ

One of the great benefits of MIME is being able to use different varieties of non-ASCII text in messages ๐ŸŒ. To use non-ASCII text in a message, a charset parameter is normally specified in the Content-type line to show which character set is being used. For the purposes of this RFC, any legal MIME charset parameter can be used with the text/enriched Content-type. But there are two difficulties that come up with the text/enriched Content-type when non-ASCII text is wanted ๐Ÿ˜ฉ. The first problem is when a user wants to create text that would normally need multiple non-ASCII character sets in the same text/enriched message. The second problem is an ambiguity caused by the text/enriched use of the < character in formatting commands.

Using multiple non-ASCII character sets ๐Ÿ”€

Normally, if a user wants to produce text with characters from entirely different character sets in the same MIME message (for example, Russian Cyrillic characters from ISO 8859-5 and Hebrew characters from ISO 8859-8), a multipart message is used ๐Ÿงฉ. Every time a new character set is wanted, a new MIME body part is started with the different character set specified in the charset parameter of the Content-type line. However, using multiple character sets this way in text/enriched messages causes problems ๐Ÿ˜ต. Since a change in the charset parameter requires a new part, text/enriched formatting commands used in the first part would not be able to apply to text in later parts. It's not possible for text/enriched formatting commands to apply across MIME body part boundaries ๐Ÿšง.

[RFC-1341] tried to get around this problem in the now obsolete text/richtext format by introducing different character set formatting commands like iso-8859-5 and us-ascii. But this, or even a more general solution along the same lines, is still undesirable ๐Ÿ™…โ€โ™€๏ธ. It's common for a MIME application to decide, for example, which character font resources or character lookup tables it will need based on the information in the charset parameter of the Content-type line, before it even starts to interpret or display the data in that body part. If the text/enriched interpreter could then change the character set, perhaps to one completely different from the charset specified in the Content-type line (with potentially very different resource requirements), that would put way too much burden on the text/enriched interpreter itself ๐Ÿฅต.

Therefore, if multiple types of non-ASCII characters are wanted in a text/enriched document, one of the following two methods must be used ๐Ÿ‘‘:

  1. For cases where the different types of non-ASCII text can be limited to their own paragraphs with distinct formatting, a multipart message can be used with each part having a Content-Type of text/enriched and a different charset parameter. The one caveat with this method is that each new part must start in the initial state for a text/enriched document. That means all of the text/enriched commands in the preceding part must be properly balanced with ending commands before the next text/enriched part begins. Also, each text/enriched part must begin a new paragraph ๐ŸŒธ.
  2. If different types of non-ASCII text are going to appear in the same line or paragraph, or if text/enriched formatting (e.g. margins, typeface, justification) is required across several different types of non-ASCII text, a single text/enriched body part should be used with a character set specified that contains all of the required characters. For example, a charset parameter of "UNICODE-1-1-UTF-7" as specified in [RFC-1642] could be used for such purposes ๐Ÿง . Not only does UNICODE contain all of the characters that can be represented in all of the other registered ISO 8859 MIME character sets, but UTF-7 is fully compatible with other aspects of the text/enriched standard, including the use of the < character referred to below ๐Ÿซถ. Any other character sets specified for use in MIME that contain different types of non-ASCII text can also be used in these situations ๐Ÿฆ‹.

Use of the "<" character in formatting commands โš ๏ธ

If the character set specified by the charset parameter on the Content-type line is anything other than "US-ASCII", the text being described by text/enriched formatting commands is in a non-ASCII character set ๐ŸŒ. However, the commands themselves are still the same ASCII commands defined in this document ๐Ÿ’…. This creates an ambiguity only for the < character, the octet with numeric value 60 ๐Ÿ‘€. In single byte character sets, like the ISO-8859 family, this is not a problem, because the octet 60 can be quoted by including it twice, just like in ASCII ๐Ÿ™Œ. It gets more complicated in multi-byte character sets, where the octet 60 might appear at any point in the byte sequence for any of several characters ๐Ÿ˜ญ.

In practice, though, most multi-byte character sets address this problem internally ๐ŸŽ‰. For example, the UNICODE character sets can use the UTF-7 encoding, which keeps all of the important ASCII characters in their single byte form. The ISO-2022 family of character sets can use certain character sequences to switch back into ASCII at any moment โœจ. Therefore it is specified that, before text/enriched formatting commands, the prevailing character set should be "switched back" into ASCII, and that only those characters which would be interpreted as < in plain text should be interpreted as token delimiters in text/enriched ๐Ÿงš.

The question of what to do for hypothetical future character sets that do not subsume ASCII is not addressed in this memo ๐Ÿ”ฎ.

Minimal text/enriched conformance โœจ

Okay bestie, here's the bare minimum for being a legit text/enriched implementation ๐Ÿ’… A minimal text/enriched implementation is one that turns << into <, deletes everything between a <param> command and the next balancing </param> command, strips out every other formatting command (anything wrapped in angle brackets) ๐Ÿซถ, and, outside of <nofill> environments, turns any series of n CRLFs into n-1 CRLFs and turns any lone CRLF pairs into SPACE.


Notes for Implementors ๐ŸŒธ

Okay so future mail systems are gonna want rich text features WAY beyond what text/enriched covers right now, and honestly? Valid ๐ŸŒˆ The whole point of text/enriched is to give everyone a shared format for all that stuff, so a big chunk of it can still be understood by software talking to other software โœจ. A fancier program can keep using text/enriched as its basic representation, extend it with brand-new formatting commands, and tuck its own private system info inside <param> constructs. As those systems grow, future published specs will keep refining text/enriched, but this version is the foundation all that evolving gets built on ๐Ÿฆ‹.

An expected common way sophisticated mail programs will make text/enriched is as part of a multipart/alternative construct ๐Ÿ’Œ. Like, a mail agent that can make ODA mail can send a more widely interoperable version by generating both a text/enriched and an ODA version of the same data, e.g.:

Content-type: multipart/alternative; boundary=foo

--foo
Content-type: text/enriched

[text/enriched version of data]
--foo Content-type: application/oda

[ODA version of data]
--foo--

If someone reads that message with a MIME-conformant mail reader that understands ODA, they'll see the ODA version. Otherwise, they get the text/enriched version ๐ŸŽ€.

Sometimes a system just can't combine certain text/enriched formatting commands, while others can do it easily ๐Ÿ™ˆ. Like, <bold> plus <italic> might give you bold italics on systems that support those fonts, but some systems can make text bold or italic, not both ๐Ÿ’€. In those cases, the most recently issued (innermost) recognized formatting command should be preferred ๐Ÿ‘‘.

One of the biggest goals for text/enriched was making it so simple that even text-only mailers would bother writing enriched-to-plain-text translators, so enriched text becomes "safe" to use super widely ๐ŸŒท. To prove how simple it is, Appendix A has an extremely simple C program that turns text/enriched input into plain text output โœจ.


Extensions to text/enriched ๐Ÿงš

It's giving extension energy ๐Ÿ’œ Various mail system authors will totally want to extend text/enriched. The simple syntax, plus the rule that unrecognized formatting commands should simply be ignored, are both designed to make extending it way easier ๐ŸŒˆ.


An Example ๐ŸŽ€

Putting it all together, here's this "text/enriched" body fragment:

From: Nathaniel Borenstein <nsb@bellcore.com>
To: Ned Freed <ned@innosoft.com>
Content-type: text/enriched

<bold>Now</bold> is the time for <italic>all</italic>
good men
<smaller>(and <<women>)</smaller> to
<ignoreme>come</ignoreme>

to the aid of their


<color><param>red</param>beloved</color>
country.

By the way,
I think that <paraindent><param>left</param><<smaller>

</paraindent>should REALLY be called

<paraindent><param>left</param><<tinier></paraindent>
and that I am always right.

-- the end

And it represents the following formatted text (which will, no doubt, look kinda cryptic in the text-only version of this document ๐Ÿ™ˆ):

Now is the time for all good men (and <women>) to come
to the aid of their

beloved country.
By the way, I think that
     <smaller>
should REALLY be called
     <tinier>
and that I am always right.
-- the end

where the word "beloved" would be in red on a color display ๐Ÿ“.


Security Considerations ๐Ÿ”’

Okay, no drama here ๐Ÿ˜Œ Security issues are not discussed in this memo, because the mechanism raises no security issues. Zero security issues, periodt ๐Ÿ’….


Authors' Addresses ๐Ÿ“ฌ

For more information, the authors of this document may be contacted via Internet mail:

Peter W. Resnick
QUALCOMM Incorporated
6455 Lusk Boulevard
San Diego, CA 92121-2779

Phone: +1 619 587 1121
Fax: +1 619 658 2230
EMail: presnick@qualcomm.com
Amanda Walker
InterCon Systems Corporation
950 Herndon Parkway
Herndon, VA 22070

Phone: +1 703 709 5500
Fax: +1 703 709 5555
EMail: amanda@intercon.com

Acknowledgements ๐Ÿซถ

The authors gratefully acknowledge the input of many contributors, readers, and implementors of the specification in this document ๐Ÿ’–. Special shoutout to Nathaniel Borenstein, the original author of RFC 1563 ๐Ÿ‘‘.


References ๐Ÿ“š

  • [RFC-1341] Borenstein, N., and N. Freed, "MIME (Multipurpose Internet Mail Extensions): Mechanisms for Specifying and Describing the Format of Internet Message Bodies", 06/11/1992.
  • [RFC-1521] Borenstein, N., and N. Freed, "MIME (Multipurpose Internet Mail Extensions) Part One: Mechanisms for Specifying and Describing the Format of Internet Message Bodies", 09/23/1993.
  • [RFC-1523] Borenstein, N., "The text/enriched MIME Content-type", 09/23/1993.
  • [RFC-1563] Borenstein, N., "The text/enriched MIME Content-type", 01/10/1994.
  • [RFC-1642] Goldsmith, D., Davis, M., "UTF-7 - A Mail-Safe Transformation Format of Unicode", 07/13/1994.
  • [RFC-1766] Alvestrand, H., "Tags for the Identification of Languages", 03/02/1995.
  • [RFC-1866] Berners-Lee, T., and D. Connolly, D., "Hypertext Markup Language - 2.0", 11/03/1995.

Appendix A--A Simple enriched-to-plain Translator in C ๐Ÿฆ‹

One of the major goals in the design of the text/enriched subtype of the text Content-Type is to make formatted text so simple that even text-only mailers will implement enriched-to-plain-text translators, so multifont text becomes "safe" to use very widely ๐Ÿ’…. To prove the point, here's a simple C program that turns text/enriched input into plain text output. Heads up: this program assumes the local newline convention (the single character represented by "\n"), but special CRLF handling might be needed on some systems โญ.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main() {
    int c, i, paramct=0, newlinect=0, nofill=0;
    char token[62], *p;

    while ((c=getc(stdin)) != EOF) {
        if (c == '<') {
            if (newlinect == 1) putc(' ', stdout);
            newlinect = 0;
            c = getc(stdin);
            if (c == '<') {
                if (paramct <= 0) putc(c, stdout);
            } else {
                ungetc(c, stdin);
                for (i=0, p=token;
                    (c=getc(stdin)) != EOF && c != '>'; i++) {
                    if (i < sizeof(token)-1)
                        *p++ = isupper(c) ? tolower(c) : c;
                }
                *p = '\0';
                if (c == EOF) break;
                if (strcmp(token, "param") == 0)
                    paramct++;
                else if (strcmp(token, "nofill") == 0)
                    nofill++;
                else if (strcmp(token, "/param") == 0)
                    paramct--;
                else if (strcmp(token, "/nofill") == 0)
                    nofill--;
            }
        } else {
            if (paramct > 0)

                ; /* ignore params */
            else if (c == '\n' && nofill <= 0) {
                if (++newlinect > 1) putc(c, stdout);
            } else {
                if (newlinect == 1) putc(' ', stdout);
                newlinect = 0;
                putc(c, stdout);
            }
        }
    }
    /* The following line is only needed with line-buffering */
    putc('\n', stdout);
    exit(0);
}

It should be noted that one can do considerably better than this in displaying text/enriched data on a dumb terminal โœจ. In particular, one can replace font information such as "bold" with textual emphasis (like *this* or _T_H_I_S_). One can also properly handle the text/enriched formatting commands regarding indentation, justification, and others ๐ŸŒธ. However, the above program is all that's necessary to present text/enriched on a dumb terminal without showing the user any formatting artifacts ๐Ÿซถ.


Appendix B--A Simple enriched-to-HTML Translator in C ๐ŸŒˆ

It is fully expected that other text formatting standards like HTML and SGML will supplant text/enriched in Internet mail ๐Ÿ’ซ. It's also likely that, as this happens, recipients of text/enriched mail will wish to view that mail with an HTML viewer. So here's a simple C program that converts text/enriched to HTML. Since the current version of HTML at the time of this document's publication is HTML 2.0 defined in [RFC-1866], this program converts to that standard ๐Ÿ’œ. A few text/enriched commands have no HTML 2.0 equivalent. For those, the program just puts the commands into processing instructions, meaning they're surrounded by "<?" and ">" ๐Ÿงš. As in Appendix A, the program assumes the local newline convention (the single character represented by "\n"), but special CRLF handling might be necessary on some systems ๐Ÿ“.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

okay bestie, the translator's main loop is finally here, and it's giving pure main character energy ๐Ÿ’…๐ŸŽ€

main() {
    int c, i, paramct=0, nofill=0;
    char token[62], *p;

    while((c=getc(stdin)) != EOF) {
        if(c == '<') {
            c = getc(stdin);
            if(c == '<') {
                fputs("&lt;", stdout);
            } else {
                ungetc(c, stdin);
                for (i=0, p=token;
                    (c=getc(stdin)) != EOF && c != '>'; i++) {
                    if (i < sizeof(token)-1)
                        *p++ = isupper(c) ? tolower(c) : c;
                }
                *p = '\0';
                if(c == EOF) break;
                if(strcmp(token, "/param") == 0) {
                    paramct--;
                    putc('>', stdout);
                } else if(paramct > 0) {
                    fputs("&lt;", stdout);
                    fputs(token, stdout);
                    fputs("&gt;", stdout);
                } else {
                    putc('<', stdout);
                    if(strcmp(token, "nofill") == 0) {
                        nofill++;
                        fputs("pre", stdout);
                    } else if(strcmp(token, "/nofill") == 0) {
                        nofill--;
                        fputs("/pre", stdout);
                    } else if(strcmp(token, "bold") == 0) {
                        fputs("b", stdout);
                    } else if(strcmp(token, "/bold") == 0) {
                        fputs("/b", stdout);
                    } else if(strcmp(token, "italic") == 0) {
                        fputs("i", stdout);
                    } else if(strcmp(token, "/italic") == 0) {
                        fputs("/i", stdout);
                    } else if(strcmp(token, "fixed") == 0) {
                        fputs("tt", stdout);
                    } else if(strcmp(token, "/fixed") == 0) {
                        fputs("/tt", stdout);
                    } else if(strcmp(token, "excerpt") == 0) {
                        fputs("blockquote", stdout);
                    } else if(strcmp(token, "/excerpt") == 0) {
                        fputs("/blockquote", stdout);
                    } else {

                        putc('?', stdout);
                        fputs(token, stdout);
                        if(strcmp(token, "param") == 0) {
                            paramct++;
                            putc(' ', stdout);
                            continue;
                        }
                    }
                    putc('>', stdout);
                }
            }
        } else if(c == '>') {
            fputs("&gt;", stdout);
        } else if (c == '&') {
            fputs("&amp;", stdout);
        } else {
            if(c == '\n' && nofill <= 0 && paramct <= 0) {
                while((i=getc(stdin)) == '\n') fputs("<br>", stdout);
                ungetc(i, stdin);
            }
            putc(c, stdout);
        }
    }
    /* The following line is only needed with line-buffering */
    putc('\n', stdout);
    exit(0);
}

and that's the whole translator ๐Ÿซถโœจ it reads everything from stdin, swaps the enriched tags for their HTML buddies, and spits out the result. no cap, it's iconic ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from