MMAIL(3) Library Functions Manual MMAIL(3)
NAME
mmail, mmail_addbody, mmail_addhead, mmail_alloc, mmail_clone, mmail_errstring, mmail_free, mmail_reset, mmail_write, mmbody_clone, mmbody_delete, mmbody_get, mmbody_next, mmhead_clone, mmhead_delete, mmhead_find, mmhead_nextchain, mmhead_nextset, mmp_alloc, mmp_char, mmp_col, mmp_detach, mmp_end, mmp_free, mmp_line, mmp_mmail, mmp_resetminimal e-mail library
SYNOPSIS
mmail
DESCRIPTION
The mmail library contains functions for the parsing, manipulation, and serialising of Internet Messages (“e-mails”). The mmail library constructs e-mails from either stream parsing (using mmp_alloc(), mmp_char(), etc.) or by direct construction (using mmail_addhead(), mmail_addbody(), etc.). Output is fully normalised.
 
The mmail library is currently under development.
Input Parsing
Input parsing (using mmp_char() or manually with mmail_addhead() and mmail_addbody()) accepts e-mails that are not well-formed, as messages are assumed to be read in human-readable format to be normalised upon calling mmail_write(). In particular, mail header fields may be of arbitrary length with binary encoding (assuming an encoding has been specified to mmp_alloc() and the appriate headers for MIME encoding). Message bodies may also be of arbitrary length (although 7bit messages may not exceed 998 characters) and may be in binary (assuming correct MIME headers).
Output Normalisation
Output is normalised to e-mail specifications. If a transfer encoding is specified for MIME messages, body lines exceeding 998 characters are properly soft line-broken; non-encoded messages are disallowed long lines (breaking them would change the message, and we leave this modifications to the calling context).
 
Header fields are properly encoded if a character encoding is specified with mmp_alloc() or mmail_alloc(). Long header bodies are correctly folded. Non-encoded messages are disallowed header bodies exceeding 998 characters.
REFERENCE
Enumeration Data Types
enum mmerr
Parse or construction error code.
enum mmheadt
Type of an e-mail header. MMHEAD__MAX indicates that a header has no specific type (it is “unstructured”, in the language of the RFC).
Function Data Types
mmfilt
Filters an e-mail body or header field value str of length len. If the callee wishes to replace str, he may provide an overriding buffer cp of size csz, which will be used in lieu of str. Input lines are not NUL terminated, as binary form is assumed. If replacement data for a header field body is in binary and no encoding is specified to mmp_alloc() or mmail_alloc(), the system will assert(3), otherwise it will be properly encoded. If replacement data for the message body is in binary and an appropriate transfer-encoding header has not been specified, the system will assert(3). If specified, cp is printed prior to subsequent invocations of the callback. Returns 0 to indicate failure.
mmprint
Output e-mail component data of variable form specified by fmt. This must accept formats as documented in printf(3).
mmerr
Raised when an error of type code occurs.
mmwarn
Raised when a warning of type code occurs. Returns 0 to halt system, non-zero otherwise.
Structure Data Types
struct mmail
Consists of an entire e-mail structure. This type is opaque and may only be manipulated via function calls.
struct mmbody
The free-form body of an e-mail (following headers). This type is opaque and may only be manipulated via function calls.
struct mmhead
Structured or un-structured headers of an e-mail. This type is opaque and may only be manipulated via function calls.
struct mmp
Parse sequence reading contents character by character into a parsed struct mmail. This type is opaque and may only be manipulated via function calls.
struct mmwriter
Write out parsed or constructed struct mmail. An optional filter or private data arg may be provided; print is mandatory.
Functions
mmail_alloc()
Allocate a new mail message. Accepts an encoding to be used for Q-encoding message headers, or NULL if headers will not be in binary. Returns NULL on allocation failure or the object on success.
mmail_addbody()
Add a line of body text. If the encoding is 7bit, this cannot be more than 998 characters long (returning MMBODY_BODYLINESIZ), nor can it be binary (returning MMAIL_BODYBIN). Otherwise, returns MMAIL_MALLOC on allocation failure or MMAIL_OK on success.
mmail_addhead()
Add a message header. This function should be called before mmail_addbody(), since mail encodings are determined by existing header data. Returns MMAIL_HEADMAX if the header type limit has been exceeded, MMAIL_HEADBODTOK if a binary header has been specified without an encoding (see mmail_alloc()), MMAIL_MALLOC on allocation failure, per-header-type errors on header validation failure, or MMAIL_OK on success.
mmail_clone()
Completely clone a mail and its components. Returns NULL on allocation failure or the object on success.
mmail_errstring()
Convert an error code into a English-language equivalent, which is formatted with a leading capital letter and no ending punctuation.
mmail_free()
Completely free a mail message's memory.
mmail_reset()
Remove the components of a mail message, readying it for re-use in a parse or manual add.
mmail_write()
Normalise an e-mail and write it. If an encoding is specified, headers are Q-encoded with quoted-printable. If a transfer encoding is specified in a MIME message, the body is appropriate transcoded. Long lines (with quoted-printable transfer encoding) are soft line-broken. Returns 0 on underlying output stream failure, 1 on success.
mmbody_clone()
Clone a body line. Returns NULL on allocation failure or the object on success.
mmbody_delete()
Unlink a body line from its mail context and free its memory.
mmbody_get()
Get the first body line of a mail message. Returns NULL if no body lines are present or the object on success.
mmbody_next()
Returns a subsequent line within a mail body or NULL if this is the last.
mmhead_clone()
Clone a header line. Returns NULL on allocation failure or the object on success.
mmhead_delete()
Unlink a message header from its mail context and free its memory. Be careful calling this on important headers as existing message flags (such as transfer encodings) may be retained.
mmhead_find()
Find the first instance of a message header. Returns the header or NULL if none exists.
mmhead_nextchain()
Proceed to the next header of the same type. Returns the header or NULL if none exists.
mmhead_nextset()
Proceed to the next header in a message. Returns the header or NULL if none exists.
mmp_alloc()
Allocate a parse routine with a given encoding (which is passed along to all generated messages), error message function, warning message function, and private data. Returns NULL on allocation failure or the object on success.
mmp_char()
Parse a single line of input into a mail message. Returns 0 on failure, 1 on success (errors/warnings will be reported via the provided callback functions).
mmp_col()
Current line column of a parsing sequence.
mmp_detach()
Detach a mail message from the parsing context. The detached message must be freed manually. Returns NULL if no message exists (has already been detached) or the object on success.
mmp_end()
End a parsing sequence. Returns 0 on failure, 1 on success (errors/warnings will be reported via the provided callback functions).
mmp_free()
Free a parsing sequence and, if it has not been detached with mmp_detach(), any contained in-parse message.
mmp_line()
Current line number of a parsing sequence.
mmp_mmail()
Get a pointer to the currently-parsed mail message. Returns NULL if no message exists (has been detached) or the object on success.
mmp_reset()
Reset a parse sequence. Calls through to mmail_reset() if the in-parse message has not been detached, else a new message is allocated. Returns 0 if memory allocation fails (in the event that the prior message has been detached), 1 on success.
SEE ALSO
STANDARDS
The mmail library closely follows RFC 5322 (Internet Message Format) for general e-mail structure, RFC 2045 (MIME Part I) for MIME header types and encodings, and RFC 2047 (MIME Part III) for Q-encoded headers.
AUTHORS
The mmail library was written by Kristaps Dzonsons ⟨kristaps@bsd.lv⟩.
CAVEATS
Structured headers (RFC 5322, 3.6 et al.) are not validated.
 
Folded headers are accepted, but non-encoded header bodies may still not exceed 998 characters.
 
Only quoted-printable and 7bit encoding MIME transfer coding are parsed and supported (RFC 2045, 6.2, 6.7).