An Updated C_MEGA_MAIL Example

By | March 22, 2018

Things get dated. It is sad, but true. Time marches on and little snippets of code you squirreled away for future use start to not work as good, or not even compile because everything around them has changed. Such was the case recently with C_MEGA_MAIL.C. It stayed locked in time and VMS changed. Oh, it still compiled and seemed to work, but when you stuck it in something which sent hundreds of mail messages over 24 hours things got a bit wonky. The problem was the ITEM_LIST structure needed by the functions changed “just a bit.”

I also tweaked this so it could run under a guest account without privs. Sorry about the funky indenting, it didn’t paste well.

/* C_MEGA_MAIL.C
 *
 * Example program to show a user how to send mail.
 *
 * Distributed with "The Minimum You Need to Know
 * to be an OpenVMS Application Developer".
 *
 */

/*
 * ANSI headers
 */
#include <stdlib>
#include <stdio>
#include <string>

/*
 * VMS headers
 */
#include <maildef>
#include <mail$routines>
#include <lib$routines>
#include <descrip>
#include <jpidef>
#include <prvdef>

# define __NEW_STARLET 
#include <iledef>

#define LENGTH(descriptor) descriptor.dsc$w_length

ILE3 nulllist[] = { {0,0,0,0} };

static unsigned int send_context = 0; 
static int priv_user; /* User has priv for commands */

/*;;;;;
 * Function prototypes
 *;;;;;
 */
void add_mail_user_dest( unsigned int *send_context, char *user_str);
void parse_logical_user( unsigned int *send_context, char *user_str);

/*;;;;;
 * Functions and subroutines
 *;;;;;
 */

int main( int *argc, char **argv)
{
 int l_stat;
 char to_str[255], from_str[255], subject_str[255],
 text_file_str[255], translated_name_str[255],
 work_str[255];

ILE3 mail_item_1[5], mail_item_2[5];
 unsigned int priv_bits[2];


 $DESCRIPTOR( work_str_desc, work_str);
 $DESCRIPTOR( translated_name_desc, translated_name_str);

/*
 ** Check the users privledges to see if they are allowed to
 ** change the "from" name
 */
 (void) lib$getjpi(&JPI$_CURPRIV, 0, 0, priv_bits, 0, 0);
 if (priv_bits[0] & PRV$M_SYSPRV)
 {
 priv_user = TRUE;
 }
 else
 {
 priv_user = FALSE;
 }

//;;;;;
 // Initialize the send
 //;;;;;
 l_stat = mail$send_begin( &send_context, nulllist, nulllist);

if (!(l_stat & 1))
 {
 puts( "Error initializing mail interface");
 printf( "Error code %d\n", l_stat);
 exit( l_stat);
 } /* end test for successful init */

//;;;;;
 // Build the attributes
 //;;;;;
 strcpy( to_str, "MEGA_SUPPORT_LIST");
 strcpy( from_str, "HUGHES");
 strcpy( subject_str, "MEGA SYSTEM NOTIFICATION");

int x=0;
 mail_item_1[x].ile3$w_length = strlen( to_str);
 mail_item_1[x].ile3$w_code = MAIL$_SEND_TO_LINE;
 mail_item_1[x].ile3$ps_bufaddr = to_str;
 mail_item_1[x].ile3$ps_retlen_addr = NULL;

++x;
 mail_item_1[x].ile3$w_length = strlen( subject_str);
 mail_item_1[x].ile3$w_code = MAIL$_SEND_SUBJECT;
 mail_item_1[x].ile3$ps_bufaddr = subject_str;
 mail_item_1[x].ile3$ps_retlen_addr = NULL;

if (priv_user)
 {
 ++x;
 mail_item_1[x].ile3$w_length = strlen( from_str);
 mail_item_1[x].ile3$w_code = MAIL$_SEND_FROM_LINE;
 mail_item_1[x].ile3$ps_bufaddr = from_str;
 mail_item_1[x].ile3$ps_retlen_addr = NULL;
 }

++x;
 mail_item_1[x].ile3$w_length = 0;
 mail_item_1[x].ile3$w_code = 0;
 mail_item_1[x].ile3$ps_bufaddr = NULL;
 mail_item_1[x].ile3$ps_retlen_addr = NULL;

l_stat = mail$send_add_attribute( &send_context, mail_item_1, nulllist);

if (!(l_stat & 1))
 {
 puts( "Error setting up mail header information");
 printf( "Error code %d\n", l_stat);
 exit( l_stat);
 } /* end test for failure */


 //;;;;;
 // Add the message body
 //;;;;;
 strcpy( text_file_str, "HELLO.TXT");

mail_item_2[0].ile3$w_length = strlen( text_file_str);
 mail_item_2[0].ile3$w_code = MAIL$_SEND_FILENAME;
 mail_item_2[0].ile3$ps_bufaddr = text_file_str;
 mail_item_2[0].ile3$ps_retlen_addr = NULL;

mail_item_2[1].ile3$w_length = 0;
 mail_item_2[1].ile3$w_code = 0;
 mail_item_2[1].ile3$ps_bufaddr = NULL;
 mail_item_2[1].ile3$ps_retlen_addr = NULL;

l_stat = mail$send_add_bodypart( &send_context, mail_item_2, nulllist);

if ( !(l_stat & 1))
 {
 puts( "Error creating message body");
 printf( "Error code %d\n", l_stat);
 exit( l_stat);
 } /* end test for failure */

//;;;;;
 // Now we have to actually fill in the address.
 // Mail does not use the address information setup
 // in the message header.
 //;;;;;
 memset( translated_name_str, '\0', sizeof( translated_name_str));
 strcpy( work_str, to_str);

LENGTH( work_str_desc) = strlen( work_str);

l_stat = lib$get_logical( &work_str_desc, &translated_name_desc);

if ( strlen( translated_name_str) < 1)
 {
 //
 // Destination is not a logical, just add the user
 //
 add_mail_user_dest( &send_context, work_str);
 }
 else
 parse_logical_user( &send_context, translated_name_str);


 //;;;;;
 // Send the message
 //;;;;;

l_stat = mail$send_message( &send_context, nulllist, nulllist);

if ( !(l_stat & 1))
 {
 puts( "Error sending the mail message");
 printf( "Error code %d\n", l_stat);
 exit( l_stat);
 } /* end test for failure */

//;;;;;
 // Clean up the mail context
 //;;;;;
 l_stat = mail$send_end( &send_context, nulllist, nulllist);

if ( !(l_stat & 1))
 {
 puts( "Error ending mail send");
 printf( "Error code %d\n", l_stat);
 exit( l_stat);
 } /* end test for failure */

return 1;

} /* end main */


//;;;;;;;;;;
// Subroutine to parse the mail destinations from a 
// translated logical string.
//;;;;;;;;;;
void parse_logical_user( unsigned int *send_context, char *user_str)
{
 int l_stat;
 char work_str[1024], *tmp, *tmp2;

strcpy( work_str, user_str);
 tmp = work_str;

while( strlen( tmp) > 0)
 {
 tmp2 = strchr( tmp, ',');
 if ( tmp2 != NULL)
 {
 *tmp2 = '\0';
 }

add_mail_user_dest( send_context, tmp);

if ( tmp2 != NULL) 
 tmp = tmp2+1;
 else
 *tmp = '\0';

} /* end while loop */
} /* end parse_logical_user subroutine */

//;;;;;
// Subroutine to add a mail user destination to the mail
// message currently being built.
//;;;;;
void add_mail_user_dest( unsigned int *send_context, char *user_str)
{
 int l_stat;
 short int w_user_type;

ILE3 m_item[5];

m_item[0].ile3$w_length = strlen( user_str);
 m_item[0].ile3$w_code = MAIL$_SEND_USERNAME;
 m_item[0].ile3$ps_bufaddr = user_str;
 m_item[0].ile3$ps_retlen_addr = NULL;

w_user_type = MAIL$_TO;

m_item[1].ile3$w_length = sizeof(w_user_type);
 m_item[1].ile3$w_code = MAIL$_SEND_USERNAME_TYPE;
 m_item[1].ile3$ps_bufaddr = &w_user_type;
 m_item[1].ile3$ps_retlen_addr = NULL;

m_item[2].ile3$w_length = 0;
 m_item[2].ile3$w_code = 0;
 m_item[2].ile3$ps_bufaddr = NULL;
 m_item[2].ile3$ps_retlen_addr = NULL;

l_stat = mail$send_add_address( send_context, m_item, nulllist);

if ( !(l_stat & 1))
 {
 puts( "Error adding mail destination address");
 printf( "Error code %d\n", l_stat);
 exit( l_stat);
 } /* end test for failure */


} /* end add_mail_user_dest subroutine */



 

Category: Information Technology Thank You Sir May I Have Another Tags: , ,

About seasoned_geek

Roland Hughes started his IT career in the early 1980s. He quickly became a consultant and president of Logikal Solutions, a software consulting firm specializing in OpenVMS application and C++/Qt touchscreen/embedded Linux development. Early in his career he became involved in what is now called cross platform development. Given the dearth of useful books on the subject he ventured into the world of professional author in 1995 writing the first of the "Zinc It!" book series for John Gordon Burke Publisher, Inc. A decade later he released a massive (nearly 800 pages) tome "The Minimum You Need to Know to Be an OpenVMS Application Developer" which tried to encapsulate the essential skills gained over what was nearly a 20 year career at that point. From there "The Minimum You Need to Know" book series was born. Three years later he wrote his first novel "Infinite Exposure" which got much notice from people involved in the banking and financial security worlds. Some of the attacks predicted in that book have since come to pass. While it was not originally intended to be a trilogy, it became the first book of "The Earth That Was" trilogy: Infinite Exposure Lesedi - The Greatest Lie Ever Told John Smith - Last Known Survivor of the Microsoft Wars When he is not consulting Roland Hughes posts about technology and sometimes politics on his blog. He also has regularly scheduled Sunday posts appearing on the Interesting Authors blog.