Sun Java System Messaging Server 6 2005Q4 MTA Developer's Reference

Caller-Supplied Processing Routine

Channel programs typically perform some form of processing on each message they dequeue. For instance, virus scanning, MMS conversion, decryption, delivery to a proprietary messaging system, and so forth. When using the MTA SDK, channel programs must provide a routine which initiates this processing on a per message basis. That is, programs must supply a routine that to be called to process a single queued message. Throughout the rest of this text, this caller-supplied routine will be referred to as “the caller-supplied processing routine,” or, for short, “the processing routine.”

When called by one of the mtaDequeueStart() execution threads, the processing routine uses the SDK to access the message’s envelope, header, and any content. Upon completion of processing, the message is then either removed from the MTA queues, or, in the event of a temporary error, left in its queue for a later processing attempt.

Dequeue Message Processing Routine Tasks

The processing routine processes a single queued message per invocation. The specific steps that a processing routine takes are:

  1. Read the envelope recipient list with repeated calls to mtaDequeueRecipientNext().

    When mtaDequeueRecipient() returns the MTA_EOF status code, the list has been exhausted and all envelope recipient addresses have been provided. All queued messages are guaranteed by the MTA to always have at least one envelope recipient address.

  2. Read the message, both header and body, with repeated calls to mtaDequeueLineNext().

    When mtaDequeueLineNext() returns the MTA_EOF status code, the message has been exhausted; that is, there is no more message text to retrieve. The message will be an RFC 2822 conformant message. As such, the division between the message’s header and content will be demarked by a blank line (a line with a length of zero). A message may have no content; that is, a message may have just a header.

  3. Process the message.

    The processing in this step could be almost anything, including possibly enqueuing a new message or messages with the MTA SDK. The details of this step will depend upon the purpose of the program itself. Programs needing to do MIME parsing should consider using the mtaDecodeMessage() routine.

    For further information about message processing threads and caller-supplied message processing routines, see Processing the Message Queue.

  4. Report the disposition of each envelope recipient with per recipient calls to mtaDequeueRecipientDisposition(), or a single call to mtaDequeueMessageFinish() with the MTA_DISP item code.

    The following table lists the valid recipient dispositions:

    Symbolic Name  



    Unable to process this recipient address. Processing has failed owing to a temporary problem, such as the network is down, a remote host is unreachable, or a mailbox is busy. Retry delivery for this recipient at a later time as determined by the configuration of the channel.


    Recipient address successfully delivered. Generate a delivery status notification if required.


    Unable to process this recipient address. Processing has failed owing to a permanent problem, such as an invalid recipient address, or recipient over quota. No further delivery attempts should be made for this recipient. Generate a non-delivery notification if required.


    Recipient address forwarded to another address or sent into a non-RFC 1891 (NOTARY) mail system. The message’s NOTARY information was, however, preserved. There is no need to generate a “relayed” notification message.


    Recipient address forwarded to another address or gatewayed to a non-RFC 1891 (NOTARY) mail system; the messages NOTARY information was not preserved; generate a relayed notification message if required.


    For this recipient, return the message as undeliverable. Generate a non-delivery notification if required. This disposition is intended for use by queue management utilities. It is not intended for channel programs.


    Unable to process this recipient address. Processing failed due to timing out. This disposition is intended for use by the MTA Return Job. Channel programs should not use this disposition.

  5. Dequeue the message with mtaDequeueMessageFinish().

    The message is not actually removed from the channel queue until this final step. This helps ensure that mail is not lost should the channel program fail unexpectedly, or some other unexpected disaster occurs.

    When this routine is called, the resulting processing depends on the disposition of the envelope recipient addresses reported with mtaDequeueRecipientDisposition() (see Step 4 in this task list).

    If all recipients have a permanent disposition (all of the ones listed in the previous table, except MTA_DISP_DEFERRED), then any required non-delivery notifications are generated and the message is permanently removed from the MTA queue.

    If all recipients are to be deferred (MTA_DISP_DEFERRED), then no notifications are generated and the message is left in the queue for later delivery attempts.

    If, however, some recipients have a permanent disposition and others are deferred, then the following happens:

    1. Notifications are generated for those recipients with permanent dispositions that require notifications.

    2. A new message is enqueued for just the deferred recipients.

    3. The original message is removed from the queue.

      Deferred messages will not be processed by this routine more than once, unless another delivery attempt is made for the deferred message while the process is still running. How long a message is deferred is configured as part of a channel’s definition, using the backoff channel keyword.

  6. When finished, the processing routine should return with a status code of zero (0) to indicate a success, and an appropriate MTA_ status code in the event of an error.

    If the processing routine returns before calling mtaDequeueFinish(), then the message that was being handled is left in its queue for a subsequent processing attempt. It will be as if the MTA_DISP_DEFFERED disposition was set for all of the message’s recipients. This will be the case even if the processing routine returns a success status code of zero.

    In the event that the processing routine needs to abort processing of a single message, it should call mtaDequeueMessageFinish() with the MTA_ABORT flag set. If the processing routine returns with a status code of MTA_ABORT, then the execution thread that called the processing routine will perform an orderly exit. Consequently, the program can prematurely terminate itself in a graceful fashion by causing its processing routine to begin returning the MTA_ABORT status code each time it is called.