Generating mail messages is a very complicated procedure.
Netsendmail
provides a comparatively simple interface
to accomplish this task without knowing too much about the details
of the mail format. Here is a kind of cookbook:
In the simplest case, the mail is an ASCII text. Generate the mail with
compose ~from_addr ~to_addrs ~subject main_text
Here, from_addr
is the sender's address as pair (name,formal_address)
,
and to_addrs
is the list of recipients in the same format.
The variable subject
contains the subject of the message as string.
Finally, main_text
is the ASCII text.
When addresses or the main text contain non-ASCII characters, you
should care about the in_charset
and out_charset
parameters.
In general, the strings you pass to compose
are encoded as
in_charset
, and the strings in the generated mail are encoded
as out_charset
. Usually, it is a good idea to have
in_charset = out_charset
, or out_charset
as a superset of
in_charset
(otherwise you might get conversion errors).
The default for both parameters is `Enc_iso88591
.
Not everything can be internationalised. In particular, the subject
,
the informal names of mail addresses, the content_description
, and
the main text can be encoded in a non-ASCII character set. Especially,
the formal mail addresses cannot be internationalised. Example:
compose
~in_charset:`Enc_iso885915
~out_charset:`Enc_iso885915
~from_addr:("Heinz Dräger", "heinz\@draeger.de")
~to_addr:("Marion Schröder", "marion\@irgendwo.de")
~subject:"Geschäftlich"
"Verkaufe Teddy-Bären für 100¤"
Note that when you also pass content_type
, the main text is
no longer converted according to in_charset
and out_charset
.
It is expected that the main text has already the right encoding,
and that the encoding is indicated by the content_type
. Example:
compose
~in_charset:`Enc_iso885915
~out_charset:`Enc_iso885915
~from_addr:("Heinz Dräger", "heinz\@draeger.de")
~to_addr:("Marion Schröder", "marion\@irgendwo.de")
~content_type:("text/html", ["charset", Netmime_string.mk_param "ISO-8859-1"])
~subject:"Geschäftlich"
"<html><body>Verkaufe Teddy-Bären für 100€</body></html>"
Here, the header fields are encoded in ISO-8859-15, but the main text uses ISO-8859-1.
The function Netmime_string.mk_param
encapsulates parameter values for
several kinds of structured values that may occur in mail headers,
here for Content-type
. This function takes care of the appropriate
representation of the parameter value (e.g. for parameters like "title"
that can be internationalised).
An attachment can simply be passed to compose
. For example, to
add a file "foo.gif":
compose
...
attachments:[ wrap_attachment
~content_type:("image/gif", [])
(new Netmime.file_mime_body "foo.gif") ]
...
This creates a multipart/mixed
mail. The class
Netmime.file_mime_body
encapsulates a file as a MIME body that
can be attached to the mail (note: The file is not read as a whole
into memory, but only chunk by chunk, so you can even attach large
files without exhausting memory).
The type multipart/mixed
has the special feature that
the attached parts can
either by displayed "inline" with the other contents, or suggested
for saving in a file. This hint is indicated by the Content-disposition
header. For example, to have the first attachment "inline", and the
second as a file with name "foo.gif", use:
compose
...
attachments:[ wrap_attachment
~content_type:("image/gif", [])
~content_disposition:("inline", [])
(new Netmime.file_mime_body "foo.gif");
wrap_attachment
~content_type:("image/gif", [])
~content_disposition:("attachment", ["filename",
Netmime_string.mk_param "foo.gif"])
(new Netmime.file_mime_body "foo.gif") ]
...
It is possible to generate messages where the main part is
available in several formats, e.g. in text/plain
and
text/html
. The mail reader program can select which format
can be presented best to the user.
The compose
function is not the right means to produce such
a mail. It is better to use the more capable functions
wrap_parts
and wrap_mail
for this purpose.
For example, to get a message with the text/plain
version
s_plain
and the text/html
version s_html
, use:
wrap_mail
~from_addr ~to_addrs ~subject
(wrap_parts
~content_type:("multipart/alternative", [])
[ wrap_attachment
~content_type:("text/plain", [])
(new Netmime.memory_mime_body s_plain);
wrap_attachment
~content_type:("text/html", [])
(new Netmime.memory_mime_body s_html)
])
Here, wrap_attachment
is used to encapsulate the two versions of
the main text. This works because there is no difference between the
format of an attachment and the format of a text part. (Actually,
wrap_attachment
should be better called wrap_body
.) The class
Netmime.memory_mime_body
encapsulates a string as MIME body.
The function wrap_parts
bundles the two versions to the main
message, and wrap_mail
adds the mail headers necessary to deliver
the mail.
Note that the simplest version of the message should be added first, and the fanciest version of the message should be added last.
As a variant, one can also add file attachments. To do so,
insert a multipart/mixed
container around the multipart/alternative
message:
wrap_mail
~from_addr ~to_addrs ~subject
(wrap_parts
~content_type:("multipart/mixed", [])
[ wrap_parts
~content_type:("multipart/alternative", [])
[ wrap_attachment
~content_type:("text/plain", [])
(new Netmime.memory_mime_body s_plain);
wrap_attachment
~content_type:("text/html", [])
(new Netmime.memory_mime_body s_html)
];
wrap_attachment
~content_type:("audio/wav", [])
(new Netmime.file_mime_body "music.wav")
])
MHTML is an HTML document with attached resource files like images
or style sheets. For example, to have the HTML text s_html
bundled
with an image and a style sheet, use:
wrap_mail
~from_addr ~to_addrs ~subject
(wrap_parts
~content_type:("multipart/related",
[ "type", Netmime_string.mk_param "text/html" ])
[ wrap_attachment
~content_type:("text/html", [])
(new Netmime.memory_mime_body s_html);
wrap_attachment
~content_type:("image/gif", [])
~content_id:"img1"
(new Netmime.file_mime_body "my.gif")
wrap_attachment
~content_type:("text/css", [])
~content_id:"style1"
(new Netmime.file_mime_body "style.css")
])
Note the content_id
arguments that assign names to the individual
parts. One can now refer to the parts from the HTML document by
cid
URLs, e.g. cid:img1
points to the image in the second
part.
There is another mechanism using the Content-Location
header to
resolve hyperlinks to message parts. See RFC 2557 for details.