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

A Simple Dequeuing Example

The program shown in Example 4–1 constitutes a simplified batch-SMTP channel that reads messages from a message queue, converting each message to batch SMTP format, and writes the result to stdout. If the conversion is successful, then the message is dequeued, otherwise it is deferred.

Some lines of code are immediately preceded by a comment of the format:

/* See explanatory comment N */

where N is a number.

The numbers are links to some corresponding explanatory text in the section that follows this code, see Explanatory Text for Numbered Comments in the Simple Dequeue Example. Find the sample output in Output from the Simple Dequeue Example.


Example 4–1 Simple Dequeue Example


/*  dequeue_simple.c -- A simple dequeue example: write BSMTP to stdout
 */
#include <stdio.h>
#include <stdlib.h>
#include "mtasdk.h"

static mta_dq_process_message_t process_message;

int main()
{
     int ires;

     /*
      * Initialize the MTA SDK
      */
     if ((ires = mtaInit(0)))
     {
         mtaLog(mtaInit() returned %d; %s\n, ires, 
                mtaStrError(ires, 0));
         return(1);
     }

     /*
      *  Start the dequeue loop.  Since this example uses stdout 
      *  for output, we indicate that we only support a single
      *  thread:
      *  (MTA_THREAD_MAX_THREADS = 1).
      */
     /*  See explanatory comment 1  */
     ires = mtaDequeueStart(NULL, process_message, NULL,
                            MTA_THREAD_MAX_THREADS, 1, 0);

     /*  
      *  Check the return status 
      */
     /*  See explanatory comment 2  */
     if (!ires) 
          /* Success */
          return(0);

     /* 
      *  Print an error message to stderr
      */
     /*  See explanatory comment 3  */
     mtaLog("mtaDequeueStart() returned %d; %s\n", ires, 
             ires, mtaStrError(ires, 0));

     /* And exit with an error */
     return(1);
}

/*  See explanatory comment 4  */
static int process_message(void **my_ctx_2, void *my_ctx_1, 
                           mta_dq_t *dq, const char *env_from,
                           size_t env_from_len)
{
     int ires;
     const char *to, *line;
     size_t len;

     /*  See explanatory comment 5  */
     if (!(*my_ctx_2))
     {
          *my_ctx_2 = (void *)1;
          printf("HELO\n");
     }
     else
          printf("RSET\n");

     /*  Output the command:
      *     MAIL FROM: <from-adr> 
      */
     printf("MAIL FROM:<%s>\n", env_from);

     /* 
      *  Output the command:
      *     RCPT TO: <to-adr> 
      *  for each recipient address 
      */
     /*  See explanatory comment 6  */
     while (!(ires = mtaDequeueRecipientNext(dq, &to, 
                                             &len, 0)))
     {
          printf("RCPT TO:<%s>\n", to);
          /*  See explanatory comment 7  */
          mtaDequeueRecipientDisposition(dq, to, len,
                                         MTA_DISP_DELIVERED, 0);
     }

     /* 
      *  If ires == MTA_EOF, then we exited the loop normally; 
      *  otherwise, theres been an error of some sort. 
      */
     if (ires != MTA_EOF)
          /*  See explanatory comment 8  */
          return(ires);
     /* 
      *  Now output the message itself
      */
     printf("DATA\n");
     /*  See explanatory comment 9  */
     while (!(ires = mtaDequeueLineNext(dq, &line, &len)))
         /*  See explanatory comment 10  */
         printf("%.*s\n", len, line);

     /* 
      *  If ires == MTA_EOF, then we exited normally;
      *  otherwise, theres been an error of some sort. 
      */
     if (ires != MTA_EOF)
         /*  See explanatory comment 8  */
         return(ires); 

     /* 
      *  Output the . command to terminate this message
      */
     printf(".\n");

     /* 
      *  And dequeue the message
      */
     /*  See explanatory comment 11  */
     ires = mtaDequeueMessageFinish(dq, 0);

     /* 
      *  All done; return ires as our result 
      */
     /*  See explanatory comment 12  */
     return(ires);
}

Explanatory Text for Numbered Comments in the Simple Dequeue Example

The numbered explanatory text that follows corresponds to the numbered comments in Example 4–1:

  1. To start the dequeue processing, mtaDequeueStart() is called, and it calls process_message(), which processes each queued message. Since process_message() uses stdout for its output, only one message can be processed at a time. To effect that behavior, mtaDequeueStart() is called with the MTA_THREAD_MAX_THREADS set to one.

  2. If the call to mtaDequeueStart() succeeds, the program exits normally.

  3. If the call to mtaDequeueStart() fails, a diagnostic error message is displayed and the program exits with an error status.

  4. process_message() is called by mtaDequeueStart() for each queued message.

  5. The private context in process_message() tracks whether or not this is the first time the routine has been called. On the first call, the memory pointed at by my_ctx_2 is guaranteed to be NULL.

  6. The routine obtains each envelope recipient address, one at a time, using calls to mtaDequeueRecipientNext().

  7. Each recipient is marked as delivered using mtaDequeueRecipientDispostion(). An actual channel program would typically not make this call until after processing the message further.

  8. If process_message() returns without first dequeuing the message, mtaDequeueStart() defers the message for a later delivery attempt.

  9. The routine calls mtaDequeueLineNext() to read the message header and body, one line at a time. When there are no more lines to read, mtaDequeueLineNext() returns a status of MTA_EOF. When a line is read successfully, mtaDequeueLineNext() returns a status of MTA_OK.

  10. The lines returned by mtaDequeueLineNext() might not be NULL terminated because the returned line pointer might reference a line in a read-only, memory-mapped file.

  11. Once the message has been processed and all the disposition of all recipients set, mtaDequeueMessageFinish() is called. This actually dequeues the message.

  12. When all message processing is complete, process_message() exits. It is called again for each additional message to be processed.

Output from the Simple Dequeue Example


HELO
MAIL FROM:<sue@siroe.com\>
RCPT TO:<dan@siroe.com\>
DATA
Received:from siroe.com by siroe.com (SunONE Messaging Server 6.0)id
 <01GP37SOPRW0A9KZFV@siroe.com\>; Fri, 21 Mar 2003 09:07:32 -0800(PST)
Date: Fri, 21 Mar 2003 09:07:41 -0800 (PST)
From: postmaster@siroe.com
To: root@siroe.com
Subject: mtasdk_example1.c
Message-id: <01GP37SOPRW2A9KZFV@siroe.com\>
Content-type: TEXT/PLAIN; CHARSET=US-ASCII
Content-transfer-encoding: 7BIT

Hello
  world!
.
QUIT