examples/x400_msrcv.c

This is an example program which can receive a message either from a P7 Message Store or directly from the MTA's P3 channel.

/* Copyright (c) 2003-2014, Isode Limited, London, England.
* All rights reserved.
*
* Acquisition and use of this software and related materials for any
* purpose requires a written licence agreement from Isode Limited,
* or a written licence from an organisation licenced by Isode Limited
* to grant such a licence.
*
*/
/*
*
* Simple example program for receiving a message from a store.
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <x400_msapi.h>
#include <amhs_att.h>
#include <seclabel_api.h> /* For security labels */
#include "example.h"
#include "ms_example.h"
static char *optstr = "u371m:d:p:w:M:D:P:W:";
static void usage(void);
static int get_msg (
struct X400msSession *sp
);
int
main(
int argc,
char **argv)
{
char buffer[BUFSIZ];
char pa[BUFSIZ];
char orn[BUFSIZ];
int status;
int nummsg;
int nummsg_ready;
struct X400msSession *sp;
int contype;
char *def_oraddr;
char *def_dn;
char *def_pa;
/* period to pass into X400msWait() */
int ms_timeout_period = 10;
/* number of timeouts from X400msWait() before exiting */
# define NUM_MSWAIT_TIMEOUTS 10
int max_timeouts = NUM_MSWAIT_TIMEOUTS;
/* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
status = X400InitializeLogging(argv[0], "x400api.xml");
if (status != X400_E_NOERROR) {
fprintf(stderr, "Failed to initialize logging, %s\n", X400msError(status));
} else {
printf("Initialized logging from file x400api.xml\n");
}
if (get_args(argc, argv, optstr)) {
usage();
exit(-1);
}
printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
contype = ic_fgetc(x400_contype, stdin);
if (contype != 10)
ic_fgetc(x400_contype, stdin);
if ( contype < '0' || '2' < contype )
contype = x400_contype;
else
contype -= '0';
if (contype == 0) {
def_oraddr = x400_ms_user_addr;
def_dn = x400_ms_user_dn;
def_pa = x400_ms_presentation_address;
}
else {
def_oraddr = x400_mta_user_addr;
def_dn = x400_mta_user_dn;
def_pa = x400_mta_presentation_address;
}
printf("Your ORAddress [%s] > ", def_oraddr);
ic_fgets(orn, sizeof orn, stdin);
if (orn[strlen(orn) - 1] == '\n')
orn[strlen(orn) - 1] = '\0';
if (orn[0] == '\0')
strcpy(orn, def_oraddr);
/* Prompt for password; note: reflected. */
printf("Password [%s]: ",
contype == 0 ? x400_p7_password : x400_p3_password);
if (ic_fgets(buffer, sizeof buffer, stdin) == NULL)
exit(1);
if (buffer[strlen(buffer) - 1] == '\n')
buffer[strlen(buffer) - 1] = '\0';
if (buffer[0] == '\0')
strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
printf("Presentation Address [%s] > ", def_pa);
ic_fgets(pa, sizeof pa, stdin);
if (pa[strlen(pa) - 1] == '\n')
pa[strlen(pa) - 1] = '\0';
if (pa[0] == '\0')
strcpy(pa, def_pa);
if (talking_to_marben_ms)
status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in Open: %s\n", X400msError(status));
exit(status);
}
if (talking_to_marben_ms)
#ifdef USING_ALERTS
/* If we register the alert auto-action, we will get an alert indication
when a message is delivered. So there is no need to poll at
short intervals within X400ms_Wait - we can do a slow background
poll and rely on the Alert indication to wake the code up instead */
#endif
#ifdef WANT_SESSION_SPECIFIC_LOGGING
/* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
#endif
if (contype == 0) {
#ifdef WANT_AUTOFORWARDING
struct X400msAutoActionParameter *aa_param;
/* Register an Autoforwarding Autoaction. */
/* Add mandatory things to AutoAction parameter for auto-forwarding:
i.e. recipient address */
X400RecipNew(0, &rp);
strlen(def_oraddr));
"AF contentid", -1);
1);
1);
1);
"This message was autoforwarded",
-1);
"This is a cover note", -1);
"AutoForwarded:", -1);
4, aa_param);
if (status != X400_E_NOERROR) {
fprintf(stderr,
"Error in RegisterAutoAction: %s\n", X400msError(status));
/* tidily close the session */
(void) X400msClose(sp);
exit(status);
}
printf("Registered AutoForwarding autoaction (id = 4) OK\n");
#endif
#ifdef USING_ALERTS
/* No parameter needed for Alert autoaction - we do not support
configuration of requested-attributes in this API yet. */
status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 9, NULL);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in RegisterAutoAction: %s\n",
X400msError(status));
/* tidily close the session */
(void) X400msClose(sp);
exit(status);
}
printf("Registered AutoAlert autoaction (id = 9) OK\n");
#endif
/* Just test the register and deregister functions */
status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 10, NULL);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in RegisterAutoAction: %s\n",
X400msError(status));
/* tidily close the session */
(void) X400msClose(sp);
exit(status);
}
printf("Registered AutoAlert autoaction (id = 10) OK\n");
/* Lets do a deregistration of the action we just registered */
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in DeregisterAutoAction: %s\n",
X400msError(status));
/* tidily close the session */
(void) X400msClose(sp);
exit(status);
}
printf("Deregistered AutoAlert autoaction (id = 10) OK\n");
}
ms_timeout_period = 20;
if (nummsg == 0) {
if (ms_timeout_period == 0) {
printf ("\n\nno messages - looping in msWait(%d) .....\n",
ms_timeout_period);
} else {
printf ("\n\nno messages - calling msWait(%d) .....\n",
ms_timeout_period);
}
} else {
printf("%d messages waiting\n", nummsg);
}
while (1) {
/* Using P3
* - if ms_timeout_period > 0, wait once then break
* - if ms_timeout_period == 0, loop through NUM_MSWAIT_TIMEOUTS
* times, then break.
*/
status = X400msWait(sp, ms_timeout_period, &nummsg_ready);
if (status == X400_E_NOERROR) {
printf("====== Getting next msg ======= (%d)\n", nummsg_ready);
(void) get_msg(sp);
max_timeouts = NUM_MSWAIT_TIMEOUTS;
} else {
if (status != X400_E_TIMED_OUT) {
/* tidily close the session */
fprintf(stderr, "X400msWait returned error: %s\n",
X400msError(status));
status = X400msClose(sp);
exit(status);
}
/* printf("X400msWait returned timeout\n"); */
sleep(1);
if (max_timeouts-- == 0)
break;
}
if (ms_timeout_period != 0)
break;
}
status = X400msClose(sp);
return(status);
}
static int get_msg (
struct X400msSession *sp
)
{
int type;
int seqn;
int status;
struct X400msMessage *mp;
char c;
size_t retlen;
char *buf = NULL;
char *databuf = &c;
printf("Getting message\n");
status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
switch (status) {
fprintf(stderr, "MsgGet successfully got message\n");
break;
default :
fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
break;
}
status = print_msg(mp, type);
if (status != X400_E_NOERROR) {
(void) X400msMsgDelete(mp, 0);
exit(status);
}
/* Get binary representation and store to file */
/* First pass to find out how big it needs to be */
status = X400msMsgGetRaw(sp, mp, databuf, 0, &retlen);
if (status != X400_E_NOSPACE) {
fprintf(stderr, "Failed to get raw message length: error %d\n", status);
} else {
struct X400msMessage *newmsg;
int newtype;
databuf = buf = (char *)malloc(retlen);
printf("Data buffer length required = %d\n", (int)retlen);
status = X400msMsgGetRaw(sp, mp, databuf, retlen, &retlen);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Failed to get raw message: error %d\n", status);
} else {
/* Dump to file */
FILE *fd = fopen("message.dump", "w");
if (fd == NULL) {
fprintf(stderr, "Failed to open file message.dump\n");
} else {
if (fwrite(databuf, 1, retlen, fd) < retlen) {
fprintf(stderr, "Failed to write message to file message.dump\n");
} else {
fprintf(stdout, "Dumped message to file message.dump\n");
}
fclose(fd);
}
}
/* And try to reconstruct message from bytes */
status = X400msMsgFromRaw(sp, databuf, retlen, &newmsg, &newtype);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Failed to create message from bytes: error %d\n", status);
}
printf("************************** Printing cached message ************************\n");
print_msg(newmsg, newtype);
if (buf != NULL)
free(buf);
X400msMsgDelete(newmsg, 0);
}
/* Deletes message in message store as well as internal copy */
printf("\n+++ got message - deleting it and returning+++\n");
status = X400msMsgDelete(mp, 0);
return status;
}
static void usage(void) {
printf("usage: %s\n", optstr);
printf("\t where:\n");
printf("\t -u : Don't prompt to override defaults \n");
printf("\t -3 : Use P3 connection \n");
printf("\t -7 : Use P7 connection \n");
printf("\t -m : OR Address in P7 bind arg \n");
printf("\t -d : DN in P7 bind arg \n");
printf("\t -p : Presentation Address of P7 Store \n");
printf("\t -w : P7 password of P7 user \n");
printf("\t -M : OR Address in P3 bind arg \n");
printf("\t -D : DN in P3 bind arg \n");
printf("\t -P : Presentation Address of P3 server\n");
printf("\t -W : P3 password of P3 user \n");
return;
}