PMDF Programmer's Reference Manual


Previous Next Contents Index

1.12.4 Dequeuing & Returning Messages

Examples 1-10 and 1-11 illustrate the use of PMDFdequeueMessageEnd to return a message to its originator. A message in the channel's queue is accessed and each of its envelope "To:" recipients are given a disposition of PMDF_DISP_RETURN which indicates that the message is undeliverable for that recipient. Then, when PMDFdequeueMessageEnd is called, a bounce message is automatically generated and sent back to the original message's originator. The original message is then removed from the queue. Note that no notification message will be generated if the NOTARY flags for all of the recipients specify PMDF_RETURN_NEVER.

These two particular examples, through the use of PMDFgetMessage, return each and every message in a message queue. A sample returned message is shown in Example 1-12.

Note

It is important to remember to define the PMDF_CHANNEL logical (OpenVMS) or environment variable (UNIX and Windows) to be the name of the channel (in lower case) to be serviced by this program. Also, if experimenting from your own account, do not leave this logical or environment variable defined while not experimenting --- PMDF can see it when you send mail and submit that mail as though it was enqueued by the channel given by PMDF_CHANNEL. (This is a debugging feature.)

The following items of note are identified with callouts in each of the two programs:

  1. In the event of an error, the current message being processed is deferred, any new message being enqueued is aborted, and the program exits.
  2. get_message is a routine which will return true (1) if PMDFgetMessage successfully accesses a message or false (0) otherwise. If PMDFgetMessage returns any error other than PMDF__EOF, then the check routine is invoked.
  3. PMDFinitialize is invoked with the ischannel argument true.
  4. Initialize a message dequeue context with PMDFdequeueInitialize.
  5. Using the get_message routine, the program loops over all messages to be processed.
  6. Obtain the next envelope "To:" address for the current message.
  7. Obtain the NOTARY flags for the envelope "To:" address just obtained.
  8. Set the disposition for this envelope "To:" address to PMDF_DISP_RETURN. This will cause the message to be returned as undeliverable for this envelope "To:" address.
  9. The message is automatically returned when PMDFdequeueMessageEnd is called.
  10. All done processing messages; dispose of the message dequeue context.

Example 1-10 Dequeuing & Returning Messages (Pascal)

(* api_example7.pas -- Return channel which returns all mail queued to it *) 
 
[inherit ('pmdf_exe:apidef')] program api_example7; 
 
  type 
    uword  = [word] 0..65535; 
    string = packed array [1..ALFA_SIZE] of char; 
 
  var 
    from_adr, orig_adr, to_adr             : string; 
    from_adr_len, orig_adr_len, to_adr_len : uword; 
    dq_context                             : PMDF_dq; 
    empty                                  : varying [1] of char; 
    nflags                                 : integer; 
 
function SYS$EXIT (%immed status : integer := %immed 1) : integer; extern; 
 
procedure check (stat : integer); (1)
 
  var reason : varying [20] of char; 
 
  begin (* check *) 
    if not odd (stat) then begin 
      writev (reason, 'Error ', stat:0); 
      if dq_context <> nil then PMDF_defer_message (dq_context, true, reason); 
    end; (* if *) 
  end; (* check *) 
 
function get_message : boolean; (2)
 
  var msg_file : string; msg_file_len : uword; stat : integer; 
 
  begin (* get_message *) 
    stat := PMDF_get_message (dq_context, msg_file, msg_file_len, 
                              from_adr, from_adr_len); 
    get_message := odd (stat); 
    if (not odd (stat)) and (stat <> PMDF__EOF) then check (stat); 
  end; (* get_message *) 
 
begin (* api_example7 *) 
  dq_context := nil; 
  empty      := ''; 
  check (PMDF_initialize (true)); (3)
  check (PMDF_dequeue_initialize (dq_context)); (4)
  while get_message do begin (5)
    while odd (PMDF_get_recipient (dq_context, to_adr, to_adr_len, (6)
                                   orig_adr, orig_adr_len)) do begin 
      check (PMDF_get_recipient_flags (dq_context, nflags)); (7)
      check (PMDF_recipient_disposition (dq_context, nflags, (8)
                 PMDF_DISP_RETURN, substr (to_adr, 1, to_adr_len), 
                 substr (orig_adr, 1, orig_adr_len), 
                 'Message undeliverable; returned by the postmaster')); 
    end; (* while *) 
    check (PMDF_dequeue_message_end (dq_context, false, empty));  (9)
  end; (* while *) 
  check (PMDF_dequeue_end (dq_context)); (10)
  check (PMDF_done); 
end. (* api_example7 *) 
 

Example 1-11 Dequeuing & Returning Messages (C)

/* api_example8.c -- Return channel which returns all mail queued to it */ 
 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#ifdef __VMS 
#include "pmdf_com:apidef.h" 
#else 
#include "/pmdf/include/apidef.h" 
#endif 
 
typedef char string[ALFA_SIZE+1]; 
 
string from_adr; 
int from_adr_len, item_index; 
PMDF_dq *dq_context = 0; 
 
void check (int stat) (1)
{ 
  char reason[20]; 
  if (!(1 & stat)) { 
    sprintf (reason, "Reason %d", stat); 
    if (dq_context) PMDFdeferMessage (&dq_context, 1, reason, strlen (reason)); 
    if (!stat) exit (0); 
    else exit (stat); 
  } 
} 
 
int get_message (void) (2)
{ 
    string msg_file; 
    int msg_file_len, stat; 
 
    msg_file_len = from_adr_len = ALFA_SIZE; 
    stat = PMDFgetMessage (&dq_context, msg_file, &msg_file_len, 
                           from_adr, &from_adr_len); 
    if (!(1 & stat) && stat != PMDF__EOF) check (stat); 
    return (1 & stat); 
} 
 
main () 
{ 
  string orig_adr, to_adr; 
  int i, nflags, orig_adr_len, to_adr_len; 
 
  channel_len = ALFA_SIZE; 
  check (PMDFinitialize (1)); (3)
  check (PMDFdequeueInitialize (&dq_context)); (4)
  while (get_message ()) { (5)
    item_index = 0; 
    to_adr_len = orig_adr_len = ALFA_SIZE; 
    while (1 & PMDFgetRecipient (&dq_context, to_adr, &to_adr_len, (6)
                                 orig_adr, &orig_adr_len)) { 
      check (PMDFgetRecipientFlags (&dq_context, &nflags)); (7)
      check (PMDFrecipientDisposition (&dq_context, nflags, (8)
                PMDF_DISP_RETURN, to_adr, to_adr_len, 
                orig_adr, orig_adr_len, 
                "Message undeliverable; returned by the postmaster", 49)); 
      to_adr_len = orig_adr_len = ALFA_SIZE; 
    } 
    check (PMDFdequeueMessageEnd (&dq_context, 0, "", 0)); (9)
  } 
  check (PMDFdequeueEnd (&dq_context)); (10)
  check (PMDFdone ()); 
} 
 

Example 1-12 shows a sample return message generated by PMDFreturnMessage. In that example, the following items are marked with callouts: the message header, (1); a MIME header line indicating that the message is a multi-part message, (2); the first body part which contains a human readable explanation as to why the message was returned, (3); the second body part which contains a machine readable explanation as to why the message was returned, (4); and the third body part containing the message being returned, (5).

Example 1-12 Output of Examples 1-10 and 1-11

Received: from example.com (PMDF V6.1 #8790) (1)
 id <01IXGG2X55A88Y55Z3@example.com>; Sat, 04 May 2012 18:04:00 EDT 
Date: Sat, 04 May 2012 18:04:00 EDT 
From: PMDF Internet Messaging <postmaster@example.com> 
Subject: Delivery Notification: Delivery has been manually aborted 
To: Trinculo@example.com, postmaster@example.com 
Message-id: <01IXGG2Y8J468Y55Z3@example.com> 
MIME-version: 1.0 
Content-type: MULTIPART/REPORT; REPORT-TYPE=DELIVERY-STATUS; (2)
 BOUNDARY="Boundary_(ID_78nMbcjsTsCboulbhJC84A)" 
 
--Boundary_(ID_78nMbcjsTsCboulbhJC84A) (3)
Content-type: text/plain; charset=us-ascii 
Content-language: EN-US 
 
This report relates to a message you sent with the following header fields: 
 
  Message-id: <01IXGGR0TSYS8Y55Z3@example.com> 
  Date: Sat, 04 May 2012 18:04:00 -0400 (EDT) 
  From: Trinculo@example.com 
  To: Stephano@example.com 
  Subject: Meeting next Wednesday 
 
Your message is being returned.  It was forced to return by the postmaster. 
 
The recipient list for this message was: 
 
  Recipient address: Stephano@example.com 
  Reason: Message undeliverable; returned by the postmaster 
 
--Boundary_(ID_78nMbcjsTsCboulbhJC84A) (4)
Content-type: message/DELIVERY-STATUS 
 
Original-envelope-id: 01IXGFBILT3M8Y55Z3@example.com 
Reporting-MTA: dns;example.com 
 
Action: failed 
Status: 5.0.0 (Message undeliverable; returned by the postmaster) 
Original-recipient: rfc822;Stephano@example.com 
Final-recipient: rfc822;Stephano@example.com 
 
--Boundary_(ID_78nMbcjsTsCboulbhJC84A) (5)
Content-type: text/rfc822-headers 
 
Return-path: Trinculo@example.com 
Received: from example.com by example.com (PMDF V6.1 #8790) 
 id <01IXGG2X55A88Y55Z3@example.com> 
 (original mail from Trinculo@example.com); Sat, 04 May 2012 18:04:00 EDT 
Received: from example.com by example.com (PMDF V6.1 #8790) 
 id <01IXGFBIKQIO8Y55Z3@example.com> for Stephano@example.com; 
 Sat, 04 May 2012 18:04:00 EDT 
Date: Sat, 04 May 2012 18:04:00 -0400 (EDT) 
From: Trinculo@example.com 
Subject: Meeting next Wednesday 
To: Stephano@example.com 
Message-id: <01IXGFBILT3M8Y55Z3@example.com> 
MIME-version: 1.0 
Content-type: TEXT/PLAIN; CHARSET=US-ASCII 
 
Can we reschedule the meeting of comic relief characters to be at 14:30? 
 
--Boundary_(ID_78nMbcjsTsCboulbhJC84A)-- 
 


Previous Next Contents Index