NAME
mhbuild - translate MIME composition drafts for nmh messagesSYNOPSIS
mhbuild
[-help] [-version] file [-auto | -noauto]
[-list | -nolist] [-realsize | -norealsize]
[-headers | -noheaders] [-directives |
-nodirectives] [-rfc934mode | -norfc934mode]
[-contentid | -nocontentid] [-verbose |
-noverbose] [-disposition | -nodisposition]
[-headerencoding encoding-algorithm |
-autoheaderencoding] [-maxunencoded line-length]
[-dist]
DESCRIPTION
The mhbuild command will translate a MIME composition draft into a valid MIME message. mhbuild creates multi-media messages as specified in RFCs 2045 through 2049. This includes the encoding of message headers as specified by RFC 2047, and, additionally, the encoding of MIME parameters as specified in RFC 2231. If you specify the name of the composition file as “-”, then mhbuild will accept the composition draft on the standard input. If the translation of this input is successful, mhbuild will output the new MIME message to the standard output. This argument must be the last argument on the command line. Otherwise, if the file argument to mhbuild is the name of a valid composition file, and the translation is successful, mhbuild will replace the original file with the new MIME message. It will rename the original file to start with the “,” character and end with the string “.orig”, e.g., if you are editing the file “draft”, it will be renamed to “,draft.orig”. This allows you to easily recover the mhbuild input file.Listing the Contents
The -list switch tells mhbuild to list the table of contents associated with the MIME message that is created. The -headers switch indicates that a one-line banner should be displayed above the listing. The -realsize switch tells mhbuild to evaluate the “native” (decoded) format of each content prior to listing. This provides an accurate count at the expense of a small delay. If the -verbose switch is present, then the listing will show any “extra” information that is present in the message, such as comments in the “Content-Type” header. If the -disposition switch is present, then the listing will show any relevant information from the “Content-Disposition” header.Simplified Attachment Interface
For users who wish to simply attach files to text content, mhbuild will scan the composition file for “Attach” headers. An “Attach” header contains a filename that will be appended to the message using normal MIME encapsulation rules. One filename is allowed per “Attach” header, but multiple “Attach” headers are allowed per composition file. These files will be appended after any other MIME content, including any content specified by mhbuild directives (see below). See send(1) for more details. By default, the Content-Disposition will be “attachment”. mhbuild looks for user profile and mhn.defaults entries of the form
mhbuild-disposition-type/subtype
or
mhbuild-disposition-type
to supply the disposition value. The only supported values are
“attachment” and “inline”.
Convert Interface
The convert interface is a powerful mechanism that supports replying to MIME messages. These placeholders are used in the following description:- TYPE
- content type/subtype
- CONVERTER
- external program, and any fixed arguments, to convert content, such as from a request to a reply
- ARGSTRING
- arguments to pass from repl to CONVERTER
- FILE
- full path of message being replied to
Nmh-mhbuild-file-TYPE: FILE Nmh-mhbuild-args-TYPE: ARGSTRING
mhbuild-convert-TYPE: CONVERTER
It's a fatal error if no such entry is found for TYPE. An empty entry,
e.g.,
mhbuild-convert-text/html:
excludes parts of that TYPE from the draft.
The mhn.defaults file contains default mhbuild-convert-text/html
and mhbuild-convert-text/plain entries. Profile entries can be used to
override corresponding mhn.defaults entries, as usual. Text converters
should limit text line lengths to a maximum of 78 characters, and must limit
them to a maximum of 998 characters, per RFC 5322 Sec. 2.1.1.
For each TYPE part in FILE, mhbuild runs CONVERTER
ARGSTRING on the content of the part. Each part in FILE that has no
corresponding TYPE entry in the profile or mhn.defaults is excluded
from the draft; the user can include them using mhbuild directives.
repl inserts Nmh-mhbuild-text/html: and
Nmh-mhbuild-text/plain: pseudoheaders in every draft. The user can
prevent insertion of content parts of either of those types by putting
corresponding empty entries in their profile.
Only the highest precedence alternative with a supported TYPE of a
multipart/alternative part is used.
mhn.defaults.sh selects the text/html-to-text/plain converter at install time.
It includes iconv and par, or fmt, in the pipeline only
if they are found.
Some content types require the addition of parameters to the Content-Type
header, such as “method=REPLY” for text/calendar. mhbuild
looks for a Content-Type header, followed by a blank line, at the beginning of
the converter output. If one is found, it is used for the corresponding part
in the reply draft.
The convert interface doesn't support different ARGSTRINGs or different
converters for different parts of the same TYPE. That would require
associating parts by part number with the ARGSTRINGs or converters.
Instead, that can be done (currently, without using the convert support), with
mhbuild directives as described below, e.g.,
#text/html; charset=utf-8 *8bit | mhstore
-noverbose -part 42.7 -outfile - | w3m -dump -cols 64 -T text/html -O
utf-8
The only way to mix convert pseudoheaders and mhbuild directives is to
insert the directives before mhbuild is run, which is typically done by
entering mime at the “What now?” prompt, or with an
-editor mhbuild switch.
If there are any Nmh-mhbuild- pseudoheaders in the composition file,
mhbuild divides the translation into two stages. The first stage
includes all translations except encoding of text content. The second stage
encodes text content as needed. This allows the user to edit the text prior to
encoding. The second stage, along with the first stage if it had not yet been
performed, is selected with the -auto switch.
These (optional) setup steps can make the convert support easier to use:
- 1)
- If the par program is installed on your system, it will be set by default (in mhn.defaults) to filter the converter output. It helps to set the PARINIT environment variable, as described in par(1).
- 2)
- Add this line to your profile:
- mhbuild-next: $EDITOR
- assuming that your EDITOR environment variable is set; if not, replace EDITOR with the name of your editor. Without that profile entry, a response of “e[dit]” at the What now? prompt will require specification of your editor if an -editor mhbuild switch is used.
- 3)
- If using repl, source the Bourne-shell compatible
functions in /usr/share/doc/nmh/contrib/replaliases.
Translating the Composition File
mhbuild is essentially a filter to aid in the composition of MIME messages. mhbuild will convert an mhbuild “composition file” into a valid MIME message. An mhbuild “composition file” is just a file containing plain text that is interspersed with various mhbuild directives. When this file is processed by mhbuild, the various directives will be expanded to the appropriate content, and will be encoded according to the MIME standards. The resulting MIME message can then be sent by electronic mail. The formal syntax for a mhbuild composition file is defined at the end of this document, but the ideas behind this format are not complex. Basically, the body contains one or more contents. A content consists of either a directive, indicated with a “#” as the first character of a line; or, plaintext (one or more lines of text). The continuation character, “\“, may be used to enter a single directive on more than one line, e.g.,#image/png \ /home/foobar/junk/picture.png
#off #include <stdio.h> puts("hello, world!"); #pop
#audio/basic |raw2audio -F < /usr/lib/sound/giggle.au
- %a
- Insert parameters from directive
- %f
- Insert filename containing content
- %F
- %f, and stdout is not re-directed
- %s
- Insert content subtype
- %%
- Insert character %
mhbuild-compose-type/subtype
to determine the command to use to compose the content. If this isn't found,
mhbuild will look for an entry of the form:
mhbuild-compose-type
to determine the composition command. If this isn't found, mhbuild will
complain.
An example entry might be:
mhbuild-compose-audio/basic: record |
raw2audio -F
Because commands like these will vary, depending on the display environment used
for login, composition strings for different contents should probably be put
in the file specified by the MHBUILD environment variable, instead of directly
in your user profile.
The “external-type” directives are used to provide a MIME
reference to a content, rather than enclosing the contents itself (for
instance, by specifying an ftp site). Hence, instead of providing a filename
as with the type directives, external-parameters are supplied. These look like
regular parameters, so they must be separated accordingly. For example,
#@application/octet-stream; \ type=tar; \ conversions=compress \ [this is the nmh distribution] \ {attachment; filename="nmh.tar.gz"} \ name="nmh.tar.gz"; \ directory="/pub/nmh"; \ site="ftp.math.gatech.edu"; \ access-type=anon-ftp; \ mode="image"
access-type= usually “anon-ftp”, “mail-server”, or “url” name= filename permission= read-only or read-write site= hostname directory= directoryname (optional) mode= usually “ascii” or “image” (optional) size= number of octets server= mailbox subject= subject to send body= command to send for retrieval url= URL of content
#@application/octet-stream [] access-type=url; \ url="http://download.savannah.gnu.org/releases/nmh/nmh-1.5.tar.gz"
#forw +inbox 42 43 99
#begin This will be a multipart with only one part. #end
#forw [important mail from Bob] +bob 1 2 3 4 5
#text/plain; charset=iso-8859-1 <>{attachment} /tmp/summary.txt
Content-Type: text/plain; charset="iso-8859-1" Content-Disposition: attachment; filename="summary.txt"
##when sent, this line will start with only
one #
If you want to end the plaintext prior to a directive, e.g., to have two
plaintext contents adjacent, simply insert a line containing a single
“#” character, e.g.,
this is the first content # and this is the second
Content-Description: text
then this will be used to describe the plaintext content. You MUST follow this
line with a blank line before starting your text.
By default, plaintext is captured as a text/plain content. You can override this
by starting the plaintext with “#<” followed by a
content-type specification. For example, e.g.,
#<text/enriched this content will be tagged as text/enriched # and this content will be tagged as text/plain # #<application/x-patch [this is a patch] and this content will be tagged as application/x-patch
#<text/plain; charset=iso-8859-5
If a text content contains any 8-bit characters (characters with the high bit
set) and the character set is not specified as above, then mhbuild will
assume the character set is of the type given by the standard locale(1)
environment variables. If these environment variables are not set, then the
character set will be labeled as “x-unknown”.
If a text content contains only 7-bit characters and the character set is not
specified as above, then the character set will be labeled as
“us-ascii”.
By default text content with the high bit set is encoded with an 8-bit
Content-Transfer-Encoding. If the text has lines longer than the value of
-maxunencoded (which defaults to 78) then the text is encoded using the
quoted-printable encoding.
The -headerencoding switch will indicate which algorithm to use when
encoding any message headers that contain 8-bit characters. The valid
arguments are base64 for base-64 encoding, quoted for
quoted-printable encoding, and utf-8 which requires that all 8-bit
header field bodies be encoded as UTF-8 (RFC 6530) and that the message be
sent to a SMTP server that supports SMTPUTF8 (RFC 6531). The
-autoheaderencoding switch instructs mhbuild to automatically
pick the encoding, either base64 or quoted-printable, that results in a
shorter encoded string.
Putting this all together, here is an example of a more complex message draft,
which will expand into a multipart/mixed message containing five parts:
To: [email protected] cc: Subject: Look and listen to me! -------- The first part will be text/plain #<text/enriched The second part will be text/enriched # This third part will be text/plain #audio/basic [silly giggle] \ |raw2audio -F < /usr/lib/sounds/giggle.au #image/gif [photo of foobar] \ /home/foobar/lib/picture.gif
Transfer Encodings
After mhbuild constructs the new MIME message by parsing directives, including files, etc., it scans the contents of the message to determine which transfer encoding to use. It will check for 8-bit data, long lines, spaces at the end of lines, and clashes with multipart boundaries. It will then choose a transfer encoding appropriate for each content type.Invoking mhbuild
Typically, mhbuild is invoked by the whatnow program. This command will expect the body of the draft to be formatted as an mhbuild composition file. Once you have composed this input file using a command such as comp, forw, or repl, you invoke mhbuild at the “What now” prompt withWhat now? mime
prior to sending the draft. This will cause whatnow to execute
mhbuild to translate the composition file into MIME format.
Normally it is an error to invoke mhbuild on a file that is already in
MIME format. The -auto switch will cause mhbuild to exit without
error if the input file already has valid MIME headers. The use of
-auto also enables the -nodirectives switch.
Finally, you should consider adding this line to your profile:
lproc: show
This way, if you decide to list after invoking mime, the command
What now? list
will work as you expect.
The -dist switch is intended to be used by dist. It will cause
mhbuild to not generate any MIME headers in the composition file (such as
“MIME-Version” or “Content-Type”), but it will
still encode message headers according to RFC 2047.
User Environment
Because the environment in which mhbuild operates may vary for a user, mhbuild will look for the environment variable MHBUILD. If present, this specifies the name of an additional user profile which should be read. Hence, when a user logs in on a particular machine, this environment variable should be set to refer to a file containing definitions useful on that machine. Finally, mhbuild will attempt to consult/etc/nmh/mhn.defaults
if it exists.
See "Profile Lookup" in mh-profile(5) for the profile search
order, and for how duplicate entries are treated.
Syntax of Composition Files
The following is the formal syntax of a mhbuild “composition file”.body ::= 1*(content | EOL) content ::= directive | plaintext directive ::= "#" type "/" subtype 0*(";" attribute "=" value) [ "(" comment ")" ] [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "*8bit" | "*qp" | "*b64" ] [ filename ] EOL | "#@" type "/" subtype 0*(";" attribute "=" value) [ "(" comment ")" ] [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "*8bit" | "*qp" | "*b64" ] external-parameters EOL | "#forw" [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "+"folder ] [ 0*msg ] EOL | "#begin" [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "alternative" | "parallel" | something-else ] EOL 1*body "#end" EOL plaintext ::= [ "Content-Description:" description EOL EOL ] 1*line [ "#" EOL ] | "#<" type "/" subtype 0*(";" attribute "=" value) [ "(" comment ")" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "*8bit" | "*qp" | "*b64" ] EOL 1*line [ "#" EOL ] line ::= "##" text EOL -- interpreted as "#"text EOL | text EOL
FILES
mhbuild looks for additional user profile files and mhn.defaults in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's Mail directory as specified in their profile. If not found there, the directory “/etc/nmh” is checked.- $HOME/.mh_profile
- The user's profile.
- $MHBUILD
- Additional profile entries.
- /etc/nmh/mhn.defaults
- System default MIME profile entries.
PROFILE COMPONENTS
- Path:
- To determine the user's nmh directory.
- Current-Folder:
- To find the default current folder.
- mhbuild-compose-type*:
- Template for composing contents.
SEE ALSO
mhlist(1), mhshow(1), mhstore(1) Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies (RFC 2045) Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types (RFC 2046) Multipurpose Internet Mail Extensions (MIME) Part Three: Message Header Extensions for Non-ASCII Text (RFC 2047) Internet Message Format (RFC 5322) MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations (RFC 2231) Proposed Standard for Message Encapsulation (RFC 934) Definition of the URL MIME External-Body Access-Type (RFC 2017) Overview and Framework for Internationalized Email (RFC 6530) SMTP Extension for Internationalized Email (RFC 6531)DEFAULTS
-noauto -autoheaderencoding -contentid -headers -maxunencoded 78 -nodisposition -norfc934mode -noverbose -realsize
DEFAULTS (with -auto)
-autoheaderencoding -contentid -headers -maxunencoded 78 -nodisposition -norfc934mode -noverbose -realsize -nodirectives
2022-03-27 | nmh-1.8-RC2 |