x400_mssend.c
1/*
2 * Copyright (c) 2003-2026, Isode Limited, London, England.
3 * All rights reserved.
4 *
5 * Acquisition and use of this software and related materials for any
6 * purpose requires a written licence agreement from Isode Limited,
7 * or a written licence from an organisation licenced by Isode Limited
8 * to grant such a licence.
9 */
10
11/*
12 * @VERSION@
13 * Simple example program for submitting a message via a message store.
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21#ifndef _WIN32
22#include <unistd.h>
23#endif
24#include "example.h"
25#include "ms_example.h"
26#include "time.h"
27
28#include <errno.h>
29#include <fcntl.h>
30#include <seclabel_api.h> /* For security labels */
31#include <x400_msapi.h>
32
33static char *optstr = "u371m:d:p:w:M:D:P:W:o:O:r:l:R:y:C:iaqsAvf:kK:B:";
34
35/* These are the data items used to construct the message for submission */
36static char *default_recip = "/CN=P7User1/O=attlee/PRMD=TestPRMD/ADMD=TestADMD/C=GB/";
37char *recip;
38static const char text[] = "First line\r\nSecond line\r\n";
39static char *binary_data;
40
41static char *fwd_subject = "Forwarded message subject";
42
43static int add_binary_attachment(struct X400msMessage *mp, char *filename_to_send);
44static int add_fwd_bp(struct X400msMessage *mp, char *recip_orn, char *recip_dn);
45static int add_ftbp(struct X400msMessage *mp);
46static void usage(void);
47
48int main(int argc, char **argv) {
49 char creds[BUFSIZ];
50 char pa[BUFSIZ];
51 char orn[BUFSIZ];
52 char tmp[BUFSIZ];
53 int status;
54 struct X400msSession *sp;
55 struct X400msMessage *mp;
56 struct X400Recipient *rp;
57 int contype;
58 char *def_oraddr;
59 char *def_dn;
60 char *def_pa;
61
62 if (get_args(argc, argv, optstr)) {
63 usage();
64 exit(-1);
65 }
66
67 printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
68 contype = ic_fgetc(x400_contype, stdin);
69 if (contype != 10) {
70 ic_fgetc(x400_contype, stdin);
71 }
72
73 if (contype < '0' || '2' < contype) {
74 contype = x400_contype;
75 }
76 else {
77 contype -= '0';
78 }
79
80 if (contype == 0) {
81 def_oraddr = x400_ms_user_addr;
82 def_dn = x400_ms_user_dn;
83 def_pa = x400_ms_presentation_address;
84 }
85 else {
86 def_oraddr = x400_mta_user_addr;
87 def_dn = x400_mta_user_dn;
88 def_pa = x400_mta_presentation_address;
89 }
90
91 printf("Your ORAddress [%s] > ", def_oraddr);
92 ic_fgets(orn, sizeof orn, stdin);
93
94 if ((strlen(orn) > 0) && (orn[strlen(orn) - 1] == '\n')) {
95 orn[strlen(orn) - 1] = '\0';
96 }
97
98 if (orn[0] == '\0') {
99 strcpy(orn, def_oraddr);
100 }
101
102 // Prompt for password; note: reflected.
103 printf("Password [%s]: ", contype == 0 ? x400_p7_password : x400_p3_password);
104 if (ic_fgets(creds, sizeof(creds), stdin) == NULL) {
105 exit(1);
106 }
107
108 if ((strlen(creds) > 0) && (creds[strlen(creds) - 1] == '\n')) {
109 creds[strlen(creds) - 1] = '\0';
110 }
111 if (creds[0] == '\0') {
112 strcpy(creds, contype == 0 ? x400_p7_password : x400_p3_password);
113 }
114
115 // Presentation Address.
116 printf("Presentation Address [%s] > ", def_pa);
117 ic_fgets(pa, sizeof pa, stdin);
118
119 if ((strlen(pa) > 0) && (pa[strlen(pa) - 1] == '\n')) {
120 pa[strlen(pa) - 1] = '\0';
121 }
122
123 if (pa[0] == '\0') {
124 strcpy(pa, def_pa);
125 }
126
127 if (talking_to_marben_ms) {
129 }
130
131 /*
132 By default (an industry norm) the simple bind response password (mtaPassword) for the MTA is never checked.
133 We can force this checking by setting the mtaPassword parameter when building the simple authentication credentials.
134 If we tokenise the credentials and the mtaPassword is NULL or empty, we skip the test, and just accept whatever is returned.
135 Example 1:
136 char* creds = X400msBuildCredentials(0, pass, "MTAPassword", NULL, NULL, NULL, NULL, NULL);
137 and passing creds as the credentials argument to X400msOpen() will check if the returned password matches "MTAPassword".
138 Example 2:
139 char* creds = X400msBuildCredentials(0, pass, NULL, NULL, NULL, NULL, NULL, NULL);
140 and passing creds as the credentials argument to X400msOpen(), or just passing the plain pass as the credentials argument to x400_ms_open() will skip the test.
141
142 The creds pointer must be freed in both cases.
143 */
144 // We've got what we need - now open an API session.
145 status = X400msOpen(contype, orn, def_dn, creds, pa, NULL, &sp);
146
147 if (status != X400_E_NOERROR) {
148 fprintf(stderr, "Error in Open: %s\n", X400msError(status));
149 exit(status);
150 }
151
152 if (talking_to_marben_ms) {
154 }
155
156 /* setup logging */
158
159 /* Turn on generation of extended-subject heading extension */
161
162 /* Turn on error on duplicate string attribute setting */
164
165 /* Configure the character sets to be used for Teletex syntax fields
166 (X400_S_FREE_FORM_NAME, X400_T_TELETEX, X400_S_SUBJECT). If not
167 explicitly configured, the default set of 102, 103, 106, 107
168 will be assumed. The string below adds Cyrillic (8859-5) into the list. */
169 X400msSetStrDefault(sp, X400_S_TELETEX_CHARSETS, "102 103 106 107 144", -1);
170
171 /* Configure the character sets to be used for Graphic string syntax fields
172 (X400_S_FTBP_APPLICATION_REFERENCE_STR, X400_S_FTBP_CONTENT_DESCRIPTION,
173 X400_S_FTBP_FILENAME). If not explicitly configured, a default of
174 character set 6 (US-ASCII) will be assumed.
175 The string below adds Cyrillic (8859-5) into the list. */
177
178 if (x400_default_recipient != NULL) {
179 recip = x400_default_recipient;
180 }
181 else {
182 recip = default_recip;
183 }
184
185 printf("Message recipient [%s]: ", recip);
186 ic_fgets(tmp, sizeof tmp, stdin);
187
188 if ((strlen(tmp) > 0) && (tmp[strlen(tmp) - 1] == '\n')) {
189 tmp[strlen(tmp) - 1] = '\0';
190 }
191 if (strlen(tmp) != 0) {
192 recip = strdup(tmp);
193 }
194
195 printf("Subject [%s]: ", subject);
196 ic_fgets(tmp, sizeof tmp, stdin);
197
198 if ((strlen(tmp) > 0) && (tmp[strlen(tmp) - 1] == '\n')) {
199 tmp[strlen(tmp) - 1] = '\0';
200 }
201 if (strlen(tmp) != 0) {
202 subject = strdup(tmp);
203 }
204
205 status = X400msMsgNew(sp, X400_MSG_MESSAGE, &mp);
206 if (status != X400_E_NOERROR) {
207 fprintf(stderr, "x400msMsgNew returned error: %s\n", X400msError(status));
208 exit(status);
209 }
210
211 status = X400msRecipNew(mp, X400_RECIP_STANDARD, &rp);
212 if (status != X400_E_NOERROR) {
213 fprintf(stderr, "x400msRecipNew returned error: %s\n", X400msError(status));
214 exit(status);
215 }
216
217 status = X400msRecipAddStrParam(rp, X400_S_OR_ADDRESS, recip, -1);
218 if (status != X400_E_NOERROR) {
219 fprintf(stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError(status));
220 exit(status);
221 }
222
223 status = X400msRecipAddStrParam(rp, X400_S_DIRECTORY_NAME, "CN=recipient;c=gb", -1);
224 if (status != X400_E_NOERROR) {
225 fprintf(stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError(status));
226 exit(status);
227 }
228
229 status = X400msMsgAddStrParam(mp, X400_S_OR_ADDRESS, orn, -1);
230 if (status != X400_E_NOERROR) {
231 fprintf(stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError(status));
232 exit(status);
233 }
234
235 status = X400msMsgAddStrParam(mp, X400_S_DIRECTORY_NAME, "CN=originator;c=gb", -1);
236 if (status != X400_E_NOERROR) {
237 fprintf(stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError(status));
238 exit(status);
239 }
240
241 /* Ask for delivery reports */
242 printf("delivery report request %d ( 1 - No, 2 - Yes)\n", x400_dr_req);
243 status = X400msRecipAddIntParam(rp, X400_N_REPORT_REQUEST, x400_dr_req);
244 if (status != X400_E_NOERROR) {
245 fprintf(stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError(status));
246 exit(status);
247 }
248
249 /* Ask for read receipts */
250 printf("read notification request %d ( 1 - RN, 2 - NRN, 4 - return of IPM with NRN )\n", x400_rn_req);
251 status = X400msRecipAddIntParam(rp, X400_N_NOTIFICATION_REQUEST, x400_rn_req);
252 if (status != X400_E_NOERROR) {
253 fprintf(stderr, "x400msRecipAddIntParam returned error: %s\n", X400msError(status));
254 exit(status);
255 }
256
257 if (1) {
258 char *contid = "ContID00001";
259
260 /* Content identifier so we can correlate with submission result */
261 status = X400msMsgAddStrParam(mp, X400_S_CONTENT_IDENTIFIER, contid, -1);
262 if (status != X400_E_NOERROR) {
263 fprintf(stderr, "X400msMsgAddIntParam %d returned error: %s\n", X400_S_CONTENT_IDENTIFIER, X400msError(status));
264 exit(status);
265 }
266 }
267
268 /* content return request on report - 0 = no */
270 if (status != X400_E_NOERROR) {
271 fprintf(stderr, "X400msMsgAddIntParam %d returned error: %s\n", X400_N_CONTENT_RETURN_REQUEST, X400msError(status));
272 exit(status);
273 }
274
275 /* Priority: 0 - normal, 1 - non-urgent, 2 - urgent */
276 printf("message priority is %d ( 0 - normal, 1 - non-urgent, 2 - urgent)\n", x400_default_priority);
277 status = X400msMsgAddIntParam(mp, X400_N_PRIORITY, x400_default_priority);
278 if (status != X400_E_NOERROR) {
279 return (status);
280 }
281
282 /* Priority: 0 - normal, 1 - non-urgent, 2 - urgent */
283 printf("military message priority is %d ( 0 - low, 1 - high)\n", x400_default_priority);
285 if (status != X400_E_NOERROR) {
286 return (status);
287 }
288
289 /* subject */
290 {
291 time_t t;
292 time(&t);
293 char tmp_buffer[255];
294 // NB strip newline from ctime result
295 snprintf(tmp_buffer, 244, "%s '%s' '%.19s'", subject, get_x400_pty_str_from_4406(x400_default_priority), ctime(&t));
296 printf("Subject is '%s'\n", tmp_buffer);
297 status = X400msMsgAddStrParam(mp, X400_S_SUBJECT, tmp_buffer, -1);
298 if (status != X400_E_NOERROR) {
299 fprintf(stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError(status));
300 exit(status);
301 }
302 }
303
304 status = add_sec_label(mp);
305 if (status != X400_E_NOERROR) {
306 fprintf(stderr, "Failed to add Security Label: %s\n", X400msError(status));
307 return (status);
308 }
309 else {
310 fprintf(stderr, "added Security Label\n");
311 }
312
313 /* content type */
314 status = X400msMsgAddStrParam(mp, X400_S_EXTERNAL_CONTENT_TYPE, "1.3.26.0.4406.0.4.1", -1);
315 if (status != X400_E_NOERROR) {
316 fprintf(stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError(status));
317 exit(status);
318 }
319 /* 8859-1 attachment */
320 status = X400msMsgAddStrParam(mp, X400_T_ISO8859_1, text, -1);
321 if (status != X400_E_NOERROR) {
322 fprintf(stderr, "x400ms returned error: %s\n", X400msError(status));
323 exit(status);
324 }
325
326 /* now an IA5 body part using the bodypart func */
327 status = X400msMsgAddAttachment(mp, X400_T_IA5TEXT, text, strlen(text));
328 if (status != X400_E_NOERROR) {
329 printf("failed to add X400_T_IA5TEXT BP\n");
330 return (status);
331 }
332
333 /* or a Binary body part using the bodypart func */
334 if (filename_to_send != NULL) {
335 status = add_binary_attachment(mp, filename_to_send);
336 if (status != X400_E_NOERROR) {
337 printf("failed to add X400_T_BINARY BP\n");
338 return (status);
339 }
340 status = add_fwd_bp(mp, orn, def_dn);
341 if (status != X400_E_NOERROR) {
342 printf("failed to add forwarded BP\n");
343 return (status);
344 }
345 }
346 else {
347 printf("no binary file set - not sending X400_T_BINARY\n");
348 printf("no binary file set - not sending forwarded BP\n");
349 }
350
351 /* File Transfer Body Part using the bodypart func */
352 status = add_ftbp(mp);
353 if (status != X400_E_NOERROR) {
354 printf("failed to add X400_T_BINARY BP\n");
355 return (status);
356 }
357
358#ifdef USE_SEC_LABEL
359 {
360#define XML_BUFSIZE 1024
361#define STRING_BUFSIZE 1024
362
363 const char *xml_filename = "seclabel.xml";
364 char xml_content[XML_BUFSIZE];
365 char str_content[STRING_BUFSIZE];
366 int str_len = STRING_BUFSIZE;
367 FILE *fd = NULL;
368
369 /* Read in the security label XML file */
370 fd = fopen(xml_filename, "r");
371 if (fd == NULL) {
372 fprintf(stderr, "Failed to open %s : %s\n", xml_filename, strerror(errno));
373 }
374
375 fread(&xml_content, XML_BUFSIZE, 1, fd);
376
377 fclose(fd);
378
379 status = SecLabelInit("Example program");
380 if (status != SECLABEL_E_NOERROR) {
381 fprintf(stderr, "SecLabelInit returned error %d\n", status);
382 exit(1);
383 }
384
385 /* Use SecLabelParse to turn the XML into an octet string */
386 status = SecLabelParse(xml_content, str_content, STRING_BUFSIZE, &str_len);
387
388 if (status != SECLABEL_E_NOERROR) {
389 fprintf(stderr, "SecLabelParse returned error %d\n", status);
390 exit(1);
391 }
392
393 /* Add the octet string to the message pointer */
394 status = X400msMsgAddStrParam(mp, X400_S_SECURITY_LABEL, str_content, str_len);
395 if (status != X400_E_NOERROR) {
396 fprintf(stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError(status));
397 exit(status);
398 }
399 }
400#endif
401
402 status = X400msMsgSend(mp);
403 if (status != X400_E_NOERROR) {
404 fprintf(stderr, "x400msMsgSend returned error: %s\n", X400msError(status));
405
406 if (status == X400_E_RECIPIENT_ERROR) {
407 int n = 1;
408 struct X400Recipient *irp;
409 int ss = X400_E_NOERROR;
410
411 while (ss == X400_E_NOERROR) {
412 ss = X400msRecipGet(mp, X400_RECIP_INVALID, n, &irp);
413 if (ss == X400_E_NOERROR) {
414 char buf[1024];
415 size_t retlen;
416 int s;
417
418 fprintf(stderr, "A recipient with ");
419
420 s = X400msRecipGetStrParam(irp, X400_S_OR_ADDRESS, buf, 1024, &retlen);
421 if (s == X400_E_NOERROR) {
422 buf[retlen] = '\0';
423 fprintf(stderr, "ORAddress %s ", buf);
424 }
425
426 s = X400msRecipGetStrParam(irp, X400_S_DIRECTORY_NAME, buf, 1024, &retlen);
427 if (s == X400_E_NOERROR) {
428 buf[retlen] = '\0';
429 fprintf(stderr, " and DN %s", buf);
430 }
431 fprintf(stderr, " was rejected\n");
432 n++;
433 }
434 }
435 }
436 }
437 else {
438 char buf[1024];
439 size_t retlen;
440 char *databuf = buf;
441
442 printf("Message submitted successfully\n");
443
444 status = X400msMsgGetStrParam(mp, X400_S_MESSAGE_IDENTIFIER, buf, 1024, &retlen);
445 if (status != X400_E_NOERROR) {
446 fprintf(stderr, "No MessageId present from submission result: error %d\n", status);
447 }
448 else {
449 buf[retlen] = '\0';
450 printf("MessageId from Submission Result = %s\n", buf);
451 }
452
453 status = X400msMsgGetStrParam(mp, X400_S_MESSAGE_SUBMISSION_TIME, buf, 1024, &retlen);
454 if (status != X400_E_NOERROR) {
455 fprintf(stderr, "No MessageSubmissionTime present from submission result: error %d\n", status);
456 }
457 else {
458 buf[retlen] = '\0';
459 printf("MessageSubmissionTime from Submission Result = %s\n", buf);
460 }
461
462 status = X400msMsgGetStrParam(mp, X400_S_CONTENT_IDENTIFIER, buf, 1024, &retlen);
463 if (status != X400_E_NOERROR) {
464 fprintf(stderr, "No ContentIdentifier present from submission result: error %d\n", status);
465 }
466 else {
467 buf[retlen] = '\0';
468 printf("ContentIdentifier from Submission Result = %s\n", buf);
469 }
470
471 /* Get binary representation and store to file */
472
473 /* First pass to find out how big it needs to be */
474 status = X400msMsgGetRaw(sp, mp, databuf, 0, &retlen);
475 if (status != X400_E_NOSPACE) {
476 fprintf(stderr, "Failed to get raw message length: error %d\n", status);
477 }
478 else {
479 struct X400msMessage *newmsg;
480 int newtype;
481
482 databuf = (char *)malloc(retlen);
483 printf("Data buffer length required = %d\n", (int)retlen);
484 status = X400msMsgGetRaw(sp, mp, databuf, retlen, &retlen);
485 if (status != X400_E_NOERROR) {
486 fprintf(stderr, "Failed to get raw message: error %d\n", status);
487 }
488 else {
489 /* Dump to file */
490 FILE *fd = fopen("message.dump", "w");
491 if (fd == NULL) {
492 fprintf(stderr, "Failed to open file message.dump\n");
493 }
494 else {
495 if (fwrite(databuf, 1, retlen, fd) < retlen) {
496 fprintf(stderr, "Failed to write message to file message.dump\n");
497 }
498 else {
499 fprintf(stdout, "Dumped message to file message.dump\n");
500 }
501 fclose(fd);
502 }
503 }
504
505 /* And try to reconstruct message from bytes */
506 status = X400msMsgFromRaw(sp, databuf, retlen, &newmsg, &newtype);
507 if (status != X400_E_NOERROR) {
508 fprintf(stderr, "Failed to create message from bytes: error %d\n", status);
509 }
510
511 free(databuf);
512 }
513 }
514
515 status = X400msMsgDelete(mp, 0);
516 if (status != X400_E_NOERROR) {
517 fprintf(stderr, "x400msMsgDelete returned error: %s\n", X400msError(status));
518 exit(status);
519 }
520
521 mp = NULL;
522 rp = NULL;
523
524 status = X400msClose(sp);
525 exit(status);
526 /* NOTREACHED */
527}
528
529static int add_binary_attachment(struct X400msMessage *mp, char *filename) {
530 int fd;
531 int file_size;
532 struct stat buf;
533 int fs = 0;
534 int status;
535
536 printf("sending file %s\n", filename);
537 if ((fd = open(filename_to_send, O_RDONLY)) == -1) {
538 printf("Failed to open content file %s: ", filename);
539 return X400_E_BADPARAM;
540 }
541
542 if (fstat(fd, &buf) != 0) {
543 close(fd);
544 printf("Can't fstat file %s %d", filename, errno);
545 return X400_E_BADPARAM;
546 }
547
548 file_size = buf.st_size;
549 printf("Content file size = %d\n", file_size);
550
551 binary_data = (char *)malloc(file_size);
552 if (binary_data == NULL) {
553 return X400_E_NOMEMORY;
554 }
555
556 if ((fs = read(fd, binary_data, file_size)) == -1) {
557 printf("Cannot read from binary file %d\n", errno);
558 return (X400_E_SYSERROR);
559 }
560 close(fd);
561
562 status = X400msMsgAddAttachment(mp, X400_T_BINARY, binary_data, fs);
563 if (status != X400_E_NOERROR) {
564 printf("failed to add X400_T_BINARY BP\n");
565 return (status);
566 }
567 return (status);
568}
569
570static int add_fwd_bp(struct X400msMessage *mp, char *orig_orn, char *orig_dn) {
571 struct X400Message *x400_mp;
572 struct X400Recipient *rp;
573 int status;
574 int num_atts = 0;
575
576 printf("sending fwd bp \n");
577
578 status = X400MsgNew(X400_MSG_MESSAGE, &x400_mp);
579 if (status != X400_E_NOERROR) {
580 fprintf(stderr, "x400MsgNew returned error: %s\n", X400msError(status));
581 exit(status);
582 }
583
584 status = X400MsgAddStrParam(x400_mp, X400_S_MESSAGE_DELIVERY_TIME, "090909090909Z", (size_t)-1);
585 if (status != X400_E_NOERROR) {
586 fprintf(stderr, "x400MsgAddStrParam returned error: %s\n", X400msError(status));
587 exit(status);
588 }
589
590 status = X400MsgAddStrParam(x400_mp, X400_S_MESSAGE_SUBMISSION_TIME, "090909090909Z", (size_t)-1);
591 if (status != X400_E_NOERROR) {
592 fprintf(stderr, "x400MsgAddStrParam returned error: %s\n", X400msError(status));
593 exit(status);
594 }
595
596 /* envelope originator OR address */
597 status = X400MsgAddStrParam(x400_mp, X400_S_OR_ADDRESS, orig_orn, (size_t)-1);
598 if (status != X400_E_NOERROR) {
599 fprintf(stderr, "x400MsgAddStrParam returned error: %s\n", X400msError(status));
600 exit(status);
601 }
602 status = X400MsgAddStrParam(x400_mp, X400_S_DIRECTORY_NAME, orig_dn, (size_t)-1);
603 if (status != X400_E_NOERROR) {
604 fprintf(stderr, "x400MsgAddStrParam returned error: %s\n", X400msError(status));
605 exit(status);
606 }
607
608 /* add originator into headers */
609 status = X400RecipNew(X400_ORIGINATOR, &rp);
610 if (status != X400_E_NOERROR) {
611 fprintf(stderr, "x400RecipNew returned error: %s\n", X400msError(status));
612 exit(status);
613 }
614
615 /* put in OR Address part of OR Name */
616 status = X400RecipAddStrParam(rp, X400_S_OR_ADDRESS, recip, -1);
617 if (status != X400_E_NOERROR) {
618 fprintf(stderr, "x400RecipAddStrParam returned error: %s\n", X400msError(status));
619 exit(status);
620 }
621
622 /* put in DN part of OR Name */
623 status = X400RecipAddStrParam(rp, X400_S_DIRECTORY_NAME, orig_dn, -1);
624 if (status != X400_E_NOERROR) {
625 fprintf(stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError(status));
626 exit(status);
627 }
628
629 /* put originator into message */
630 status = X400MsgAddRecip(x400_mp, X400_ORIGINATOR, rp);
631 if (status != X400_E_NOERROR) {
632 fprintf(stderr, "X400MsgAddRecip returned error: %s\n", X400msError(status));
633 exit(status);
634 }
635 printf("Put %s in as originator\n", orig_orn);
636
637 /* add a recipient */
638 status = X400RecipNew(X400_RECIP_STANDARD, &rp);
639 if (status != X400_E_NOERROR) {
640 fprintf(stderr, "x400RecipNew returned error: %s\n", X400msError(status));
641 exit(status);
642 }
643
644 status = X400RecipAddStrParam(rp, X400_S_OR_ADDRESS, recip, -1);
645 if (status != X400_E_NOERROR) {
646 fprintf(stderr, "x400RecipAddStrParam returned error: %s\n", X400msError(status));
647 exit(status);
648 }
649
650 status = X400RecipAddStrParam(rp, X400_S_DIRECTORY_NAME, "CN=recipient;c=gb", -1);
651 if (status != X400_E_NOERROR) {
652 fprintf(stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError(status));
653 exit(status);
654 }
655
656 status = X400MsgAddRecip(x400_mp, X400_RECIP_STANDARD, rp);
657 if (status != X400_E_NOERROR) {
658 fprintf(stderr, "X400MsgAddRecip returned error: %s\n", X400msError(status));
659 exit(status);
660 }
661 printf("Put %s in as reipient\n", recip);
662
663 /* Add 2nd recipient */
664 status = X400RecipNew(X400_RECIP_STANDARD, &rp);
665 if (status != X400_E_NOERROR) {
666 fprintf(stderr, "x400RecipNew returned error: %s\n", X400msError(status));
667 exit(status);
668 }
669
670 status = X400RecipAddStrParam(rp, X400_S_OR_ADDRESS, recip, -1);
671 if (status != X400_E_NOERROR) {
672 fprintf(stderr, "x400RecipAddStrParam returned error: %s\n", X400msError(status));
673 exit(status);
674 }
675
676 status = X400RecipAddStrParam(rp, X400_S_DIRECTORY_NAME, "CN=second recipient;c=gb", -1);
677 if (status != X400_E_NOERROR) {
678 fprintf(stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError(status));
679 exit(status);
680 }
681
682 /* put recipient into message */
683 status = X400MsgAddRecip(x400_mp, X400_RECIP_STANDARD, rp);
684 if (status != X400_E_NOERROR) {
685 fprintf(stderr, "X400MsgAddRecip returned error: %s\n", X400msError(status));
686 exit(status);
687 }
688 printf("Put %s in as reipient\n", recip);
689
690 /* envelope */
691
692 /* Priority: 0 - normal, 1 - non-urgent, 2 - urgent */
693 printf("message priority is %d ( 0 - normal, 1 - non-urgent, 2 - urgent)\n", x400_default_priority);
694 status = X400MsgAddIntParam(x400_mp, X400_N_PRIORITY, x400_default_priority);
695 if (status != X400_E_NOERROR) {
696 return (status);
697 }
698
699 /* Priority: 0 - normal, 1 - non-urgent, 2 - urgent */
700 printf("military message priority is %d ( 0 - low, 1 - high)\n", x400_default_priority);
702 if (status != X400_E_NOERROR) {
703 return (status);
704 }
705
706 /* content */
707 /* subject */
708 status = X400MsgAddStrParam(x400_mp, X400_S_SUBJECT, fwd_subject, (size_t)-1);
709 if (status != X400_E_NOERROR) {
710 fprintf(stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError(status));
711 exit(status);
712 }
713
714 /* now an IA5 body part using the bodypart func */
715 status = X400MsgAddAttachment(x400_mp, X400_T_IA5TEXT, text, strlen(text));
716 if (status != X400_E_NOERROR) {
717 printf("failed to add X400_T_IA5TEXT BP\n");
718 return (status);
719 }
720 num_atts++;
721
722 /* 8859-1 attachment */
723 status = X400MsgAddStrParam(x400_mp, X400_T_ISO8859_1, text, (size_t)-1);
724 if (status != X400_E_NOERROR) {
725 fprintf(stderr, "x400ms returned error: %s\n", X400msError(status));
726 exit(status);
727 }
728 num_atts++;
729
730 status = X400MsgAddIntParam(x400_mp, X400_N_NUM_ATTACHMENTS, num_atts);
731 if (status != X400_E_NOERROR) {
732 return (status);
733 }
734
735 status = X400msMsgAddMessageBody(mp, x400_mp);
736 if (status != X400_E_NOERROR) {
737 fprintf(stderr, "X400msMsgAddMessageBody returned error: %s\n", X400msError(status));
738 return (status);
739 }
740
741 return X400_E_NOERROR;
742}
743
744static int add_ftbp(struct X400msMessage *mp) {
745 FILE *fp = NULL;
746 int fs = 0;
747 char *binary_data;
748 int status;
749 struct X400Bodypart *bp;
750
751 /* Add FTBP using the bodypart func */
752 if (filename_to_send == NULL) {
753 printf("no file set - not sending X400_T_FTBP\n");
754 return X400_E_NOERROR;
755 }
756 fp = fopen(filename_to_send, "rb");
757 if (fp == (FILE *)NULL) {
758 printf("Cannot open binary file\n");
759 return (X400_E_SYSERROR);
760 }
761 binary_data = (char *)malloc(bin_bp_size);
762 if (binary_data == NULL) {
763 return X400_E_NOMEMORY;
764 }
765 if ((fs = fread(binary_data, sizeof(char), bin_bp_size / sizeof(char), fp)) == -1) {
766 printf("Cannot read from binary file\n");
767 free(binary_data);
768 fclose(fp);
769 return (X400_E_SYSERROR);
770 }
771 fclose(fp);
772 if (fs < bin_bp_size) {
773 printf("Cannot read %d bytes from binary file (got %d)\n", bin_bp_size, fs);
774 free(binary_data);
775 return (X400_E_SYSERROR);
776 }
777
779 X400BodypartAddStrParam(bp, X400_S_BODY_DATA, binary_data, fs);
781 /* NB this value should have the filename, but not the full path */
782 /* And on Windows backslashes must be escaped with a second backslash */
783 X400BodypartAddStrParam(bp, X400_S_FTBP_FILENAME, filename_to_send, -1);
784 X400BodypartAddStrParam(bp, X400_S_FTBP_CREATION_DATE, "20230801060101.0Z", -1);
785 X400BodypartAddStrParam(bp, X400_S_FTBP_MODIFICATION_DATE, "20230801060202.0Z", -1);
787 status = X400msMsgAddBodypart(mp, bp);
788 free(binary_data);
789
790 if (status != X400_E_NOERROR) {
791 printf("failed to add X400_T_FTBP BP\n");
792 return (status);
793 }
794 printf("Sent %d bytes as X400_T_FTBP BP\n", fs);
795 return X400_E_NOERROR;
796}
797
798static void usage(void) {
799 printf("usage: %s\n", optstr);
800 printf("\t where:\n");
801 printf("\t -u : Don't prompt to override defaults \n");
802 printf("\t -3 : Use P3 connection \n");
803 printf("\t -7 : Use P7 connection \n");
804 printf("\t -1 : Use Marben-compatibility mode for P7 connection \n");
805 printf("\t -m : OR Address in P7 bind arg \n");
806 printf("\t -d : DN in P7 bind arg \n");
807 printf("\t -p : Presentation Address of P7 Store \n");
808 printf("\t -w : P7 password of P7 user \n");
809 printf("\t -M : OR Address in P3 bind arg \n");
810 printf("\t -D : DN in P3 bind arg \n");
811 printf("\t -P : Presentation Address of P3 server\n");
812 printf("\t -W : P3 password of P3 user \n");
813 printf("\t -o : Originator \n");
814 printf("\t -O : Originator Return Address \n");
815 printf("\t -r : Recipient\n");
816 printf("\t -l : Logline\n");
817 printf("\t -R : Report setting: 0=none, 1=-ve, 2=+ve\n");
818 printf("\t -y : Military Priority \n");
819 printf("\t\t 0 - deferred, 1 - routine, 2 - priority \n");
820 printf("\t\t 3 - immediate, 4 - flash, 5 - override \n");
821 printf("\t -C : Content Type (2/22/772/OID) \n");
822 printf("\t -i : Implicit conversion prohibited = TRUE \n");
823 printf("\t -a : Alternate Recipient Prohibited = TRUE \n");
824 printf("\t -q : Content Return Request = TRUE \n");
825 printf("\t -s : Disclosure of Recipient = FALSE \n");
826 printf("\t -A : Recipient Reassignment Prohibited = FALSE \n");
827 printf("\t -v : Conversion with Loss Prohibited = FALSE \n");
828 printf("\t -f : Filename to transfer as binary bp\n");
829 printf("\t -k : Request Delivery Report\n");
830 printf("\t -K : Request Read Notification ( 1 - RN, 2 - NRN, 4 - return of IPM with NRN )\n");
831 printf("\t -B : Set alternative subject line \n");
832 return;
833}
int X400RecipNew(int type, struct X400Recipient **rpp)
Create a new recipient object.
int X400MsgAddRecip(struct X400Message *mp, int reciptype, struct X400Recipient *recip)
Add a recipient object to the message.
int X400RecipAddStrParam(struct X400Recipient *rp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the recipient.
int X400MsgAddIntParam(struct X400Message *mp, int paramtype, int value)
Add integer-valued parameter to the message.
int X400BodypartAddStrParam(struct X400Bodypart *bp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the body part.
int X400BodypartAddIntParam(struct X400Bodypart *bp, int paramtype, int value)
Add integer-valued parameter to the body part.
int X400MsgNew(int type, struct X400Message **mpp)
Creates new message.
int X400MsgAddAttachment(struct X400Message *mp, int type, const char *string, size_t length)
Add an attachment to the message.
int X400MsgAddStrParam(struct X400Message *mp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the message.
int X400BodypartNew(int type, struct X400Bodypart **bpp)
Create a new body part object.
int X400msMsgAddStrParam(struct X400msMessage *mp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the message.
int X400msMsgFromRaw(struct X400msSession *sp, char *buffer, size_t buflen, struct X400msMessage **mpp, int *typep)
Reconstruct a message from a binary representation.
int X400msMsgAddBodypart(struct X400msMessage *mp, struct X400Bodypart *bp)
int X400msRecipGet(struct X400msMessage *mp, int type, int number, struct X400Recipient **rpp)
Get recipient object from message.
int X400msRecipAddIntParam(struct X400Recipient *rp, int paramtype, int value)
Add integer-valued parameter to the message.
int X400msMsgAddIntParam(struct X400msMessage *mp, int paramtype, int value)
Add integer-valued parameter to the message.
int X400msMsgGetStrParam(struct X400msMessage *mp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the message object.
int X400msMsgGetRaw(struct X400msSession *sp, struct X400msMessage *mp, char *buffer, size_t buflen, size_t *buflenp)
Get a binary representation of a message which can be subsequently be used to reconstruct the message...
int X400msRecipGetStrParam(struct X400Recipient *rp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the recipient object.
int X400msRecipNew(struct X400msMessage *mp, int type, struct X400Recipient **rpp)
Add new recipient to a message.
const char * X400msError(int error)
Obtain a string describing the meaning of the given error code.
int X400msRecipAddStrParam(struct X400Recipient *rp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the message.
int X400msSetIntDefault(struct X400msSession *sp, int paramtype, int value)
Set a default integer parameter value in a session.
int X400msMsgSend(struct X400msMessage *mp)
Send message object.
int X400msMsgAddMessageBody(struct X400msMessage *mp, struct X400Message *mbp)
int X400msMsgDelete(struct X400msMessage *mp, int retain)
Delete message object.
int X400msMsgAddAttachment(struct X400msMessage *mp, int type, const char *string, size_t length)
Add attachment to the message.
void X400msSetConfigRequest(int val)
Disable and enable configuration requests in MS Bind operations.
int X400msMsgNew(struct X400msSession *sp, int type, struct X400msMessage **mpp)
Creates new message.
int X400msClose(struct X400msSession *sp)
Close a X400 Session.
int X400msSetStrDefault(struct X400msSession *sp, int paramtype, const char *value, size_t length)
Set a default string parameter value in a session.
int X400msOpen(int type, const char *oraddr, const char *dirname, const char *credentials, const char *pa, int *messages, struct X400msSession **spp)
Open a session to a Message Store (P7) or MTA (P3) in synchronous mode.
#define X400_S_DIRECTORY_NAME
Definition x400_att.h:397
#define X400_S_OR_ADDRESS
Definition x400_att.h:349
#define X400_N_FTBP_OBJECT_SIZE
Definition x400_att.h:1239
#define X400_S_FTBP_FILENAME
Definition x400_att.h:1227
#define X400_S_BODY_DATA
Definition x400_att.h:1194
#define X400_S_FTBP_MODIFICATION_DATE
Definition x400_att.h:1233
#define X400_S_FTBP_CREATION_DATE
Definition x400_att.h:1230
#define X400_S_FTBP_CONTENT_DESCRIPTION
Definition x400_att.h:1224
#define X400_S_SUBJECT
Definition x400_att.h:749
#define X400_T_BINARY
Definition x400_att.h:851
#define X400_T_IA5TEXT
Definition x400_att.h:825
#define X400_N_NUM_ATTACHMENTS
Definition x400_att.h:822
#define X400_T_ISO8859_1
Definition x400_att.h:835
#define X400_T_FTBP
Definition x400_att.h:860
#define X400_S_GRAPHIC_CHARSETS
Definition x400_att.h:1168
#define X400_S_TELETEX_CHARSETS
Definition x400_att.h:1175
#define X400_S_LOG_CONFIGURATION_FILE
Definition x400_att.h:1116
#define X400_N_PRIORITY
Definition x400_att.h:433
#define X400_S_MESSAGE_DELIVERY_TIME
Definition x400_att.h:451
#define X400_N_MMTS_PRIORITY_QUALIFIER
Definition x400_att.h:482
#define X400_S_CONTENT_IDENTIFIER
Definition x400_att.h:425
#define X400_N_CONTENT_RETURN_REQUEST
Definition x400_att.h:445
#define X400_S_MESSAGE_SUBMISSION_TIME
Definition x400_att.h:448
#define X400_S_EXTERNAL_CONTENT_TYPE
Definition x400_att.h:456
#define X400_S_MESSAGE_IDENTIFIER
Definition x400_att.h:416
#define X400_S_SECURITY_LABEL
Definition x400_att.h:1370
#define X400_E_BADPARAM
Definition x400_att.h:55
#define X400_E_SYSERROR
Definition x400_att.h:49
#define X400_E_RECIPIENT_ERROR
Definition x400_att.h:157
#define X400_E_NOMEMORY
Definition x400_att.h:52
#define X400_E_NOERROR
Definition x400_att.h:46
#define X400_E_NOSPACE
Definition x400_att.h:112
#define X400_N_ERROR_DUPLICATE_ATTRIBUTE
Definition x400_att.h:1306
#define X400_N_STRICT_P7_1988
Definition x400_att.h:1293
#define X400_N_USE_EXTENDED_SUBJECT
Definition x400_att.h:1299
#define X400_MSG_MESSAGE
Definition x400_att.h:29
#define X400_N_REPORT_REQUEST
Definition x400_att.h:680
#define X400_N_NOTIFICATION_REQUEST
Definition x400_att.h:702
#define X400_RECIP_STANDARD
Definition x400_att.h:341
#define X400_ORIGINATOR
Definition x400_att.h:305
#define X400_RECIP_INVALID
Definition x400_att.h:338
X400 MA/MS (P3/P7) Interface.

All rights reserved © 2002 - 2024 Isode Ltd.