examples/x400_mttutorial.c

This is a streamlined heavily commented example program, which transfers a message into the MTA, and then transfers the message out of it.

00001 /*  Copyright (c) 2008, Isode Limited, London, England.
00002  *  All rights reserved.
00003  *                                                                       
00004  *  Acquisition and use of this software and related materials for any      
00005  *  purpose requires a written licence agreement from Isode Limited,
00006  *  or a written licence from an organisation licenced by Isode Limited
00007  *  to grant such a licence.
00008  *
00009  */
00010 
00011 /* x400_mttutorial.c 
00012  *
00013  * The purpose of this file is to simply explain how to send and receive
00014  * X400 email messages using the Message Transfer (Gateway) API.
00015  *
00016  */
00017 
00018 /*
00019  * Setting up your configuration.
00020  * Before you go any further you need to have a suitable configuration created
00021  * The simplist way to do this is to run the "quickconfig" program, and
00022  * select the "X.400" option as the configuration type.
00023  *
00024  * The "quickconfig" program is located within BINDIR. So that's typically
00025  * /opt/isode/bin on unix, and c:\Program Files\Isode\bin on Windows.
00026  *
00027  *
00028  * The purpose of this tutorial is to provide a very simple example of the 
00029  * basic principles of the Isode X.400api
00030  *
00031  * Specifically it demonstrates:
00032  * 1) The Object Oriented approach to manipulating X.400 Messages
00033  * 2) How to create a new "Session"
00034  * 3) How to create a new message associated with that session.
00035  * 4) How to add attributes to that Message.
00036  * 5) How to receive a Message.
00037  * 6) How to retrieve attributes from that Message.
00038  * 7) How to close a session.
00039  * 8) How to safely destroy a Message.
00040  *
00041  * This tutorial will only cover these basics.
00042  * the example X.400api programs give a more detailed example of how to use 
00043  * the X.400api.
00044  */
00045 
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 
00049 
00050 #include <x400_mtapi.h>
00051 #include "example.h"
00052 #include <sys/types.h>
00053 #include <sys/stat.h>
00054 #include <fcntl.h>
00055 #include <errno.h>
00056 #include <time.h>
00057 
00058 char *orig = "/CN=GatewayUser/OU=Sales/OU=dhcp-164/O=GatewayMTA/PRMD=TestPRMD/ADMD=TestADMD/C=GB/";
00059 char *recip = "/CN=GatewayUser/OU=Sales/OU=dhcp-164/O=GatewayMTA/PRMD=TestPRMD/ADMD=TestADMD/C=GB/";
00060 
00061 static void send_hello_world(
00062         struct X400mtSession *sp
00063 );
00064 
00065 static void receive_hello_world(
00066     struct X400mtSession *sp
00067 );
00068 
00069 int main () 
00070 {
00071   int status;
00072   struct X400mtSession *sp; /* This is the session pointer object.
00073                              * All susequent objects like message objects
00074                              * are associated back to this session 
00075                              * When the session is closed these objects are 
00076                              * free'd.
00077                              */
00078   
00079   /* Open a new session, and check that the session has been opened ok.
00080    * The different values the API can return are in x400_att.h */
00081   
00082   status = X400mtOpen (x400_channel, &sp);
00083   if ( status != X400_E_NOERROR ) {
00084     fprintf (stderr, "Error in Open: %s\n", X400mtError (status));
00085     exit (status);
00086   }
00087   
00088   /* We now want to configure logging
00089    * Isode logging is configured using a specific XML file.
00090    * a GUI editor SBINDIR/logconfig allows you to easily alter the XML file.
00091    *
00092    * To specify a particular xml file, we need to manipulate the
00093    * session object.
00094    *
00095    * To do this we call X400mtSetStrDefault, passing in the session
00096    * pointer, the attribute of the object we wish to manipulate 
00097    * (X400_S_LOG_CONFIGURATION_FILE), the filename, and the size in bytes
00098    * of the filename.
00099    *
00100    * Since we don't actually have the size of the filename in bytes, 
00101    * we can pass in 0 or -1 in for the size field. The underlying code will
00102    * calculate the size for us.
00103    */
00104 
00105   X400mtSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
00106  
00107   /* The reference section of the API manual contains descriptions of
00108    * other default attributes you may set.
00109    */
00110   
00111   /* We can now attempt to send a message */
00112   send_hello_world(sp);
00113   
00114  
00115 
00116   /* We can now attempt to receive a message */
00117   receive_hello_world(sp);
00118 
00119   X400mtClose (sp);
00120   if ( status != X400_E_NOERROR ) {
00121     fprintf (stderr, "Error in Close: %s\n", X400mtError (status));
00122     exit (status);
00123   }
00124   
00125   exit(0);
00126 }
00127 
00128 
00129 /*
00130  * 1) Sending a "Hello World!" email
00131  * 
00132  * You will need to know a single X.400 email addresses.
00133  * This email address needs to be routed to use the Gateway channel.
00134  * 
00135  * Fortunately quickconfig helps by providing a suitable user:
00136  * /CN=GatewayUser/OU=Sales/OU=HOSTNAME/O=GatewayMTA/PRMD=TestPRMD/ADMD=TestADMD/C=GB/
00137  * 
00138  * You should alter "HOSTNAME" to being the correct value for your 
00139  * configuration.
00140  *
00141  * The following section will show you how to send a "Hello World!" 
00142  * X.400 email througth the messag transfer API.
00143  */
00144 
00145 static void send_hello_world(
00146     struct X400mtSession *sp
00147 )
00148 {
00149   int status;
00150 
00151   /* Now lets create a new message */
00152   struct X400mtMessage *mp; /* This is the pointer to a message object */
00153   struct X400Recipient *rp; /* This is the pointer to a new recipient  */
00154 
00155 
00156   printf("Now sending simple message\n");
00157   /* We now need to create a new message object, and have the new
00158    * message object associated with the session object.
00159    *
00160    * To do this we use X400mtMsgNew.
00161    */
00162   status = X400mtMsgNew (sp, X400_MSG_MESSAGE, &mp);
00163   
00164   if ( status != X400_E_NOERROR ) {
00165     fprintf (stderr, "Error in MsgNew: %s\n", X400mtError (status));
00166     exit (status);
00167   }
00168   
00169   /* We can now manipulate the message object */
00170   
00171   /* Add an originator. Similar concepts here,
00172    * we are manipulating the message object to add an originator address
00173    */
00174   status = X400mtMsgAddStrParam (mp, X400_S_OR_ADDRESS, orig, -1);
00175     
00176   if ( status != X400_E_NOERROR ) {
00177     fprintf (stderr, "Error adding orignator: %s\n", X400mtError (status));
00178     exit (status);
00179   }
00180   
00181   /* Create a new recipient object, and associate it with the message object.
00182    */
00183   status = X400mtRecipNew (mp, X400_RECIP_STANDARD, &rp);
00184   if ( status != X400_E_NOERROR ) {
00185     fprintf (stderr, "Error adding recipient: %s\n", X400mtError (status));
00186     exit (status);
00187   }
00188 
00189   /* We can now manipulate the recipient object and add the following:
00190    * 1) The OR address of the recipient.
00191    * Obviously this is important, otherwise the message cannot be routed.
00192    *
00193    * 2) The responsibility value 
00194    * You don't actually need to set this. However it is usefull to see
00195    * how the attributes being manipulated correspond with the standards.
00196    */
00197   status = X400mtRecipAddStrParam (rp, X400_S_OR_ADDRESS, recip, -1);
00198   if ( status != X400_E_NOERROR ) {
00199     fprintf (stderr, "Error adding recipient address: %s\n", 
00200              X400mtError (status));
00201     exit (status);
00202   }
00203   
00204   /* The following attribute might see slightly confusing.
00205    * The best thing to do at this point is to take a brief look 
00206    * at X.411, section 12.2.1.1.1.6, this describes the responsibility
00207    * attribute.
00208    */
00209 
00210   status = X400mtRecipAddIntParam (rp, X400_N_RESPONSIBILITY, 1);
00211   if ( status != X400_E_NOERROR ) {
00212     fprintf (stderr, "Error adding recipient responsibility: %s\n", 
00213              X400mtError (status));
00214     exit (status);
00215   }
00216 
00217   /* Extra envelope attributes */
00218   status = X400mtMsgAddIntParam (mp, X400_N_CONTENT_TYPE, 2);
00219   if ( status != X400_E_NOERROR ) {
00220     fprintf (stderr, "Error adding Content type : %s\n", 
00221              X400mtError (status));
00222     exit (status);
00223   }
00224   
00225   /* And now for the content */
00226   {
00227     char *content = "Hello World!";
00228     char *subject = "A simple test message";
00229 
00230     status = X400mtMsgAddStrParam (mp,X400_T_IA5TEXT, content , -1);
00231     if ( status != X400_E_NOERROR ) {
00232       fprintf (stderr, "Error adding content : %s\n", 
00233                X400mtError (status));
00234       exit (status);
00235     }
00236 
00237     status = X400mtMsgAddStrParam (mp, X400_S_SUBJECT, subject, -1);
00238      if ( status != X400_E_NOERROR ) {
00239        fprintf (stderr, "Error adding subject : %s\n", 
00240                 X400mtError (status));
00241        exit (status);
00242      }
00243   }
00244   
00245   /* we should now be able to send the message */
00246   status = X400mtMsgSend (mp);
00247   if ( status != X400_E_NOERROR ) {
00248     fprintf (stderr, "Error in MsgSend: %s\n", X400mtError (status));
00249     exit (status);
00250   }
00251   
00252   /* We can now delete the message */
00253   status = X400mtMsgDelete (mp);
00254   if ( status != X400_E_NOERROR ) {
00255     fprintf (stderr, "Error in X400mtMsgDelete: %s\n", X400mtError (status));
00256     exit (status);
00257   }
00258   
00259   printf("Sent message\n");
00260 }
00261 
00262 
00263 static void receive_hello_world(
00264     struct X400mtSession *sp
00265 )
00266 {
00267   struct X400mtMessage *mp;
00268   int status;
00269   int type;
00270   char    buffer[BUFSIZ];
00271   size_t  length;
00272 
00273   printf("Now fetching message\n");
00274 
00275   status = X400mtMsgGetStart (sp, &mp, &type);
00276    if ( status != X400_E_NOERROR ) {
00277      fprintf (stderr, "Error in X400mtMsgGetStart: %s\n", 
00278               X400mtError (status));
00279      exit (status);
00280    }
00281 
00282    switch ( type) {
00283    case X400_MSG_REPORT:
00284      printf("Got a report\n");
00285      exit(0);
00286    case X400_MSG_PROBE:
00287      printf("Got a probe\n");
00288      exit(0);
00289    case X400_MSG_MESSAGE:
00290      break;
00291    }
00292    
00293    /* Get the originator */
00294    status = X400mtMsgGetStrParam (mp, X400_S_OR_ADDRESS,
00295                                   buffer, sizeof buffer , &length);
00296    if(status == X400_E_NOERROR) {
00297      printf ("Originator: %.*s\n",(int)length,buffer);
00298    } else if (status == X400_E_NOSPACE) {
00299      /* This is an interesting error.
00300       * It means that the size of buffer is too small for the originator 
00301       * address. The correct thing to do here is to create a buffer 
00302       * of size length bytes to hold the value.
00303       * 
00304       * All of the GetStrParam functions work in this way.
00305       */
00306      
00307      char * big_buff = NULL;
00308      big_buff = (char *) malloc((sizeof(char)) * length);
00309      status = X400mtMsgGetStrParam (mp, X400_S_OR_ADDRESS,
00310                                     big_buff, length , &length);
00311      if (status != X400_E_NOERROR) {
00312        fprintf(stderr, "Error in getting originator address: %s\n", 
00313                X400mtError (status));
00314        exit (status);
00315      }
00316      printf("Large Originator: %.*s\n",(int)length,big_buff);
00317      free(big_buff);
00318 
00319    } else {
00320      fprintf (stderr, "Error in getting originator address: %s\n", 
00321               X400mtError (status));
00322      exit (status);
00323    }
00324 
00325    {
00326      /* Fetching recipients 
00327       *
00328       * Within the message there are 1 or more recipients.
00329       * so it is important to try to read through the whole list.
00330       *
00331       * All list objects work in this same way.
00332       */
00333      int n;
00334      struct X400Recipient *rp; /* Pointer to recipient object */
00335       for ( n = 1; ; n++ ) {
00336         /* Get the next recipient object with a "Get" command
00337          *  Notice that I'm using the "X400_RECIP_ENVELOPE".
00338          * IE this is fetching recipients from the envelope.
00339          * We can fetch recipients from the message header as well
00340          * Using X400_RECIP_PRIMARY / X400_RECIP_CC / ETC
00341          */
00342         status = X400mtRecipGet (mp, X400_RECIP_ENVELOPE, n, &rp);
00343         if ( status == X400_E_NO_RECIP ) {
00344           printf("Got final recipient\n");
00345             break;
00346         } else if ( status != X400_E_NOERROR ) {
00347             fprintf (stderr, "Error fetching recipients: %s\n", 
00348                 X400mtError (status));
00349             exit(status);
00350         }
00351         
00352         /* Now we have a recipient object that represents a single 
00353            recipient. 
00354         */
00355         
00356         status = X400mtRecipGetStrParam (rp, X400_S_OR_ADDRESS,
00357                                          buffer, BUFSIZ, &length);
00358         if ( status == X400_E_NOERROR ) {
00359             printf ("%s recipient %d: %.*s\n", buffer, n, 
00360                     (int)length, buffer);
00361         } else {
00362           fprintf (stderr, "Error fetching OR Address: %s\n", 
00363                    X400mtError (status));
00364           exit (status);
00365         }
00366 
00367         /* It is possible to continue to try to obtain other recipient 
00368            information. However lets keep it simple here
00369         */
00370 
00371       }
00372    }/* end of fetch recips*/
00373 
00374    /* Now lets obtain the subject of the message */
00375    /* Subject */
00376     status = X400mtMsgGetStrParam (mp, X400_S_SUBJECT,
00377                                    buffer, sizeof buffer , &length);
00378     if ( status == X400_E_NOERROR ) {
00379       printf ("Subject: %.*s\n", (int)length, buffer);
00380     } else {
00381       fprintf (stderr, "Error fetching subject: %s\n", 
00382                    X400mtError (status));
00383       exit (status);
00384     }
00385     /* Followed by the message content (Hello World).
00386      * The message we just created contained an ia5-text bodypart
00387      * so lets request that
00388      */
00389     
00390     status = X400mtMsgGetStrParam (mp, X400_T_IA5TEXT,
00391                                    buffer, sizeof buffer , &length);
00392     if ( status == X400_E_NOERROR ) {
00393       printf ("Text:\n%.*s\n", (int)length, buffer);
00394     } else {
00395       fprintf (stderr, "Error fetching ia5-text bodypart: %s\n", 
00396                    X400mtError (status));
00397       exit (status);
00398     }
00399 
00400     /* Now that we've got the message we need to let the MTA know the message
00401      * has been transfered ok*/
00402     status = X400mtMsgGetFinish (mp, X400_E_NOERROR, -1, -1, "");
00403     if ( status != X400_E_NOERROR ) {
00404         printf("X400mtMsgFinish returned error %d\n", status);
00405         fprintf (stderr, "Error in X400mtMsgFinish: %s\n", 
00406             X400mtError (status));
00407     }
00408 
00409     /* And now we can delete our own copy of the message */
00410     status = X400mtMsgDelete (mp);
00411     if ( status != X400_E_NOERROR ) {
00412         printf("X400mtMsgDelete returned error %d\n", status);
00413         fprintf (stderr, "Error in X400mtMsgDelete: %s\n", 
00414             X400mtError (status));
00415     }
00416     
00417 }
00418 
Copyright © 2008 Isode privacy   feedback Subscribe to our rss newsfeed