Message Dequeue API

When dequeuing a message, the following message components are dequeued in the following order:

message envelope,
message header,
optional message body,
optional previous delivery failure logs.

Prior to start dequeuing messages, a dequeue context must be created by calling immd_init. An arbitrary number of messages can then be dequeued serially. Finally, when the dequeuing session is over, the corresponding dequeue context should be destroyed by calling immd_end.

The Message Dequeue API can be used only after the IMTA has been initialized with a previous call to imta_init, through which is the channel to be processed is specified.

Programs which run indefinitely should be made aware of configuration changes by calling immd_end/immd_init. periodically.


Reading a queued message

First, the envelope:
If there is at least one queued message, which is not currently processed by another dequeue context, immd_get_message opens a queued message and supplies the originator's address. Envelope recipients can be obtained by calling immd_get_recipient once for each of the recipients. The end of the list of receipients is signaled by a specific return code.

Then, the message header:
The message header object can be read from the message being dequeued by calling immd_read_header. The header lines can then be read individually by using the Message Header API.

The message Body:
The message body is read line by line, by calling immd_read_text repeatedly, until the end of the body is reached. The end of the body is signaled by a specific return code.

Finally, the delivery failure logs:
If a program has previously attempted to deliver this message and failed, an arbitrary number of previous failed delivery attempts may have been logged with calls to immd_defer. Failure logs are read one by one by calling repeatedly immd_read_failure_log. The end of the failure log list is signaled by a specific return code.


Delivery status and notifications

The whole purpose of dequeuing a message is to deliver it to a destination system, or to re-enqueue it. Should this operation fail, action, depending on the type of failure should be taken

If the processing fails owing to a permanent error (e.g., no such host, no such user, illegal address, etc.), then a delivery status notification must be generated with a call to immd_return. Then, the message must be deleted from the system with immd_dequeue.

However, if the processing fails with a temporary error which may be rectified in the near future (e.g., network link down) or an unexpected error, then the message should be deferred for later reprocessing by a call to immd_defer. This call allows the program to log the reason why the delivery has failed, so that a subsequent delivery attempt can be made aware of it by calling immd_read_failure_log.
Note that in this case the message must *not* be deleted.


Note - In the unlikely case where the message can be processed for some envelope To: addresses but, owing to temporary errors, for others, then a new message with only the unsuccessful envelope To: address list should be enqueued using the Message enqueue API, and the original message deleted with immd_dequeue.

The Notary standard, defined in RFC 1891, allows the message originator to request a delivery status notification (DSN) even if the delivery is successful. In this case, the DSN is generated automatically by the IMTA.


Decoding a multipart MIME message

The Sun Internet Mail SDK provides an alternative method to read queued messages, particularly adapted to multipart MIME messages: immd_mime_decode.

Managing dequeue contexts

For a given enqueue context, messages have to be dequeued serially, through repeated calls to immd_get_message. Each message in the queue will only be presented once; i.e., a dequeue context will not repeatedly see a message which it has deferred.

Multiple dequeue contexts may be used simultaneously to process the same message queue. The SIMS IMTA automatically and transparently coordinates such efforts and uses file locks to prevent two or more dequeue contexts from simultaneously processing the same message.

When immd_get_message is called, the accessed message is locked so that no other jobs may access that message. The message is then unlocked when immd_dequeue or immd_defer is called, or when the job exits, abnormally or otherwise. A dequeued message will not be seen by other jobs processing the same queue; once dequeued, the message is definitely gone.

Generally, programs which perform dequeue processing do not run indefinitely but rather exit after processing all messages in a specific queue. However, should it be necessary to write a program which never exits and does dequeue processing, then immd_end should be called after looping over all messages in a message queue. Then, when it is time to again try processing the message queue, immd_init should be called prior to the first immd_get_message call.


Example algorithm and programs


The example C programs dequeue_messages.c, return_messages.c, reenqueue_messages.c and decode_mime_messages.c illustrate the concepts defined in this section.




Copyright © 1999 Sun Microsystems, Inc. All Rights Reserved.