Sun logo      Previous      Contents      Index      Next     

Sun ONE Messaging Server 6.0 MTA Programmer's Reference Manual

Chapter 7
Using Callable Send: mtaSend

The Sun™ One Messaging Server MTA Callable Send facility, mtaSend(), is a single procedure that is used to send (enqueue) mail messages of local origin; that is, to originate mail from the local host. Because the mtaSend() routine is not as flexible as the SDK routines and will take possibly undesirable, but necessary, authentication steps (such as, the addition of a Sender: header line), the MTA SDK routines should generally be used by programs that need to resend, forward, send through a gateway, or otherwise route mail messages.

The mtaSend() routine may be used simultaneously with the MTA SDK routines.

This chapter covers the following topics:


Sending a Message

Each message sent with mtaSend() must have a corresponding item list describing the message. The entries in this item list specify the message’s From: and To: addresses as well as input sources for the content of the message.

The basic steps in sending a message with mtaSend() are:

  1. Build an item list to pass to mtaSend().
  2. To build an item list, complete the following steps:

  3. Pass the item list to mtaSend().
  4. Check the return status from mtaSend().
  5. For a description of all item codes and their return status values, see Chapter 8, "mtaSend Routine Specification."

To enqueue additional messages, simply repeat these steps.


Envelope and Header From: Addresses

The envelope From: address for a message should be specified with the MTA_USER item code. With this item code, only the local part of a mail address may be specified, that is, the user name. The mtaSend() routine will automatically append the official local host name to the user name so as to produce a valid mail address.

The MTA_ENV_FROM item code may be used to explicitly specify a complete envelope From: address but this is usually not necessary. Applications that enqueue nonlocal mail should probably be using the SDK routines rather than mtaSend().

If neither MTA_USER nor MTA_ENV_FROM are specified, then the user name associated with the current process will be used for the envelope From: address. When MTA_USER is used, the From: header line will be derived from the envelope From: address. When MTA_ENV_FROM is used, the From: header line will be derived from the user name of the current process. In either case, if a From: header line is supplied in an initial header, then a Sender: header line will be added to the message header. The initial From: header line will be left intact and the address specified, and Sender: address will be derived from either the envelope From: address (MTA_USER) or from the user name of the current process, that is, from MTA_ENV_FROM.

Only privileged users may use MTA_USER to specify a user name different than that of the current process. To be considered a "privileged" process on UNIX® systems, the process must have the same (real) user ID (UID) as either the root or Messaging Server account.


To:, Cc:, and Bcc: Addresses

The list of To:, Cc:, and Bcc: addresses to send a message to is built up, one address at a time, with item-list entries. Each item-list entry specifies the type of address (To:, Cc:, or Bcc:) and a string containing the address.

The type of address is denoted by the item code, MTA_TO, MTA_CC, or MTA_BCC, associated with the item-list entry. The mtaSend() routine uses this information to build the message envelope To: address list and To:, Cc:, and Bcc: header.

To specify an envelope-only address that should not appear in the message header (for example, an active transport address), use MTA_ENV_TO. Likewise, to specify a header-only address that should not appear in the envelope, such as, an inactive address, use MTA_HDR_TO, MTA_HDR_CC, or MTA_HDR_BCC, as appropriate.

When one or more of the To:, Cc:, or Bcc: addresses is illegal, the mtaSend() routine will not, by default, indicate which addresses were in error. However, the differentiation can be achieved by using the MTA_ADR_STATUS item code. When this item code is used, the item_status field associated with an address will be set either to zero (0) if the address was accepted, or to a non-zero value if there was an error processing the address.

When item_status is zero, item_smessage points to a NULL terminated string containing the rewritten form of the address. When item_status has a non-zero value, item_smessage points to a NULL terminated string containing an error message suitable for printing for diagnostic purposes.


Message Headers and Content

The body of a message, that is, the message content, is built up from zero or more input files or procedures. The input files and procedures are read or invoked in the order specified in the item list passed to the mtaSend() routine. The message body is built up by appending the next input source to the end of the previous input source. A blank line will be inserted in the message as a separator between input sources if the MTA_BLANK item is requested in the item list. The MTA_MSG_FILE and MTA_MSG_PROC item codes are used to specify the name or address of input files or procedures.

An initial message header may be supplied from either an input file or procedure. The message header will then be modified as needed when the message is enqueued. The MTA_HDR_FILE and MTA_HDR_PROC items are used to specify the name or address of an input file or procedure. If an initial message header is to be supplied, it must appear in the item list before any MTA_MSG_FILE or MTA_MSG_PROC items. A blank line must be supplied at the end of the message header, or at the start of the first message-body input source. This blank line will automatically be supplied when the MTA_BLANK item code is specified in the item list.

The MTA_MODE_ and MTA_ENC_ items control the access mode and encodings applied to message body input sources. These items set the current access mode and encoding to be applied to all subsequent input sources that appear in the item list. The default access mode is MTA_MODE_TEXT, which uses text mode access. The default encoding is MTA_ENC_UNKNOWN, which results in no encoding of the data.

The binary access mode will not be applied to input procedures. The access mode and encoding item codes do not apply to input sources for an initial message header, which is always accessed using the default access mode and never encoded.

Input procedures use the following calling format:

ssize_t proc(const char **bufadr)

where const char **bufadr is the address of pointer to the starting memory location of the next piece of input data.

The return value is ssize_t, which gives the length of the input data. A value that is equal to or greater than zero (0) indicates success. A value of minus one (-1) indicates that there is no further data to return (EOF). Any other negative value indicates an error for which processing should be aborted.

The procedure will be repeatedly called until a negative value is returned, which indicates all input data has been retrieved or an error occurred.


Required Privileges

Like the MTA SDK routines, privileges are required in order to use mtaSend(). Enqueuing messages requires privileges sufficient to create, open, read from, and write to the MTA message queue directories. On UNIX, this is accomplished by having your executable program owned and run by the MTA account or, alternatively, owned by the MTA and have the setuid attribute set.

In order to submit mail under a user name that differs from that of the calling process, privileges are required. On UNIX platforms, the process must have the same (real) UID as either the root or Messaging Server account.

In some applications, it is important to keep strict control over when privileges are enabled and disabled. To this end, the MTA_PRIV_ENABLE_PROC and MTA_PRIV_DISABLE_PROC item codes may be used to specify the addresses of two procedures to call immediately prior to and immediately after enqueuing a message. This allows the required privileges to be enabled only when they are needed, that is, when the message is enqueued, and to remain disabled at all other times.

The mtaSend() routine does not use a condition handler, so if a fatal error occurs while enqueuing a message, it is up to the calling program to trap the error and, if necessary, disable any privileges that should be disabled. These procedures, if specified, should accept no arguments and return no function result (return value).

The privileges to be enabled must either be granted to the program using mtaSend() (for example, the program may have been installed with privileges), or the process running the program must have the requisite privileges. The mtaSend() routine and the MTA do not provide these privileges.


mtaSendDispose

For each call to mtaSend() where MTA_ADR_STATUS is used, there should be a subsequent call to mtaSendDispose().

Syntax

void mtaSendDispose(mta_item_list_t *item_list)

Arguments

Argument

Description

item_list

Pointer to an array with elements of type mta_item_list_t. This should be an array previously passed to mtaSend().

Description

Each call to this routine disposes of virtual memory allocated by mtaSend() for returning address status information requested with the MTA_ADR_STATUS item code.

Return Values

None

Example

...

item_list[index++].item_code=MTA_ADR_STATUS;

item_list[index++].item_code=MTA_ITEM_END;

istat=mtaSend(item_list);

...

mtaSendDispose(item_list);


Compiling and Linking Programs

Programs that use mtaSend() are linked using the same steps as the MTA SDK routines. For details, see Chapter 2, "MTA SDK Programming Considerations."


Examples of Using mtaSend

Several example programs, written in C, are provided in this section:

The example routines shown in this section may be found in the examples/mta/sdk directory.

Example 1: Sending a Simple Message

The program shown in Code Example 7-1 demonstrates how to send a simple message to the root account. The source code itself is used as the input source for the body of the message to be sent. The From: address associated with the message is that of the process running the program. Comments in the program example explain the sample output line they generate.

Code Example 7-1  Send a Simple Message

/* send_simple.c Send a simple message */

#include <string.h>

#include "mtasdk.h"

/* Push an entry onto the item list */

#define ITEM(item,adr) item_list[index].item_code = item;\

 item_list[index].item_address = adr;\

 item_list[index].item_length = adr ? strlen(adr) : 0; \

  item_list[index].item_status = 0;\

 item_list[index++].item_smessage = NULL

main ()

{

  mta_item_list_t item_list[4];

  int index = 0;

  ITEM(MTA_TO, "root"); /* Becomes the To: line in the output */

  ITEM(MTA_SUBJECT, "send_simple.c");

 ITEM(MTA_MSG_FILE, __FILE__);/* Becomes the Subject: line */

  ITEM(MTA_END_LIST, 0);

 exit(mtaSend(item_list));

}

Example 1 Output

Date: 04 Oct 1992 22:24:07 -0700 (PDT)

From: jdoe@sesta.com

Subject: send_simple.c

To: root@sesta.com

Message-id: <01GPKF10JIB89LV1WX@sesta.com>

MIME-version: 1.0

Content-type: TEXT/PLAIN; CHARSET=US-ASCII

Content-transfer-encoding: 7BIT

/* send_simple.c -- Send a simple message */

#include <string.h>

#include "mtasdk.h"

...

Example 2: Specifying an Initial Message Header

The program shown in Code Example 7-2 illustrates the use of the MTA_HDRMSG_FILE and MTA_HDR_ADRS item codes to enqueue a message that has already been composed, including the headers, and stored in a file. The input file is given in the Example 2 Input File. The resulting message is shown in Example 2 Output.

When the entire message, header and body, is contained in a single file, use the MTA_HDRMSG_FILE item code in place of the MTA_HDR_FILE and MTA_MSG_FILE item codes.

Code Example 7-2  Specify an Initial Message Header

/* send_header.c -- Send a message with initial header */

#include <string.h>

#include "mtasdk.h"

/* Push an entry onto the item list */

#define ITEM(item,adr) item_list[index].item_code = item;\

  item_list[index].item_address = adr;\

  item_list[index].item_length = adr ? strlen(adr) : 0;\

  item_list[index].item_status = 0;\

  item_list[index++].item_smessage = NULL

main ()

{

  MTA_item_list_t item_list[3];

  int index = 0;

  ITEM(MTA_HDR_ADRS, 0);

  ITEM(MTA_HDRMSG_FILE, "send_header.txt");

  ITEM(MTA_END_LIST, 0);

  exit(mtaSend(item_list));

}

Example 2 Input File

Subject: MTA SDK callable Send example

To: root@sesta.com

MIME-version: 1.0

Content-type: TEXT/PLAIN; CHARSET=US-ASCII

Content-transfer-encoding: 7BIT

Comments: Ignore this message -- it’s just a test

This is a test of the emergency broadcasting system!

1234567890123456789012345678901234567890123456789012345678901234

5678901234567890

0000000001111111111222222222233333333334444444444555555555566666

6666677777777778

Example 2 Output

Date: 04 Jan 2003 22:42:25 -0800 (PST)

From: system@sesta.com

Subject: MTA SDK callable Send example

To: system@sesta.com

Message-id: <01GPKFNPUQF89LV1WX@sesta.com>

MIME-version: 1.0

Content-type: TEXT/PLAIN; CHARSET=US-ASCII

Content-transfer-encoding: 7BIT

Comments: Ignore this message -- it’s just a test

This is a test of the emergency broadcasting system!

1234567890123456789012345678901234567890123456789012345678901234

5678901234567890

0000000001111111111222222222233333333334444444444555555555566666

6666677777777778

Example 3: Sending a Message to Multiple Recipients

The program given in Code Example 7-3 demonstrates the following points:

The message is sent to one To: address, a Cc: address, and a Bcc: address. After mtaSend() is called, any status message associated with each address is displayed.

The log output produced by running the program is shown in Example 3 Output.

The following items of note are identified in the comments in the program:

Code Example 7-3  Sending a Message to Multiple Recipients  

/* send_multi.c -- Send a message to multiple recipients */

#include <stdio.h>

#include <string.h>

#include "mtasdk.h"

#define ITEM(item,adr) item_list[index].item_code = item;\

  item_list[index].item_address = adr;\

  item_list[index].item_length = adr ? strlen(adr) : 0;\

  item_list[index].item_status = 0;\

  item_list[index++].item_smessage = NULL

main ()

{

  int index = 0, istat, i;

  mta_item_list_t item_list[7];

  /* Specify the Subject: header line and message input source */

  ITEM(MTA_SUBJECT, "send_multi.c");

  ITEM(MTA_MSG_FILE, __FILE__);

  /* Return per address status/error messages */

  ITEM(MTA_ADR_STATUS, 0); /* Instructs mtaSend() to return a */

                           /* status message for each envelope */

                           /* recipient address                */

  /* Specify regular Bcc:, To:, and Cc: addresses */

  ITEM(MTA_BCC, "root");

  ITEM(MTA_TO, "abuse@sample.com");

  ITEM(MTA_CC, "postmaster@sample.com");

  /* Now terminate the item list */

  ITEM(MTA_END_LIST, 0);

  /* And send the message */

  istat = mtaSend(item_list);/* Sends the message. */

  /* Display the address status messages provided that no */

  /* error other than MTA_HOST has occurred               */

  for (i = 0; i < index; i++) /* Display any returned status */

                              /* messages                    */

       if (item_list[i].item_smessage)

           printf ("%s: %s - %s\n",

                   (const char *)item_list[i].item_address,

                   item_list[i].item_status ? "Failed" :

                                              "Succeeded",

                   item_list[i].item_smessage);

  /* Dispose of status messages */

  mtaSendDispose(item_list);

  exit(istat);

}

Example 3 Output

Succeeded: root@sample.com

Succeeded: abuse@sample.com

Succeeded: postmaster@sample.com

Example 4: Using an Input Procedure to Generate the Message Body

The program shown in Code Example 7-4 uses an input procedure as the source for the body of a message to be sent. In the program, the input procedure msg_proc will read input until the runtime library routine fgets() signals an EOF condition, for example, a control-D has been input. The address of the procedure msg_proc is passed to mtaSend() using a MTA_MSG_PROC item code. The mtaSend() routine repeatedly calls the msg_proc procedure, until a negative value is returned by the procedure.

Code Example 7-4  Using an Input Procedure to Generate the Message Body

/* send_input.c -- Demonstrate the use of MTA_MSG_PROC */

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "mtasdk.h"

#ifdef _WIN32

typedef long ssize_t;

#endif

/* Push an entry onto the item list */

#define ITEM(item,adr) item_list[index].item_code = item;\

item_list[index].item_address = adr;\

item_list[index].item_length = 0;\

item_list[index].item_status = 0;\

item_list[index++].item_smessage = NULL

ssize_t msg_proc(const char **bufadr)

{

  static char buf[1024];

  if (!bufadr)

      return(-2); /* Call error; abort */

  printf("input: ");

  if (fgets(buf, sizeof(buf), stdin))

  {

    *bufadr = buf;

    buflen = strlen(buf);

    if (buf[buflen-1] == ’\n’)

      buflen -= 1;

    return(buflen);

  }

  else

    return(-1); /* EOF */

}

main ()

{

  int istat, index = 0;

  mta_item_list_t item_list[4];

  STRITEM(MTA_SUBJECT, "send_input.c");

  STRITEM(MTA_TO, "root");

  ITEM(MTA_MSG_PROC, msg_proc);

  ITEM(MTA_END_LIST, 0);

  exit(mtaSend(item_list));

}



Previous      Contents      Index      Next     


Copyright 2003 Sun Microsystems, Inc. All rights reserved.