Messages are introduced to the MTA by enqueuing them. Each enqueued message contains two required components, the message envelope and the message header, and may optionally contain a third component, the message body. The contents of the envelope and header must be provided by the program using the SDK.
For instructions on how to enqueue messages, see Chapter 2, MTA SDK Programming Considerations.
For an example of how to enqueue a message, see A Simple Example of Enqueuing a Message.
This section describes the three message components: envelope, header and body.
The message envelope contains the envelope From: address, and the list of envelope To: addresses. The envelope is created by the SDK as the message is enqueued. The addresses to be placed in the envelope must conform to RFC 2822. The envelope To: addresses are often referred to as envelope recipient addresses.
Programs should rely solely upon the MTA SDK routines to read and write envelope information, since the queued message file formats are subject to change. Using the SDK routines insulates programmers from format changes.
The routines mtaEnqueueStart( and mtaEnqueueTo( are used to construct a message envelope.
The message header contains RFC 2822 style header lines. The program enqueuing the message has nearly complete control over the contents of the header and can specify as many or as few header lines as it sees fit, with a few exceptions. A header must have at a minimum three lines: From:, Date:, and at least one recipient header line, such as To:, Cc:, or Bcc:.
As the message is enqueued, the SDK will do its best to supply any mandatory header lines that are missing as well as take some measures to ensure that the contents of the header lines conform to any relevant standards. If the From: header line is omitted by the program using the SDK, the SDK code will construct a default header line from the envelope From: address. This may not always be appropriate; for instance, when mail is addressed to a mailing list that specifies an Errors-to: address, then the Errors-to: address should be used as the envelope From: address. In this case, it is not appropriate to derive the header From: line from the envelope From: address. If the Date: header line is omitted, the SDK code will supply it, as well as a Date-warning: header line. Finally, if no recipient header lines are present, then the SDK code will generate them using the envelope recipient addresses.
Any addresses appearing in the message header should conform to RFC 2822.
The header is written line-by-line using the routines mtaEnqueueWrite() and mtaEnqueueWriteLine().
The optional message body contains the content of the message. As with the message header, the program enqueuing the message has nearly complete control over the contents of the message body. The only exception to this is when the message is structured with multiple parts or requires encoding, for example if it contains binary data, or lines requiring wrapping. In such cases, the SDK will ensure that the message body conforms to MIME standards (RFCs 2045– 2049).
As with the message header, message body lines are written with the routines mtaEnqueueWrite() and mtaEnqueueWriteLine().
Enqueued messages may be seen in the MTA queue directories and are merely ASCII text files. In the following sample message, lines 1 and 2 are the message envelope, the next four lines are the header, and the rest of the lines are the body.
email@example.com firstname.lastname@example.org Date: Tues, 1 Apr 2003 15:01 PST From: John Doe To: Mike Smith Subject: Lunch today Mike, Just confirming our lunch appointment today I’ll meet you at the restaurant at noon. John
As stated earlier, do not directly read from or write messages to the MTA message queues. Always use the SDK routines or Callable Send. The file structure of messages in the MTA queues are subject to change. In addition, site specific constraints may be placed on things such as encodings, and character set usage. The SDK routines automatically handle these and other issues.
Each individual message being enqueued to the MTA is represented within the SDK by an opaque enqueue context of type mta_nq_t. This enqueue context is created by mtaEnqueueStart() and destroyed by mtaEnqueueFinish(). Throughout the enqueue process, the message being enqueued is referenced through its enqueue context. A program using the SDK may simultaneously enqueue multiple messages, each message represented by its own enqueue context. Indeed, multiple threads may simultaneously enqueue one or more messages per thread. The only requirement is that a specific enqueue context not be simultaneously used by two or more threads. In the event that the SDK detects simultaneous usages, it returns the MTA_THREAD error.
If a message being enqueued is the result of dequeuing a message, then all envelope fields can automatically be carried over from the old message to the new message. Both per-message fields (such as envelope IDs) and per-recipient fields (such as delivery receipt requests) can be preserved. This preservation is achieved by supplying the associated dequeue context to the routines mtaEnqueueStart(), or mtaEnqueueTo(), or both. Supplying the dequeue context to mtaEnqueueStart() preserves per-message envelope fields, while supplying the dequeue context to mtaEnqueueTo() preserves the per-recipient fields for the specified envelope recipient.
For information on message dequeuing and message dequeue contexts, see Dequeuing Messages.