Previous | Next | Contents | Index |
Each of the two programs shown in Examples 1-5 and 1-6 constitutes a PMDF-to-batch-SMTP channel which reads messages from a message queue, converting each message to a batch SMTP format stored in a file on disk. If the conversion is successful, then the message is dequeued and deferred otherwise. Sample output is given in Example 1-7.
Note that these example programs always attempt to specify an envelope
id in the batch SMTP message they output. This is done for illustration
purposes only. In general, the code should check to see if the envelope
id obtained with PMDFgetEnvelopeId
is of zero length. Only
if it has non-zero length should it then be outputting an envelope id.
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:
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.
read_line
is a routine which
will return true (1) if PMDFgetLine
successfully reads a
line from a message or false (0) otherwise. If
PMDFreadLine
returns any error other than
PMDF__EOF
, then the check routine, ,
is invoked.
open_outbound
is a routine which
opens an output file to which to write the batch SMTP command. Output
from PMDFgetUniqueString
is used in generating the file
name.
notify
is a routine which,
builds an RFC 1891 NOTIFY= parameter based upon the NOTARY flags for an
envelope "To:" recipient.
PMDFinitialize
is invoked with
the ischannel argument true.
PMDFdequeueInitialize
creates
and initializes a message dequeue context.
get_message
routine,
the program loops over all messages to be processed.
PMDFgetRecipient
, the
program loops over the envelope "To:" address list in the currently
accessed message.
PMDFgetRecipientFlags
.
read_line
routine, the
program loops over the message header and body, copying each line to
the batch SMTP file.
Example 1-5 Message Dequeuing (Pascal) |
---|
(* api_example3.pas -- Dequeue a message and output it in batch SMTP format *) [inherit ('pmdf_exe:apidef')] program api_example3 (output); type uword = [word] 0..65535; string = packed array [1..ALFA_SIZE] of char; bigstring = packed array [1..BIGALFA_SIZE] of char; vstring = varying [64] of char; var dq_context : PMDF_dq; empty : varying [1] of char; env_id, from_adr, host, orig_adr, to_adr : string; env_id_len, from_adr_len, host_len, orig_adr_len, to_adr_len, txt_len : uword; nflags, stat : integer; outbound_open : boolean; outfile : text; txt : bigstring; 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); if outbound_open then close (file_variable := outfile, disposition := delete); halt; end; (* if *) end; (* check *) function get_message : boolean; (2) var msg_file : string; msg_file_len : uword; 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 *) function read_line : boolean; (3) begin (* read_line *) stat := PMDF_read_line (dq_context, txt, txt_len); read_line := odd (stat); if (not odd (stat)) and (stat <> PMDF__EOF) then check (stat); end; (* read_line *) procedure open_outbound; (4) var str : string; str_len : uword; begin (* open_outbound *) check (PMDF_get_unique_string (str, str_len)); open (file_variable := outfile, file_name := 'ZZ' + substr (str, 1, str_len) + '.00', history := NEW, record_length := 1024); stat := status (outfile); if stat >= 0 then begin rewrite (outfile); outbound_open := true; end else begin writeln ('Pascal file error ', stat:0, '; aborting'); check (0); end; (* if *) end; (* open_outbound *) function notify (nflags : integer) : vstring; (5) var str : vstring; procedure add (bit : integer; toadd : varying [len] of char); begin (* add *) if 0 <> uand (nflags, bit) then begin if length (str) = 0 then str := ' NOTIFY=' else str := str + ','; str := str + toadd; end; (* if *) end; (* add *) begin (* notify *) str := ''; add (PMDF_RECEIPT_NEVER, 'NEVER'); add (PMDF_RECEIPT_FAILURES, 'FAILURE'); add (PMDF_RECEIPT_DELAYS, 'DELAY'); add (PMDF_RECEIPT_SUCCESSES, 'SUCCESS'); notify := str; end; (* notify *) begin (* api_example3 *) empty := ''; dq_context := nil; outbound_open := false; check (PMDF_initialize (true)); (6) check (PMDF_get_host_name (host, host_len)); check (PMDF_dequeue_initialize (dq_context)); (7) while get_message do begin (8) check (PMDF_get_envelope_id (dq_context, env_id, env_id_len)); open_outbound; writeln (outfile, 'EHLO ', substr (host, 1, host_len)); writeln (outfile, 'MAIL FROM:<', substr (from_adr, 1, from_adr_len), '>', ' ENVID=', substr (env_id, 1, env_id_len)); while odd (PMDF_get_recipient (dq_context, to_adr, to_adr_len, (9) orig_adr, orig_adr_len)) do begin check (PMDF_get_recipient_flags (dq_context, nflags)); (10) writeln (outfile, 'RCPT TO:<', substr (to_adr, 1, to_adr_len), '>', ' ORCPT=', substr (orig_adr, 1, orig_adr_len), notify (nflags)); check (PMDF_recipient_disposition (dq_context, nflags, (11) PMDF_DISP_DELIVERED, substr (to_adr, 1, to_adr_len), substr (orig_adr, 1, orig_adr_len), empty)); end; (* while *) writeln (outfile, 'DATA'); while read_line do begin (12) if txt_len > 0 then if txt[1] = '.' then write (outfile, '.'); writeln (outfile, substr (txt, 1, txt_len)); end; (* while *) writeln (outfile, '.'); writeln (outfile, 'QUIT'); close (outfile); outbound_open := false; check (PMDF_dequeue_message_end (dq_context, false, empty)); (13) end; (* while *) check (PMDF_dequeue_end (dq_context)); (14) check (PMDF_done); end. (* api_example3 *) |
Example 1-6 Message Dequeuing (C) |
---|
/* api_example4.c -- Dequeue a message and output it in batch SMTP format */ #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 filename, from_adr, txt; int outbound_open, txt_len; PMDF_dq *dq_context = 0; FILE *outfile; 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 (outbound_open) { fclose (outfile); remove (filename); } if (!stat) exit (0); else exit (stat); } } int get_message (void) (2) { string msg_file; int from_adr_len, msg_file_len, stat; from_adr_len = msg_file_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); } int read_line (void) (3) { int stat; txt_len = BIGALFA_SIZE; stat = PMDFreadLine (&dq_context, txt, &txt_len); if ( !(1 & stat) && stat != PMDF__EOF) check (stat); return (1 & stat); } void open_outbound (void) (4) { char str[18+5+1]; int str_len = 18; check (PMDFgetUniqueString (str, &str_len)); sprintf (filename, "ZZ%s.00", str); outfile = fopen (filename, "w"); if (!outfile) { fprintf (stderr, "Error opening output file; aborting\n", filename); check (0); } outbound_open = 1; } void add (int nflags, int bit, char *src, char *dst) { if (!(nflags & bit)) return; if (*dst) strcat (dst, ","); strcat (dst, src); } void make_notify (int nflags, char *buf) (5) { *buf = '\0'; add (nflags, PMDF_RECEIPT_NEVER, "NEVER", buf); add (nflags, PMDF_RECEIPT_FAILURES, "FAILURE", buf); add (nflags, PMDF_RECEIPT_DELAYS, "DELAY", buf); add (nflags, PMDF_RECEIPT_SUCCESSES, "SUCCESS", buf); } main () { string env_id, host, orig_adr, to_adr; int env_id_len, nflags, host_len, orig_adr_len, to_adr_len; char notify[64]; outbound_open = 0; check (PMDFinitialize (1)); (6) host_len = ALFA_SIZE; check (PMDFgetHostName (host, &host_len)); check (PMDFdequeueInitialize (&dq_context)); (7) while (get_message ()) { (8) env_id_len = ALFA_SIZE; check (PMDFgetEnvelopeId (&dq_context, env_id, &env_id_len)); open_outbound (); fprintf (outfile, "EHLO %s\n", host); fprintf (outfile, "MAIL FROM:<%s> ENVID=%s\n", from_adr, env_id); to_adr_len = orig_adr_len = ALFA_SIZE; while (1 & PMDFgetRecipient (&dq_context, to_adr, &to_adr_len, (9) orig_adr, &orig_adr_len)) { check (PMDFgetRecipientFlags (&dq_context, &nflags)); (10) make_notify (nflags, notify); fprintf (outfile, "RCPT TO:<%s> ORCPT=%s", to_adr, orig_adr); if (notify[0]) fprintf (outfile, " NOTIFY=%s\n", notify); else fprintf (outfile, "\n"); check (PMDFrecipientDisposition (&dq_context, nflags, (11) PMDF_DISP_DELIVERED, to_adr, to_adr_len, orig_adr, orig_adr_len, NULL, 0)); to_adr_len = orig_adr_len = ALFA_SIZE; } fprintf (outfile, "DATA\n"); while (read_line ()) { (12) if (txt_len > 0) if (txt[0] == '.') fprintf (outfile, "."); fprintf (outfile, "%s\n", txt); } fprintf (outfile, ".\nQUIT\n"); fclose (outfile); outbound_open = 0; check (PMDFdequeueMessageEnd (&dq_context, 0, NULL, 0)); (13) } check (PMDFdequeueEnd (&dq_context)); (14) check (PMDFdone ()); } |
Example 1-7 Output of Examples 1-5 and 1-6 |
---|
EHLO EXAMPLE.COM MAIL FROM:<stephano@example.com> ENVID=01ISXU84PB929AMHQL@EXAMPLE.COM RCPT TO:<caliban@example.com> ORCPT=rfc822;caliban@island.example.com NOTIFY=FAILURES,DELAY DATA Received: from EXAMPLE.COM by EXAMPLE.COM (PMDF #1339) id <01GP3A97QW9CAATXKZ@EXAMPLE.COM>; Sat, 04 May 2012 18:04:00 EDT Date: 04 May 2012 18:04:00 -0400 (EDT) From: "Stephano the Drunken Butler" <stephano@example.com> Subject: Testing To: "Caliban the Savage" <caliban@island.example.com> Message-id: <01GP3A97R5WIAATXKZ@EXAMPLE.COM> MIME-version: 1.0 Content-type: TEXT/PLAIN; CHARSET=US-ASCII Content-transfer-encoding: 7BIT This is a test of the emergency broadcasting system. Please do not be alarmed. Please do not hold your breath. Bye . QUIT |
Previous | Next | Contents | Index |