RFC 1896
The text/enriched MIME Content-type
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:
- 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.
- The syntax must be extensible to allow for new formatting commands that are deemed essential for some application.
- 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.
- 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:
- Most MIME-aware Internet mail applications are already able to either properly format
text/enrichedmail 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. - 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/enrichedalready 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
fontfamilycommand needs a parameter, set using theparamcommand. 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. useTimes, notTimesRomannorTimesBoldItalic). when nested, the innerfontfamilycommand takes precedence. also,fontfamilyis 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
colorcommand needs a parameter, set using theparamcommand. 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
paraindentcommand needs a parameter, set using theparamcommand. 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
nofillscope.
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 ๐:
- 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-Typeoftext/enrichedand a differentcharsetparameter. The one caveat with this method is that each new part must start in the initial state for atext/enricheddocument. That means all of thetext/enrichedcommands in the preceding part must be properly balanced with ending commands before the nexttext/enrichedpart begins. Also, eachtext/enrichedpart must begin a new paragraph ๐ธ. - If different types of non-ASCII text are going to appear in the same line or paragraph, or if
text/enrichedformatting (e.g. margins, typeface, justification) is required across several different types of non-ASCII text, a singletext/enrichedbody part should be used with a character set specified that contains all of the required characters. For example, acharsetparameter 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 thetext/enrichedstandard, 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("<", 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("<", stdout);
fputs(token, stdout);
fputs(">", 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(">", stdout);
} else if (c == '&') {
fputs("&", 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
- ietf: rfc1896 1996-02
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms