2 Stand-alone MAPI application
6 Copyright (C) Julien Kerihuel 2007-2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "libmapi/libmapi.h"
23 #include "libmapi/libmapi_private.h"
24 #include "libmapi/mapi_nameid.h"
25 #include "libocpf/ocpf.h"
29 #include "openchangeclient.h"
30 #include "openchange-tools.h"
40 * init sendmail struct
43 static void init_oclient(struct oclient *oclient)
45 oclient->mapi_ctx = NULL;
47 /* update and delete parameter */
48 oclient->update = NULL;
49 oclient->delete = NULL;
52 oclient->props = NULL;
54 /* email related parameter */
55 oclient->subject = NULL;
56 oclient->pr_body = NULL;
57 oclient->pr_html_inline = NULL;
58 oclient->attach = NULL;
59 oclient->attach_num = 0;
60 oclient->store_folder = NULL;
62 /* appointment related parameters */
63 oclient->location = NULL;
64 oclient->dtstart = NULL;
65 oclient->dtend = NULL;
66 oclient->busystatus = -1;
68 oclient->private = false;
69 oclient->freebusy = NULL;
70 oclient->force = false;
71 oclient->summary = false;
73 /* contact related parameters */
74 oclient->email = NULL;
75 oclient->full_name = NULL;
76 oclient->card_name = NULL;
78 /* task related parameters */
79 oclient->importance = -1;
80 oclient->taskstatus = -1;
82 /* note related parameters */
87 /* pf related parameters */
90 /* folder related parameters */
91 oclient->folder = NULL;
92 oclient->folder_name = NULL;
93 oclient->folder_comment = NULL;
95 /* ocpf related parameters */
96 oclient->ocpf_files = NULL;
97 oclient->ocpf_dump = NULL;
100 static enum MAPISTATUS openchangeclient_getdir(TALLOC_CTX *mem_ctx,
101 mapi_object_t *obj_container,
102 mapi_object_t *obj_child,
105 enum MAPISTATUS retval;
106 struct SPropTagArray *SPropTagArray = NULL;
107 struct SRowSet SRowSet;
108 mapi_object_t obj_htable;
109 mapi_object_t obj_folder;
110 char **folder = NULL;
117 /* Step 1. Extract the folder list from full path */
118 folder = str_list_make(mem_ctx, path, "/");
119 mapi_object_copy(&obj_folder, obj_container);
121 for (i = 0; folder[i]; i++) {
124 mapi_object_init(&obj_htable);
125 retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
126 MAPI_RETVAL_IF(retval, GetLastError(), folder);
128 SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
129 PR_DISPLAY_NAME_UNICODE,
131 retval = SetColumns(&obj_htable, SPropTagArray);
132 MAPIFreeBuffer(SPropTagArray);
133 MAPI_RETVAL_IF(retval, retval, folder);
135 while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) && SRowSet.cRows) {
136 for (index = 0; (index < SRowSet.cRows) && (found == false); index++) {
137 fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[index], PR_FID);
138 name = (const char *)find_SPropValue_data(&SRowSet.aRow[index], PR_DISPLAY_NAME_UNICODE);
139 if (name && fid && !strcmp(name, folder[i])) {
140 retval = OpenFolder(&obj_folder, *fid, obj_child);
141 MAPI_RETVAL_IF(retval, retval, folder);
144 mapi_object_copy(&obj_folder, obj_child);
149 mapi_object_release(&obj_htable);
153 MAPI_RETVAL_IF(found == false, MAPI_E_NOT_FOUND, NULL);
155 return MAPI_E_SUCCESS;
159 static enum MAPISTATUS openchangeclient_getpfdir(TALLOC_CTX *mem_ctx,
160 mapi_object_t *obj_store,
161 mapi_object_t *obj_child,
164 enum MAPISTATUS retval;
165 mapi_object_t obj_pf;
168 retval = GetDefaultPublicFolder(obj_store, &id_pf, olFolderPublicIPMSubtree);
169 if (retval != MAPI_E_SUCCESS) return retval;
171 mapi_object_init(&obj_pf);
172 retval = OpenFolder(obj_store, id_pf, &obj_pf);
173 if (retval != MAPI_E_SUCCESS) return retval;
175 retval = openchangeclient_getdir(mem_ctx, &obj_pf, obj_child, name);
176 if (retval != MAPI_E_SUCCESS) return retval;
178 return MAPI_E_SUCCESS;
182 * read a file and store it in the appropriate structure element
185 static bool oclient_read_file(TALLOC_CTX *mem_ctx, const char *filename,
186 struct oclient *oclient, uint32_t mapitag)
191 if ((fd = open(filename, O_RDONLY)) == -1) {
192 printf("Error while opening %s\n", filename);
196 if (fstat(fd, &sb) != 0) {
203 oclient->pr_html.lpb = talloc_size(mem_ctx, sb.st_size);
204 oclient->pr_html.cb = read(fd, oclient->pr_html.lpb, sb.st_size);
207 case PR_ATTACH_DATA_BIN:
208 oclient->attach[oclient->attach_num].filename = talloc_strdup(mem_ctx, filename);
209 oclient->attach[oclient->attach_num].bin.lpb = talloc_size(mem_ctx, sb.st_size);
210 oclient->attach[oclient->attach_num].bin.cb = sb.st_size;
211 if ((oclient->attach[oclient->attach_num].bin.lpb = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (void *) -1) {
216 oclient->attach[oclient->attach_num].fd = fd;
217 printf("filename = %s (size = %u / %u)\n", filename, oclient->attach[oclient->attach_num].bin.cb, (uint32_t)sb.st_size);
221 printf("unsupported MAPITAG: %s\n", get_proptag_name(mapitag));
231 * Parse attachments and load their content
233 static bool oclient_parse_attachments(TALLOC_CTX *mem_ctx, const char *filename,
234 struct oclient *oclient)
240 if ((tmp = strtok((char *)filename, ";")) == NULL) {
241 printf("Invalid string format [;]\n");
245 filenames = talloc_array(mem_ctx, char *, 2);
246 filenames[0] = strdup(tmp);
248 for (j = 1; (tmp = strtok(NULL, ";")) != NULL; j++) {
249 filenames = talloc_realloc(mem_ctx, filenames, char *, j+2);
250 filenames[j] = strdup(tmp);
253 oclient->attach = talloc_array(mem_ctx, struct attach, j);
255 for (j = 0; filenames[j]; j++) {
256 oclient->attach_num = j;
257 if (oclient_read_file(mem_ctx, filenames[j], oclient, PR_ATTACH_DATA_BIN) == false) {
266 static const char *get_filename(const char *filename)
270 if (!filename) return NULL;
272 substr = rindex(filename, '/');
273 if (substr) return substr + 1;
280 * build unique ID from folder and message
282 static char *build_uniqueID(TALLOC_CTX *mem_ctx, mapi_object_t *obj_folder,
283 mapi_object_t *obj_message)
286 struct SPropTagArray *SPropTagArray;
287 struct SPropValue *lpProps;
292 /* retrieve the folder ID */
293 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_FID);
294 GetProps(obj_folder, 0, SPropTagArray, &lpProps, &count);
295 MAPIFreeBuffer(SPropTagArray);
296 if (GetLastError() != MAPI_E_SUCCESS) return NULL;
297 fid = (const uint64_t *)get_SPropValue_data(lpProps);
299 /* retrieve the message ID */
300 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_MID);
301 GetProps(obj_message, 0, SPropTagArray, &lpProps, &count);
302 MAPIFreeBuffer(SPropTagArray);
303 if (GetLastError() != MAPI_E_SUCCESS) return NULL;
304 mid = (const uint64_t *)get_SPropValue_data(lpProps);
306 if (!fid || !mid) return NULL;
308 id = talloc_asprintf(mem_ctx, "%"PRIX64"/%"PRIX64, *fid, *mid);
314 * fetch the user INBOX
317 #define MAX_READ_SIZE 0x1000
319 static bool store_attachment(mapi_object_t obj_attach, const char *filename, uint32_t size, struct oclient *oclient)
322 enum MAPISTATUS retval;
324 mapi_object_t obj_stream;
328 unsigned char buf[MAX_READ_SIZE];
330 if (!filename || !size) return false;
332 mapi_object_init(&obj_stream);
334 mem_ctx = talloc_named(NULL, 0, "store_attachment");
336 if (!(dir = opendir(oclient->store_folder))) {
337 if (mkdir(oclient->store_folder, 0700) == -1) return false;
342 path = talloc_asprintf(mem_ctx, "%s/%s", oclient->store_folder, filename);
343 if ((fd = open(path, O_CREAT|O_WRONLY, S_IWUSR|S_IRUSR)) == -1) {
348 retval = OpenStream(&obj_attach, PR_ATTACH_DATA_BIN, 0, &obj_stream);
349 if (retval != MAPI_E_SUCCESS) return false;
353 retval = ReadStream(&obj_stream, buf, MAX_READ_SIZE, &read_size);
354 if (retval != MAPI_E_SUCCESS) goto error;
355 write(fd, buf, read_size);
359 mapi_object_release(&obj_stream);
360 talloc_free(mem_ctx);
364 mapi_object_release(&obj_stream);
366 talloc_free(mem_ctx);
370 static enum MAPISTATUS openchangeclient_fetchmail(mapi_object_t *obj_store,
371 struct oclient *oclient)
373 enum MAPISTATUS retval;
376 mapi_object_t obj_tis;
377 mapi_object_t obj_inbox;
378 mapi_object_t obj_message;
379 mapi_object_t obj_table;
380 mapi_object_t obj_tb_attach;
381 mapi_object_t obj_attach;
383 struct SPropTagArray *SPropTagArray;
384 struct SRowSet rowset;
385 struct SRowSet rowset_attach;
388 const uint8_t *has_attach;
389 const uint32_t *attach_num;
390 const char *attach_filename;
391 const uint32_t *attach_size;
393 mem_ctx = talloc_named(NULL, 0, "openchangeclient_fetchmail");
395 mapi_object_init(&obj_tis);
396 mapi_object_init(&obj_inbox);
397 mapi_object_init(&obj_table);
399 if (oclient->pf == true) {
400 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_inbox, oclient->folder);
401 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
403 if (oclient->folder) {
404 retval = GetDefaultFolder(obj_store, &id_inbox, olFolderTopInformationStore);
405 MAPI_RETVAL_IF(retval, retval, mem_ctx);
407 retval = OpenFolder(obj_store, id_inbox, &obj_tis);
408 MAPI_RETVAL_IF(retval, retval, mem_ctx);
410 retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_inbox, oclient->folder);
411 MAPI_RETVAL_IF(retval, retval, mem_ctx);
413 retval = GetReceiveFolder(obj_store, &id_inbox, NULL);
414 MAPI_RETVAL_IF(retval, retval, mem_ctx);
416 retval = OpenFolder(obj_store, id_inbox, &obj_inbox);
417 MAPI_RETVAL_IF(retval, retval, mem_ctx);
421 retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
422 MAPI_RETVAL_IF(retval, retval, mem_ctx);
424 printf("MAILBOX (%u messages)\n", count);
425 if (!count) goto end;
427 SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
433 retval = SetColumns(&obj_table, SPropTagArray);
434 MAPIFreeBuffer(SPropTagArray);
435 MAPI_RETVAL_IF(retval, retval, mem_ctx);
437 while ((retval = QueryRows(&obj_table, count, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND && rowset.cRows) {
438 count -= rowset.cRows;
439 for (i = 0; i < rowset.cRows; i++) {
440 mapi_object_init(&obj_message);
441 retval = OpenMessage(obj_store,
442 rowset.aRow[i].lpProps[0].value.d,
443 rowset.aRow[i].lpProps[1].value.d,
445 if (GetLastError() == MAPI_E_SUCCESS) {
446 if (oclient->summary) {
447 mapidump_message_summary(&obj_message);
449 struct SPropValue *lpProps;
452 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_HASATTACH);
454 retval = GetProps(&obj_message, 0, SPropTagArray, &lpProps, &count);
455 MAPIFreeBuffer(SPropTagArray);
456 if (retval != MAPI_E_SUCCESS) return retval;
458 aRow.ulAdrEntryPad = 0;
459 aRow.cValues = count;
460 aRow.lpProps = lpProps;
462 retval = octool_message(mem_ctx, &obj_message);
464 has_attach = (const uint8_t *) get_SPropValue_SRow_data(&aRow, PR_HASATTACH);
466 /* If we have attachments, retrieve them */
467 if (has_attach && *has_attach) {
468 mapi_object_init(&obj_tb_attach);
469 retval = GetAttachmentTable(&obj_message, &obj_tb_attach);
470 if (retval == MAPI_E_SUCCESS) {
471 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_ATTACH_NUM);
472 retval = SetColumns(&obj_tb_attach, SPropTagArray);
473 if (retval != MAPI_E_SUCCESS) return retval;
474 MAPIFreeBuffer(SPropTagArray);
476 retval = QueryRows(&obj_tb_attach, 0xa, TBL_ADVANCE, &rowset_attach);
477 if (retval != MAPI_E_SUCCESS) return retval;
479 for (j = 0; j < rowset_attach.cRows; j++) {
480 attach_num = (const uint32_t *)find_SPropValue_data(&(rowset_attach.aRow[j]), PR_ATTACH_NUM);
481 retval = OpenAttach(&obj_message, *attach_num, &obj_attach);
482 if (retval == MAPI_E_SUCCESS) {
483 struct SPropValue *lpProps2;
486 SPropTagArray = set_SPropTagArray(mem_ctx, 0x4,
488 PR_ATTACH_LONG_FILENAME,
490 PR_ATTACH_CONTENT_ID);
492 retval = GetProps(&obj_attach, MAPI_UNICODE, SPropTagArray, &lpProps2, &count2);
493 MAPIFreeBuffer(SPropTagArray);
494 if (retval != MAPI_E_SUCCESS) return retval;
496 aRow.ulAdrEntryPad = 0;
497 aRow.cValues = count2;
498 aRow.lpProps = lpProps2;
500 attach_filename = get_filename(octool_get_propval(&aRow, PR_ATTACH_LONG_FILENAME));
501 if (!attach_filename || (attach_filename && !strcmp(attach_filename, ""))) {
502 attach_filename = get_filename(octool_get_propval(&aRow, PR_ATTACH_FILENAME));
504 attach_size = (const uint32_t *) octool_get_propval(&aRow, PR_ATTACH_SIZE);
505 printf("[%u] %s (%u Bytes)\n", j, attach_filename, attach_size ? *attach_size : 0);
507 if (oclient->store_folder) {
508 status = store_attachment(obj_attach, attach_filename, attach_size ? *attach_size : 0, oclient);
509 if (status == false) {
510 printf("A Problem was encountered while storing attachments on the filesystem\n");
511 MAPI_RETVAL_IF(status == false, MAPI_E_UNABLE_TO_COMPLETE, mem_ctx);
515 MAPIFreeBuffer(lpProps2);
520 MAPIFreeBuffer(lpProps);
524 mapi_object_release(&obj_message);
528 mapi_object_release(&obj_table);
529 mapi_object_release(&obj_inbox);
530 mapi_object_release(&obj_tis);
532 talloc_free(mem_ctx);
535 return MAPI_E_SUCCESS;
539 * send a mail to a user whom belongs to the Exchange organization
542 static char **get_cmdline_recipients(TALLOC_CTX *mem_ctx, const char *recipients)
553 if ((tmp = strtok((char *)recipients, ",")) == NULL) {
554 DEBUG(2, ("Invalid recipient string format\n"));
558 usernames = talloc_array(mem_ctx, char *, 2);
559 usernames[0] = strdup(tmp);
561 for (j = 1; (tmp = strtok(NULL, ",")) != NULL; j++) {
562 usernames = talloc_realloc(mem_ctx, usernames, char *, j+2);
563 usernames[j] = strdup(tmp);
571 * We set external recipients at the end of aRow
573 static bool set_external_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, const char *username, enum ulRecipClass RecipClass)
576 struct SPropValue SPropValue;
578 SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 1);
579 last = SRowSet->cRows;
580 SRowSet->aRow[last].cValues = 0;
581 SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
584 SPropValue.ulPropTag = PR_OBJECT_TYPE;
585 SPropValue.value.l = MAPI_MAILUSER;
586 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
588 /* PR_DISPLAY_TYPE */
589 SPropValue.ulPropTag = PR_DISPLAY_TYPE;
590 SPropValue.value.l = 0;
591 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
594 SPropValue.ulPropTag = PR_GIVEN_NAME_UNICODE;
595 SPropValue.value.lpszA = username;
596 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
598 /* PR_DISPLAY_NAME */
599 SPropValue.ulPropTag = PR_DISPLAY_NAME_UNICODE;
600 SPropValue.value.lpszA = username;
601 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
603 /* PR_7BIT_DISPLAY_NAME */
604 SPropValue.ulPropTag = PR_7BIT_DISPLAY_NAME_UNICODE;
605 SPropValue.value.lpszA = username;
606 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
608 /* PR_SMTP_ADDRESS */
609 SPropValue.ulPropTag = PR_SMTP_ADDRESS_UNICODE;
610 SPropValue.value.lpszA = username;
611 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
614 SPropValue.ulPropTag = PR_ADDRTYPE_UNICODE;
615 SPropValue.value.lpszA = "SMTP";
616 SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
618 SetRecipientType(&(SRowSet->aRow[last]), RecipClass);
624 static bool set_usernames_RecipientType(TALLOC_CTX *mem_ctx, uint32_t *index, struct SRowSet *rowset,
625 char **usernames, struct PropertyTagArray_r *flaglist,
626 enum ulRecipClass RecipClass)
629 uint32_t count = *index;
630 static uint32_t counter = 0;
632 if (count == 0) counter = 0;
633 if (!usernames) return false;
635 for (i = 0; usernames[i]; i++) {
636 if (flaglist->aulPropTag[count] == MAPI_UNRESOLVED) {
637 set_external_recipients(mem_ctx, rowset, usernames[i], RecipClass);
639 if (flaglist->aulPropTag[count] == MAPI_RESOLVED) {
640 SetRecipientType(&(rowset->aRow[counter]), RecipClass);
651 static char **collapse_recipients(TALLOC_CTX *mem_ctx, struct oclient *oclient)
657 if (!oclient->mapi_to && !oclient->mapi_cc && !oclient->mapi_bcc) return NULL;
660 for (i = 0; oclient->mapi_to && oclient->mapi_to[i]; i++, count++);
661 for (i = 0; oclient->mapi_cc && oclient->mapi_cc[i]; i++, count++);
662 for (i = 0; oclient->mapi_bcc && oclient->mapi_bcc[i]; i++, count++);
664 usernames = talloc_array(mem_ctx, char *, count + 1);
667 for (i = 0; oclient->mapi_to && oclient->mapi_to[i]; i++, count++) {
668 usernames[count] = talloc_strdup(mem_ctx, oclient->mapi_to[i]);
671 for (i = 0; oclient->mapi_cc && oclient->mapi_cc[i]; i++, count++) {
672 usernames[count] = talloc_strdup(mem_ctx, oclient->mapi_cc[i]);
675 for (i = 0; oclient->mapi_bcc && oclient->mapi_bcc[i]; i++, count++) {
676 usernames[count] = talloc_strdup(mem_ctx, oclient->mapi_bcc[i]);
679 usernames[count++] = 0;
685 * Write a stream with MAX_READ_SIZE chunks
688 #define MAX_READ_SIZE 0x1000
690 static bool openchangeclient_stream(TALLOC_CTX *mem_ctx, mapi_object_t obj_parent,
691 mapi_object_t obj_stream, uint32_t mapitag,
692 uint32_t access_flags, struct Binary_r bin)
694 enum MAPISTATUS retval;
700 /* Open a stream on the parent for the given property */
701 retval = OpenStream(&obj_parent, mapitag, access_flags, &obj_stream);
702 fprintf (stderr, "openstream: retval = %s (0x%.8x)\n",
703 mapi_get_errstr (retval), retval);
705 if (retval != MAPI_E_SUCCESS) return false;
707 /* WriteStream operation */
708 printf("We are about to write %u bytes in the stream\n", bin.cb);
709 size = MAX_READ_SIZE;
711 while (offset <= bin.cb) {
712 stream.length = size;
713 stream.data = talloc_size(mem_ctx, size);
714 memcpy(stream.data, bin.lpb + offset, size);
716 retval = WriteStream(&obj_stream, &stream, &read_size);
717 talloc_free(stream.data);
718 if (retval != MAPI_E_SUCCESS) return false;
722 /* Exit when there is nothing left to write */
724 mapi_object_release(&obj_stream);
730 if ((offset + size) > bin.cb) {
731 size = bin.cb - offset;
735 mapi_object_release(&obj_stream);
741 #define SETPROPS_COUNT 4
747 static enum MAPISTATUS openchangeclient_sendmail(TALLOC_CTX *mem_ctx,
748 mapi_object_t *obj_store,
749 struct oclient *oclient)
751 enum MAPISTATUS retval;
752 struct SPropTagArray *SPropTagArray;
753 struct SPropValue SPropValue;
754 struct SRowSet *SRowSet = NULL;
755 struct PropertyTagArray_r *flaglist = NULL;
757 mapi_object_t obj_outbox;
758 mapi_object_t obj_message;
759 mapi_object_t obj_stream;
762 struct SPropValue props[SETPROPS_COUNT];
763 uint32_t prop_count = 0;
766 mapi_object_init(&obj_outbox);
767 mapi_object_init(&obj_message);
769 if (oclient->pf == true) {
770 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_outbox, oclient->folder);
771 if (retval != MAPI_E_SUCCESS) return retval;
773 /* Get Sent Items folder but should be using olFolderOutbox */
774 retval = GetDefaultFolder(obj_store, &id_outbox, olFolderOutbox);
775 if (retval != MAPI_E_SUCCESS) return retval;
777 /* Open outbox folder */
778 retval = OpenFolder(obj_store, id_outbox, &obj_outbox);
779 if (retval != MAPI_E_SUCCESS) return retval;
782 /* Create the message */
783 retval = CreateMessage(&obj_outbox, &obj_message);
784 if (retval != MAPI_E_SUCCESS) return retval;
786 /* Recipients operations */
787 SPropTagArray = set_SPropTagArray(mem_ctx, 0xA,
789 PR_DISPLAY_NAME_UNICODE,
792 PR_TRANSMITTABLE_DISPLAY_NAME_UNICODE,
793 PR_EMAIL_ADDRESS_UNICODE,
796 PR_7BIT_DISPLAY_NAME_UNICODE,
797 PR_SMTP_ADDRESS_UNICODE);
799 oclient->usernames = collapse_recipients(mem_ctx, oclient);
802 retval = ResolveNames(mapi_object_get_session(&obj_message), (const char **)oclient->usernames,
803 SPropTagArray, &SRowSet, &flaglist, MAPI_UNICODE);
804 MAPIFreeBuffer(SPropTagArray);
805 if (retval != MAPI_E_SUCCESS) return retval;
808 SRowSet = talloc_zero(mem_ctx, struct SRowSet);
811 set_usernames_RecipientType(mem_ctx, &index, SRowSet, oclient->mapi_to, flaglist, MAPI_TO);
812 set_usernames_RecipientType(mem_ctx, &index, SRowSet, oclient->mapi_cc, flaglist, MAPI_CC);
813 set_usernames_RecipientType(mem_ctx, &index, SRowSet, oclient->mapi_bcc, flaglist, MAPI_BCC);
815 SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
816 SPropValue.value.l = 0;
817 SRowSet_propcpy(mem_ctx, SRowSet, SPropValue);
819 /* ModifyRecipients operation */
820 retval = ModifyRecipients(&obj_message, SRowSet);
821 MAPIFreeBuffer(SRowSet);
822 MAPIFreeBuffer(flaglist);
823 if (retval != MAPI_E_SUCCESS) return retval;
825 /* set message properties */
826 msgflag = MSGFLAG_UNSENT;
827 oclient->subject = (!oclient->subject) ? "" : oclient->subject;
828 set_SPropValue_proptag(&props[0], PR_SUBJECT_UNICODE,
829 (const void *)oclient->subject);
830 set_SPropValue_proptag(&props[1], PR_MESSAGE_FLAGS,
831 (const void *)&msgflag);
834 /* Set PR_BODY or PR_HTML or inline PR_HTML */
835 if (oclient->pr_body) {
836 editor = EDITOR_FORMAT_PLAINTEXT;
837 set_SPropValue_proptag(&props[3], PR_MSG_EDITOR_FORMAT, (const void *)&editor);
839 if (strlen(oclient->pr_body) > MAX_READ_SIZE) {
842 bin.lpb = (uint8_t *)oclient->pr_body;
843 bin.cb = strlen(oclient->pr_body);
844 openchangeclient_stream(mem_ctx, obj_message, obj_stream, PR_BODY, 2, bin);
846 set_SPropValue_proptag(&props[2], PR_BODY_UNICODE,
847 (const void *)oclient->pr_body);
850 } else if (oclient->pr_html_inline) {
851 editor = EDITOR_FORMAT_HTML;
852 set_SPropValue_proptag(&props[3], PR_MSG_EDITOR_FORMAT, (const void *)&editor);
854 if (strlen(oclient->pr_html_inline) > MAX_READ_SIZE) {
857 bin.lpb = (uint8_t *)oclient->pr_html_inline;
858 bin.cb = strlen(oclient->pr_html_inline);
860 openchangeclient_stream(mem_ctx, obj_message, obj_stream, PR_HTML, 2, bin);
862 struct SBinary_short bin;
864 bin.cb = strlen(oclient->pr_html_inline);
865 bin.lpb = (uint8_t *)oclient->pr_html_inline;
866 set_SPropValue_proptag(&props[2], PR_HTML, (void *)&bin);
870 } else if (&oclient->pr_html) {
871 editor = EDITOR_FORMAT_HTML;
872 set_SPropValue_proptag(&props[3], PR_MSG_EDITOR_FORMAT, (const void *)&editor);
874 if (oclient->pr_html.cb <= MAX_READ_SIZE) {
875 struct SBinary_short bin;
877 bin.cb = oclient->pr_html.cb;
878 bin.lpb = oclient->pr_html.lpb;
880 set_SPropValue_proptag(&props[2], PR_HTML, (void *)&bin);
883 mapi_object_init(&obj_stream);
884 openchangeclient_stream(mem_ctx, obj_message, obj_stream, PR_HTML, 2, oclient->pr_html);
888 retval = SetProps(&obj_message, 0, props, prop_count);
889 if (retval != MAPI_E_SUCCESS) return retval;
891 /* attachment related code */
892 if (oclient->attach) {
895 for (i = 0; oclient->attach[i].filename; i++) {
896 mapi_object_t obj_attach;
897 mapi_object_t obj_stream;
898 struct SPropValue props_attach[4];
899 uint32_t count_props_attach;
901 mapi_object_init(&obj_attach);
903 retval = CreateAttach(&obj_message, &obj_attach);
904 if (retval != MAPI_E_SUCCESS) return retval;
906 props_attach[0].ulPropTag = PR_ATTACH_METHOD;
907 props_attach[0].value.l = ATTACH_BY_VALUE;
908 props_attach[1].ulPropTag = PR_RENDERING_POSITION;
909 props_attach[1].value.l = 0;
910 props_attach[2].ulPropTag = PR_ATTACH_FILENAME;
911 printf("Sending %s:\n", oclient->attach[i].filename);
912 props_attach[2].value.lpszA = get_filename(oclient->attach[i].filename);
913 props_attach[3].ulPropTag = PR_ATTACH_CONTENT_ID;
914 props_attach[3].value.lpszA = get_filename(oclient->attach[i].filename);
915 count_props_attach = 4;
918 retval = SetProps(&obj_attach, 0, props_attach, count_props_attach);
919 if (retval != MAPI_E_SUCCESS) return retval;
921 /* Stream operations */
922 mapi_object_init(&obj_stream);
923 openchangeclient_stream(mem_ctx, obj_attach, obj_stream, PR_ATTACH_DATA_BIN, 2, oclient->attach[i].bin);
925 /* Save changes on attachment */
926 retval = SaveChangesAttachment(&obj_message, &obj_attach, KeepOpenReadWrite);
927 if (retval != MAPI_E_SUCCESS) return retval;
929 mapi_object_release(&obj_attach);
934 retval = SaveChangesMessage(&obj_outbox, &obj_message, KeepOpenReadOnly);
935 if (retval != MAPI_E_SUCCESS) return retval;
938 /* Submit the message */
939 retval = SubmitMessage(&obj_message);
940 if (retval != MAPI_E_SUCCESS) return retval;
943 mapi_object_release(&obj_message);
944 mapi_object_release(&obj_outbox);
946 return MAPI_E_SUCCESS;
950 * delete a mail from user INBOX
952 static bool openchangeclient_deletemail(TALLOC_CTX *mem_ctx,
953 mapi_object_t *obj_store,
954 struct oclient *oclient)
956 enum MAPISTATUS retval;
957 struct SPropTagArray *SPropTagArray;
958 struct SRowSet SRowSet;
960 mapi_id_t *id_messages;
961 uint32_t count_messages;
963 mapi_object_t obj_inbox;
964 mapi_object_t obj_table;
968 if (!oclient->subject) {
969 printf("You need to specify at least a message subject pattern\n");
970 MAPI_RETVAL_IF(!oclient->subject, MAPI_E_INVALID_PARAMETER, NULL);
973 mapi_object_init(&obj_inbox);
974 mapi_object_init(&obj_table);
976 if (oclient->pf == true) {
977 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_inbox, oclient->folder);
978 if (retval != MAPI_E_SUCCESS) return retval;
980 retval = GetReceiveFolder(obj_store, &id_inbox, NULL);
981 if (retval != MAPI_E_SUCCESS) return false;
983 retval = OpenFolder(obj_store, id_inbox, &obj_inbox);
984 if (retval != MAPI_E_SUCCESS) return false;
987 retval = GetContentsTable(&obj_inbox, &obj_table, 0, NULL);
988 if (retval != MAPI_E_SUCCESS) return false;
990 SPropTagArray = set_SPropTagArray(mem_ctx, 0x5,
996 retval = SetColumns(&obj_table, SPropTagArray);
997 if (retval != MAPI_E_SUCCESS) return false;
999 while ((retval = QueryRows(&obj_table, 0x10, TBL_ADVANCE, &SRowSet)) == MAPI_E_SUCCESS) {
1000 count_rows = SRowSet.cRows;
1001 if (!count_rows) break;
1002 id_messages = talloc_array(mem_ctx, uint64_t, count_rows);
1005 len = strlen(oclient->subject);
1007 for (i = 0; i < count_rows; i++) {
1008 if (!strncmp(SRowSet.aRow[i].lpProps[4].value.lpszA, oclient->subject, len)) {
1009 id_messages[count_messages] = SRowSet.aRow[i].lpProps[1].value.d;
1013 if (count_messages) {
1014 retval = DeleteMessage(&obj_inbox, id_messages, count_messages);
1015 if (retval != MAPI_E_SUCCESS) return false;
1019 mapi_object_release(&obj_table);
1020 mapi_object_release(&obj_inbox);
1026 static enum MAPISTATUS check_conflict_date(struct oclient *oclient,
1028 struct FILETIME *ft)
1030 enum MAPISTATUS retval;
1031 mapi_object_t obj_store;
1032 struct mapi_session *session;
1033 struct mapi_session *session2;
1036 session = mapi_object_get_session(obj);
1037 retval = MapiLogonEx(oclient->mapi_ctx, &session2, session->profile->profname, session->profile->password);
1038 MAPI_RETVAL_IF(retval, retval, NULL);
1040 mapi_object_init(&obj_store);
1041 retval = OpenPublicFolder(session2, &obj_store);
1042 MAPI_RETVAL_IF(retval, retval, NULL);
1044 retval = IsFreeBusyConflict(&obj_store, ft, &conflict);
1047 if (conflict == true) {
1048 printf("[WARNING]: This start date conflicts with another appointment\n");
1049 return MAPI_E_INVALID_PARAMETER;
1052 return MAPI_E_SUCCESS;
1059 static enum MAPISTATUS appointment_SetProps(TALLOC_CTX *mem_ctx,
1060 mapi_object_t *obj_folder,
1061 mapi_object_t *obj_message,
1062 struct oclient *oclient)
1064 enum MAPISTATUS retval;
1065 struct SPropValue *lpProps;
1066 struct FILETIME *start_date;
1067 struct FILETIME *end_date;
1068 uint32_t cValues = 0;
1075 lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
1077 if (oclient->subject) {
1078 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_CONVERSATION_TOPIC_UNICODE,
1079 (const void *) oclient->subject);
1080 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT_UNICODE,
1081 (const void *) oclient->subject);
1083 if (oclient->pr_body) {
1084 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_BODY_UNICODE, (const void *)oclient->pr_body);
1086 if (oclient->location) {
1087 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidLocation, (const void *)oclient->location);
1089 if (oclient->dtstart) {
1090 if (!strptime(oclient->dtstart, DATE_FORMAT, &tm)) {
1091 printf("Invalid date format: yyyy-mm-dd hh:mm:ss (e.g.: 2007-09-17 10:00:00)\n");
1092 return MAPI_E_INVALID_PARAMETER;
1094 unix_to_nt_time(&nt, mktime(&tm));
1095 start_date = talloc(mem_ctx, struct FILETIME);
1096 start_date->dwLowDateTime = (nt << 32) >> 32;
1097 start_date->dwHighDateTime = (nt >> 32);
1099 retval = check_conflict_date(oclient, obj_folder, start_date);
1100 if (oclient->force == false) {
1101 MAPI_RETVAL_IF(retval, retval, NULL);
1104 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_START_DATE, (const void *)start_date);
1105 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidCommonStart, (const void *)start_date);
1106 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentStartWhole, (const void *) start_date);
1108 if (oclient->dtend) {
1109 if (!strptime(oclient->dtend, DATE_FORMAT, &tm)) {
1110 printf("Invalid date format: yyyy-mm-dd hh:mm:ss (e.g.:2007-09-17 18:30:00)\n");
1111 return MAPI_E_INVALID_PARAMETER;
1113 unix_to_nt_time(&nt, mktime(&tm));
1114 end_date = talloc(mem_ctx, struct FILETIME);
1115 end_date->dwLowDateTime = (nt << 32) >> 32;
1116 end_date->dwHighDateTime = (nt >> 32);
1118 retval = check_conflict_date(oclient, obj_folder, end_date);
1119 if (oclient->force == false) {
1120 MAPI_RETVAL_IF(retval, retval, NULL);
1123 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_END_DATE, (const void *) end_date);
1124 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidCommonEnd, (const void *) end_date);
1125 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentEndWhole, (const void *) end_date);
1128 if (!oclient->update) {
1129 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS_UNICODE, (const void *)"IPM.Appointment");
1132 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_FLAGS, (const void *)&flag);
1134 flag= MEETING_STATUS_NONMEETING;
1135 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentStateFlags, (const void *) &flag);
1138 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidReminderDelta, (const void *)&flag);
1140 /* WARNING needs to replace private */
1141 flag2 = oclient->private;
1142 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidPrivate, (const void *)&flag2);
1144 oclient->label = (oclient->label == -1) ? 0 : oclient->label;
1145 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentColor, (const void *) &oclient->label);
1147 oclient->busystatus = (oclient->busystatus == -1) ? 0 : oclient->busystatus;
1148 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidBusyStatus, (const void *) &oclient->busystatus);
1150 if (oclient->busystatus != -1) {
1151 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidBusyStatus, (const void *) &oclient->busystatus);
1153 if (oclient->label != -1) {
1154 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidAppointmentColor, (const void *) &oclient->label);
1158 flag = (oclient->private == true) ? 2 : 0;
1159 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_SENSITIVITY, (const void *)&flag);
1161 retval = SetProps(obj_message, 0, lpProps, cValues);
1162 MAPIFreeBuffer(lpProps);
1163 MAPI_RETVAL_IF(retval, retval, NULL);
1165 return MAPI_E_SUCCESS;
1169 static bool openchangeclient_sendappointment(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
1171 enum MAPISTATUS retval;
1172 mapi_object_t obj_calendar;
1173 mapi_object_t obj_message;
1174 mapi_id_t id_calendar;
1177 mapi_object_init(&obj_calendar);
1179 if (oclient->pf == true) {
1180 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_calendar, oclient->folder);
1181 if (retval != MAPI_E_SUCCESS) return false;
1183 /* Open Calendar default folder */
1184 retval = GetDefaultFolder(obj_store, &id_calendar, olFolderCalendar);
1185 if (retval != MAPI_E_SUCCESS) return false;
1187 retval = OpenFolder(obj_store, id_calendar, &obj_calendar);
1188 if (retval != MAPI_E_SUCCESS) return false;
1191 /* Create calendar message */
1192 mapi_object_init(&obj_message);
1193 retval = CreateMessage(&obj_calendar, &obj_message);
1194 if (retval != MAPI_E_SUCCESS) return false;
1196 /* Set calendar message properties */
1197 retval = appointment_SetProps(mem_ctx, &obj_calendar, &obj_message, oclient);
1198 if (retval != MAPI_E_SUCCESS) return false;
1200 retval = SaveChangesMessage(&obj_calendar, &obj_message, KeepOpenReadOnly);
1201 if (retval != MAPI_E_SUCCESS) return false;
1203 /* Fetch and Display the message unique ID */
1204 uniq_id = build_uniqueID(mem_ctx, &obj_calendar, &obj_message);
1205 printf(" %-25s: %s\n", "Unique ID", uniq_id);
1207 talloc_free(uniq_id);
1209 mapi_object_release(&obj_message);
1210 mapi_object_release(&obj_calendar);
1218 static enum MAPISTATUS contact_SetProps(TALLOC_CTX *mem_ctx,
1219 mapi_object_t *obj_folder,
1220 mapi_object_t *obj_message,
1221 struct oclient *oclient)
1223 enum MAPISTATUS retval;
1224 struct SPropValue *lpProps;
1225 struct mapi_nameid *nameid;
1226 struct SPropTagArray *SPropTagArray;
1227 uint32_t cValues = 0;
1229 /* Build the list of named properties we want to set */
1230 nameid = mapi_nameid_new(mem_ctx);
1231 retval = mapi_nameid_string_add(nameid, "urn:schemas:contacts:fileas", PS_PUBLIC_STRINGS);
1232 if (retval != MAPI_E_SUCCESS) {
1233 talloc_free(nameid);
1237 /* GetIDsFromNames and map property types */
1238 SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
1239 retval = GetIDsFromNames(obj_folder, nameid->count,
1240 nameid->nameid, 0, &SPropTagArray);
1241 if (retval != MAPI_E_SUCCESS) {
1242 talloc_free(nameid);
1245 mapi_nameid_SPropTagArray(nameid, SPropTagArray);
1246 MAPIFreeBuffer(nameid);
1249 lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
1251 if (oclient->card_name) {
1252 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT_UNICODE, (const void *)oclient->card_name);
1253 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidFileUnder, (const void *)oclient->card_name);
1254 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, SPropTagArray->aulPropTag[0], (const void *)oclient->card_name);
1256 if (oclient->full_name) {
1257 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_DISPLAY_NAME_UNICODE, (const void *)oclient->full_name);
1259 if (oclient->email) {
1260 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidEmail1OriginalDisplayName, (const void *)oclient->email);
1261 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidEmail1EmailAddress, (const void *)oclient->email);
1263 if (!oclient->update) {
1264 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS_UNICODE, (const void *)"IPM.Contact");
1266 retval = SetProps(obj_message, 0, lpProps, cValues);
1267 MAPIFreeBuffer(SPropTagArray);
1268 MAPIFreeBuffer(lpProps);
1269 MAPI_RETVAL_IF(retval, retval, NULL);
1271 return MAPI_E_SUCCESS;
1274 static bool openchangeclient_sendcontact(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
1276 enum MAPISTATUS retval;
1277 mapi_object_t obj_contact;
1278 mapi_object_t obj_message;
1279 mapi_id_t id_contact;
1282 mapi_object_init(&obj_contact);
1284 if (oclient->pf == true) {
1285 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_contact, oclient->folder);
1286 if (retval != MAPI_E_SUCCESS) return retval;
1288 /* Open Contact default folder */
1289 retval = GetDefaultFolder(obj_store, &id_contact, olFolderContacts);
1290 if (retval != MAPI_E_SUCCESS) return false;
1292 retval = OpenFolder(obj_store, id_contact, &obj_contact);
1293 if (retval != MAPI_E_SUCCESS) return false;
1296 /* Create contact message */
1297 mapi_object_init(&obj_message);
1298 retval = CreateMessage(&obj_contact, &obj_message);
1299 if (retval != MAPI_E_SUCCESS) return false;
1301 /* Set contact message properties */
1302 retval = contact_SetProps(mem_ctx, &obj_contact, &obj_message, oclient);
1303 if (retval != MAPI_E_SUCCESS) return false;
1305 retval = SaveChangesMessage(&obj_contact, &obj_message, KeepOpenReadOnly);
1306 if (retval != MAPI_E_SUCCESS) return false;
1308 /* Fetch and Display the message unique ID */
1309 uniq_id = build_uniqueID(mem_ctx, &obj_contact, &obj_message);
1310 printf(" %-25s: %s\n", "Unique ID", uniq_id);
1312 talloc_free(uniq_id);
1314 mapi_object_release(&obj_message);
1315 mapi_object_release(&obj_contact);
1323 static enum MAPISTATUS task_SetProps(TALLOC_CTX *mem_ctx,
1324 mapi_object_t *obj_message,
1325 struct oclient *oclient)
1327 enum MAPISTATUS retval;
1328 struct SPropValue *lpProps;
1329 struct FILETIME *start_date;
1330 struct FILETIME *end_date;
1331 uint32_t cValues = 0;
1336 lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
1338 if (oclient->card_name) {
1339 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_CONVERSATION_TOPIC_UNICODE, (const void *)oclient->card_name);
1340 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT_UNICODE, (const void *)oclient->card_name);
1343 if (oclient->dtstart) {
1344 if (!strptime(oclient->dtstart, DATE_FORMAT, &tm)) {
1345 printf("Invalid date format (e.g.: 2007-06-01 22:30:00)\n");
1346 return MAPI_E_INVALID_PARAMETER;
1348 unix_to_nt_time(&nt, mktime(&tm));
1349 start_date = talloc(mem_ctx, struct FILETIME);
1350 start_date->dwLowDateTime = (nt << 32) >> 32;
1351 start_date->dwHighDateTime = (nt >> 32);
1352 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskStartDate, (const void *)start_date);
1355 if (oclient->dtend) {
1356 if (!strptime(oclient->dtend, DATE_FORMAT, &tm)) {
1357 printf("Invalid date format (e.g.: 2007-06-01 22:30:00)\n");
1358 return MAPI_E_INVALID_PARAMETER;
1360 unix_to_nt_time(&nt, mktime(&tm));
1361 end_date = talloc(mem_ctx, struct FILETIME);
1362 end_date->dwLowDateTime = (nt << 32) >> 32;
1363 end_date->dwHighDateTime = (nt >> 32);
1364 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskDueDate, (const void *)end_date);
1367 if (oclient->pr_body) {
1368 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_BODY_UNICODE, (const void *)oclient->pr_body);
1371 if (!oclient->update) {
1372 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS_UNICODE, (const void *)"IPM.Task");
1373 oclient->importance = (oclient->importance == -1) ? 1 : oclient->importance;
1374 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_IMPORTANCE, (const void *)&oclient->importance);
1375 oclient->taskstatus = (oclient->taskstatus == -1) ? 0 : oclient->taskstatus;
1376 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskStatus, (const void *)&oclient->taskstatus);
1378 if (oclient->importance != -1) {
1379 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_IMPORTANCE, (const void *)&oclient->importance);
1381 if (oclient->taskstatus != -1) {
1382 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidTaskStatus, (const void *)&oclient->taskstatus);
1386 retval = SetProps(obj_message, 0, lpProps, cValues);
1387 MAPIFreeBuffer(lpProps);
1388 MAPI_RETVAL_IF(retval, retval, NULL);
1390 return MAPI_E_SUCCESS;
1393 static bool openchangeclient_sendtask(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
1395 enum MAPISTATUS retval;
1396 mapi_object_t obj_task;
1397 mapi_object_t obj_message;
1401 mapi_object_init(&obj_task);
1403 if (oclient->pf == true) {
1404 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_task, oclient->folder);
1405 if (retval != MAPI_E_SUCCESS) return retval;
1407 /* Open Contact default folder */
1408 retval = GetDefaultFolder(obj_store, &id_task, olFolderTasks);
1409 if (retval != MAPI_E_SUCCESS) return false;
1411 retval = OpenFolder(obj_store, id_task, &obj_task);
1412 if (retval != MAPI_E_SUCCESS) return false;
1415 /* Create contact message */
1416 mapi_object_init(&obj_message);
1417 retval = CreateMessage(&obj_task, &obj_message);
1418 if (retval != MAPI_E_SUCCESS) return false;
1420 /* Set contact properties */
1421 retval = task_SetProps(mem_ctx, &obj_message, oclient);
1423 retval = SaveChangesMessage(&obj_task, &obj_message, KeepOpenReadOnly);
1424 if (retval != MAPI_E_SUCCESS) return false;
1426 /* Fetch and Display the message unique ID */
1427 uniq_id = build_uniqueID(mem_ctx, &obj_task, &obj_message);
1428 printf(" %-25s: %s\n", "Unique ID", uniq_id);
1430 talloc_free(uniq_id);
1432 mapi_object_release(&obj_message);
1433 mapi_object_release(&obj_task);
1442 static enum MAPISTATUS note_SetProps(TALLOC_CTX *mem_ctx,
1443 mapi_object_t *obj_message,
1444 struct oclient *oclient)
1446 enum MAPISTATUS retval;
1447 struct SPropValue *lpProps;
1448 uint32_t cValues = 0;
1452 lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
1454 if (oclient->card_name) {
1455 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_CONVERSATION_TOPIC_UNICODE, (const void *)oclient->card_name);
1456 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_SUBJECT_UNICODE, (const void *)oclient->card_name);
1457 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_NORMALIZED_SUBJECT_UNICODE, (const void *)oclient->card_name);
1458 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_BODY_UNICODE, (const void *)oclient->card_name);
1461 if (!oclient->update) {
1462 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_CLASS_UNICODE, (const void *)"IPM.StickyNote");
1465 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_MESSAGE_FLAGS, (const void *)&value);
1468 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PR_ICON_INDEX, (const void *)&value);
1471 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidSideEffects, (const void *)&value);
1473 oclient->color = (oclient->color == -1) ? olYellow : oclient->color;
1474 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteColor, (const void *)&oclient->color);
1476 oclient->width = (oclient->width == -1) ? 166 : oclient->width;
1477 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteWidth, (const void *)&oclient->width);
1479 oclient->height = (oclient->height == -1) ? 200 : oclient->height;
1480 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteHeight, (const void *)&oclient->height);
1483 if (oclient->color != -1) {
1484 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteColor, (const void *)&oclient->color);
1486 if (oclient->width != -1) {
1487 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteWidth, (const void *)&oclient->width);
1489 if (oclient->height != -1) {
1490 lpProps = add_SPropValue(mem_ctx, lpProps, &cValues, PidLidNoteHeight, (const void *)&oclient->height);
1495 retval = SetProps(obj_message, 0, lpProps, cValues);
1496 MAPIFreeBuffer(lpProps);
1497 MAPI_RETVAL_IF(retval, retval, NULL);
1499 return MAPI_E_SUCCESS;
1502 static bool openchangeclient_sendnote(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
1504 enum MAPISTATUS retval;
1505 mapi_object_t obj_note;
1506 mapi_object_t obj_message;
1510 mapi_object_init(&obj_note);
1512 if (oclient->pf == true) {
1513 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_note, oclient->folder);
1514 if (retval != MAPI_E_SUCCESS) return retval;
1516 /* Open Contact default folder */
1517 retval = GetDefaultFolder(obj_store, &id_note, olFolderNotes);
1518 if (retval != MAPI_E_SUCCESS) return false;
1520 retval = OpenFolder(obj_store, id_note, &obj_note);
1521 if (retval != MAPI_E_SUCCESS) return false;
1524 /* Create contact message */
1525 mapi_object_init(&obj_message);
1526 retval = CreateMessage(&obj_note, &obj_message);
1527 if (retval != MAPI_E_SUCCESS) return false;
1529 /* Set Note message properties */
1530 retval = note_SetProps(mem_ctx, &obj_message, oclient);
1531 if (retval != MAPI_E_SUCCESS) return false;
1533 retval = SaveChangesMessage(&obj_note, &obj_message, KeepOpenReadOnly);
1534 if (retval != MAPI_E_SUCCESS) return false;
1536 /* Fetch and Display the message unique ID */
1537 uniq_id = build_uniqueID(mem_ctx, &obj_note, &obj_message);
1538 printf(" %-25s: %s\n", "Unique ID", uniq_id);
1540 talloc_free(uniq_id);
1542 mapi_object_release(&obj_message);
1543 mapi_object_release(&obj_note);
1549 static const char *get_container_class(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id)
1551 enum MAPISTATUS retval;
1552 mapi_object_t obj_folder;
1553 struct SPropTagArray *SPropTagArray;
1554 struct SPropValue *lpProps;
1557 mapi_object_init(&obj_folder);
1558 retval = OpenFolder(parent, folder_id, &obj_folder);
1559 if (retval != MAPI_E_SUCCESS) return false;
1561 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_CONTAINER_CLASS);
1562 retval = GetProps(&obj_folder, MAPI_UNICODE, SPropTagArray, &lpProps, &count);
1563 MAPIFreeBuffer(SPropTagArray);
1564 mapi_object_release(&obj_folder);
1565 if ((lpProps[0].ulPropTag != PR_CONTAINER_CLASS) || (retval != MAPI_E_SUCCESS)) {
1569 return lpProps[0].value.lpszA;
1572 static bool get_child_folders(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id, int count)
1574 enum MAPISTATUS retval;
1576 mapi_object_t obj_folder;
1577 mapi_object_t obj_htable;
1578 struct SPropTagArray *SPropTagArray;
1579 struct SRowSet rowset;
1581 const char *comment;
1582 const uint32_t *total;
1583 const uint32_t *unread;
1584 const uint32_t *child;
1586 const uint64_t *fid;
1589 mapi_object_init(&obj_folder);
1590 retval = OpenFolder(parent, folder_id, &obj_folder);
1591 if (retval != MAPI_E_SUCCESS) return false;
1593 mapi_object_init(&obj_htable);
1594 retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
1595 if (retval != MAPI_E_SUCCESS) return false;
1597 SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
1598 PR_DISPLAY_NAME_UNICODE,
1603 PR_FOLDER_CHILD_COUNT);
1604 retval = SetColumns(&obj_htable, SPropTagArray);
1605 MAPIFreeBuffer(SPropTagArray);
1606 if (retval != MAPI_E_SUCCESS) return false;
1608 while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
1609 for (index = 0; index < rowset.cRows; index++) {
1610 fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
1611 name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME_UNICODE);
1612 comment = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_COMMENT_UNICODE);
1613 total = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_CONTENT_COUNT);
1614 unread = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_CONTENT_UNREAD);
1615 child = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_FOLDER_CHILD_COUNT);
1617 for (i = 0; i < count; i++) {
1620 printf("|---+ %-15s : %-20s (Total: %u / Unread: %u - Container class: %s) [FID: 0x%016"PRIx64"]\n",
1621 name, comment?comment:"", total?*total:0, unread?*unread:0,
1622 get_container_class(mem_ctx, parent, *fid), *fid);
1623 if (child && *child) {
1624 ret = get_child_folders(mem_ctx, &obj_folder, *fid, count + 1);
1625 if (ret == false) return ret;
1630 mapi_object_release(&obj_htable);
1631 mapi_object_release(&obj_folder);
1636 static bool get_child_folders_pf(TALLOC_CTX *mem_ctx, mapi_object_t *parent, mapi_id_t folder_id, int count)
1638 enum MAPISTATUS retval;
1640 mapi_object_t obj_folder;
1641 mapi_object_t obj_htable;
1642 struct SPropTagArray *SPropTagArray;
1643 struct SRowSet rowset;
1645 const uint32_t *child;
1647 const uint64_t *fid;
1650 mapi_object_init(&obj_folder);
1651 retval = OpenFolder(parent, folder_id, &obj_folder);
1652 if (retval != MAPI_E_SUCCESS) return false;
1654 mapi_object_init(&obj_htable);
1655 retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
1656 if (retval != MAPI_E_SUCCESS) return false;
1658 SPropTagArray = set_SPropTagArray(mem_ctx, 0x3,
1659 PR_DISPLAY_NAME_UNICODE,
1661 PR_FOLDER_CHILD_COUNT);
1662 retval = SetColumns(&obj_htable, SPropTagArray);
1663 MAPIFreeBuffer(SPropTagArray);
1664 if (retval != MAPI_E_SUCCESS) return false;
1666 while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &rowset)) != MAPI_E_NOT_FOUND) && rowset.cRows) {
1667 for (index = 0; index < rowset.cRows; index++) {
1668 fid = (const uint64_t *)find_SPropValue_data(&rowset.aRow[index], PR_FID);
1669 name = (const char *)find_SPropValue_data(&rowset.aRow[index], PR_DISPLAY_NAME_UNICODE);
1670 child = (const uint32_t *)find_SPropValue_data(&rowset.aRow[index], PR_FOLDER_CHILD_COUNT);
1672 for (i = 0; i < count; i++) {
1675 printf("|---+ %-15s [FID: 0x%016"PRIx64"]\n", name, *fid);
1677 ret = get_child_folders_pf(mem_ctx, &obj_folder, *fid, count + 1);
1678 if (ret == false) return ret;
1687 static bool openchangeclient_pf(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store)
1689 enum MAPISTATUS retval;
1690 mapi_id_t id_pubroot;
1692 retval = GetDefaultPublicFolder(obj_store, &id_pubroot, olFolderPublicRoot);
1693 if (retval != MAPI_E_SUCCESS) return false;
1695 return get_child_folders_pf(mem_ctx, obj_store, id_pubroot, 0);
1699 static bool openchangeclient_mailbox(TALLOC_CTX *mem_ctx,
1700 mapi_object_t *obj_store)
1702 enum MAPISTATUS retval;
1703 mapi_id_t id_mailbox;
1704 struct SPropTagArray *SPropTagArray;
1705 struct SPropValue *lpProps;
1707 const char *mailbox_name;
1709 /* Retrieve the mailbox folder name */
1710 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_DISPLAY_NAME_UNICODE);
1711 retval = GetProps(obj_store, MAPI_UNICODE, SPropTagArray, &lpProps, &cValues);
1712 MAPIFreeBuffer(SPropTagArray);
1713 if (retval != MAPI_E_SUCCESS) return false;
1715 if (lpProps[0].value.lpszW) {
1716 mailbox_name = lpProps[0].value.lpszW;
1721 /* Prepare the directory listing */
1722 retval = GetDefaultFolder(obj_store, &id_mailbox, olFolderTopInformationStore);
1723 if (retval != MAPI_E_SUCCESS) return false;
1725 printf("+ %s\n", mailbox_name);
1726 return get_child_folders(mem_ctx, obj_store, id_mailbox, 0);
1729 static bool openchangeclient_fetchitems(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, const char *item,
1730 struct oclient *oclient)
1732 enum MAPISTATUS retval;
1733 mapi_object_t obj_tis;
1734 mapi_object_t obj_folder;
1735 mapi_object_t obj_table;
1736 mapi_object_t obj_message;
1738 uint32_t olFolder = 0;
1739 struct SRowSet SRowSet;
1740 struct SPropTagArray *SPropTagArray;
1741 struct mapi_SPropValue_array properties_array;
1746 if (!item) return false;
1748 mapi_object_init(&obj_tis);
1749 mapi_object_init(&obj_folder);
1751 for (i = 0; defaultFolders[i].olFolder; i++) {
1752 if (!strncasecmp(defaultFolders[i].container_class, item, strlen(defaultFolders[i].container_class))) {
1753 olFolder = defaultFolders[i].olFolder;
1757 if (!olFolder) return false;
1759 if (oclient->pf == true) {
1760 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_folder, oclient->folder);
1761 if (retval != MAPI_E_SUCCESS) return retval;
1763 if (oclient->folder) {
1764 retval = GetDefaultFolder(obj_store, &fid, olFolderTopInformationStore);
1765 MAPI_RETVAL_IF(retval, retval, mem_ctx);
1767 retval = OpenFolder(obj_store, fid, &obj_tis);
1768 MAPI_RETVAL_IF(retval, retval, mem_ctx);
1770 retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_folder, oclient->folder);
1771 MAPI_RETVAL_IF(retval, retval, mem_ctx);
1773 retval = GetDefaultFolder(obj_store, &fid, olFolder);
1774 if (retval != MAPI_E_SUCCESS) return false;
1776 /* We now open the folder */
1777 retval = OpenFolder(obj_store, fid, &obj_folder);
1778 if (retval != MAPI_E_SUCCESS) return false;
1782 /* Operations on the folder */
1783 mapi_object_init(&obj_table);
1784 retval = GetContentsTable(&obj_folder, &obj_table, 0, &count);
1785 if (retval != MAPI_E_SUCCESS) return false;
1787 printf("MAILBOX (%u messages)\n", count);
1789 mapi_object_release(&obj_table);
1790 mapi_object_release(&obj_folder);
1791 mapi_object_release(&obj_tis);
1796 SPropTagArray = set_SPropTagArray(mem_ctx, 0x8,
1802 PR_MESSAGE_CLASS_UNICODE,
1803 PR_RULE_MSG_PROVIDER,
1805 retval = SetColumns(&obj_table, SPropTagArray);
1806 MAPIFreeBuffer(SPropTagArray);
1807 if (retval != MAPI_E_SUCCESS) return false;
1809 while ((retval = QueryRows(&obj_table, count, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows) {
1810 count -= SRowSet.cRows;
1811 for (i = 0; i < SRowSet.cRows; i++) {
1812 mapi_object_init(&obj_message);
1813 retval = OpenMessage(&obj_folder,
1814 SRowSet.aRow[i].lpProps[0].value.d,
1815 SRowSet.aRow[i].lpProps[1].value.d,
1817 if (retval != MAPI_E_NOT_FOUND) {
1818 if (oclient->summary) {
1819 mapidump_message_summary(&obj_message);
1821 retval = GetPropsAll(&obj_message, MAPI_UNICODE, &properties_array);
1822 if (retval == MAPI_E_SUCCESS) {
1823 id = talloc_asprintf(mem_ctx, ": %"PRIX64"/%"PRIX64,
1824 SRowSet.aRow[i].lpProps[0].value.d,
1825 SRowSet.aRow[i].lpProps[1].value.d);
1826 mapi_SPropValue_array_named(&obj_message,
1830 mapidump_message(&properties_array, id, NULL);
1832 case olFolderCalendar:
1833 mapidump_appointment(&properties_array, id);
1835 case olFolderContacts:
1836 mapidump_contact(&properties_array, id);
1839 mapidump_task(&properties_array, id);
1842 mapidump_note(&properties_array, id);
1848 mapi_object_release(&obj_message);
1853 mapi_object_release(&obj_table);
1854 mapi_object_release(&obj_folder);
1855 mapi_object_release(&obj_tis);
1863 * Edit the existing item specified on command line.
1864 * The function first loops over the mailbox, looking for the folder
1865 * ID, then it looks for the particular message ID. It finally opens
1866 * it, set properties and save the message.
1869 static enum MAPISTATUS folder_lookup(TALLOC_CTX *mem_ctx,
1871 mapi_object_t *obj_parent,
1872 mapi_id_t folder_id,
1873 mapi_object_t *obj_ret)
1875 enum MAPISTATUS retval;
1876 mapi_object_t obj_folder;
1877 mapi_object_t obj_htable;
1878 struct SPropTagArray *SPropTagArray;
1879 struct SRowSet SRowSet;
1881 const uint64_t *fid;
1883 mapi_object_init(&obj_folder);
1884 retval = OpenFolder(obj_parent, folder_id, &obj_folder);
1885 if (retval != MAPI_E_SUCCESS) return retval;
1887 mapi_object_init(&obj_htable);
1888 retval = GetHierarchyTable(&obj_folder, &obj_htable, 0, NULL);
1889 if (retval != MAPI_E_SUCCESS) return retval;
1891 SPropTagArray = set_SPropTagArray(mem_ctx, 0x1, PR_FID);
1892 retval = SetColumns(&obj_htable, SPropTagArray);
1893 MAPIFreeBuffer(SPropTagArray);
1894 if (retval != MAPI_E_SUCCESS) return retval;
1896 while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows)) {
1897 for (i = 0; i < SRowSet.cRows; i++) {
1898 fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_FID);
1899 if (fid && *fid == sfid) {
1900 retval = OpenFolder(&obj_folder, *fid, obj_ret);
1901 mapi_object_release(&obj_htable);
1902 mapi_object_release(&obj_folder);
1903 return MAPI_E_SUCCESS;
1905 retval = folder_lookup(mem_ctx, sfid, &obj_folder, *fid, obj_ret);
1906 if (retval == MAPI_E_SUCCESS) {
1907 mapi_object_release(&obj_htable);
1908 mapi_object_release(&obj_folder);
1909 return MAPI_E_SUCCESS;
1915 mapi_object_release(&obj_htable);
1916 mapi_object_release(&obj_folder);
1918 errno = MAPI_E_NOT_FOUND;
1919 return MAPI_E_NOT_FOUND;
1922 static enum MAPISTATUS message_lookup(TALLOC_CTX *mem_ctx,
1924 mapi_object_t *obj_folder,
1925 mapi_object_t *obj_message)
1927 enum MAPISTATUS retval;
1928 mapi_object_t obj_htable;
1929 struct SPropTagArray *SPropTagArray;
1930 struct SRowSet SRowSet;
1932 const uint64_t *fid;
1933 const uint64_t *mid;
1935 mapi_object_init(&obj_htable);
1936 retval = GetContentsTable(obj_folder, &obj_htable, 0, NULL);
1937 if (retval != MAPI_E_SUCCESS) return retval;
1939 SPropTagArray = set_SPropTagArray(mem_ctx, 0x2, PR_FID, PR_MID);
1940 retval = SetColumns(&obj_htable, SPropTagArray);
1941 MAPIFreeBuffer(SPropTagArray);
1942 if (retval != MAPI_E_SUCCESS) return retval;
1944 while (((retval = QueryRows(&obj_htable, 0x32, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND) && SRowSet.cRows) {
1945 for (i = 0; i < SRowSet.cRows; i++) {
1946 fid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_FID);
1947 mid = (const uint64_t *)find_SPropValue_data(&SRowSet.aRow[i], PR_MID);
1948 if (mid && *mid == smid) {
1949 retval = OpenMessage(obj_folder, *fid, *mid, obj_message, ReadWrite);
1950 mapi_object_release(&obj_htable);
1956 mapi_object_release(&obj_htable);
1958 errno = MAPI_E_NOT_FOUND;
1959 return MAPI_E_NOT_FOUND;
1962 static bool openchangeclient_updateitem(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store,
1963 struct oclient *oclient, const char *container_class)
1965 enum MAPISTATUS retval;
1966 mapi_object_t obj_folder;
1967 mapi_object_t obj_message;
1972 const char *item = NULL;
1974 item = oclient->update;
1977 DEBUG(0, ("Missing ID\n"));
1978 errno = MAPI_E_INVALID_PARAMETER;
1982 if (!container_class) {
1983 DEBUG(0, ("Missing container class\n"));
1984 errno = MAPI_E_INVALID_PARAMETER;
1988 fid_str = strsep((char **)&item, "/");
1989 if (!fid_str || !item) {
1990 DEBUG(0, (" Invalid ID: %s\n", fid_str ? fid_str : "null"));
1991 errno = MAPI_E_INVALID_PARAMETER;
1995 fid = strtoull(fid_str, NULL, 16);
1996 mid = strtoull(item, NULL, 16);
1998 /* Step 1: search the folder from Top Information Store */
1999 mapi_object_init(&obj_folder);
2000 retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
2001 if (retval != MAPI_E_SUCCESS) return false;
2003 retval = folder_lookup(mem_ctx, fid, obj_store, id_tis, &obj_folder);
2004 if (retval != MAPI_E_SUCCESS) return false;
2006 /* Step 2: search the message */
2007 mapi_object_init(&obj_message);
2008 retval = message_lookup(mem_ctx, mid, &obj_folder, &obj_message);
2009 if (retval != MAPI_E_SUCCESS) return false;
2011 /* Step 3: edit the message */
2012 if (!strcmp(container_class, IPF_APPOINTMENT)) {
2013 retval = appointment_SetProps(mem_ctx, &obj_folder, &obj_message, oclient);
2014 } else if (!strcmp(container_class, IPF_CONTACT)) {
2015 retval = contact_SetProps(mem_ctx, &obj_folder, &obj_message, oclient);
2016 } else if (!strcmp(container_class, IPF_TASK)) {
2017 retval = task_SetProps(mem_ctx, &obj_message, oclient);
2018 } else if (!strcmp(container_class, IPF_STICKYNOTE)) {
2019 retval = note_SetProps(mem_ctx, &obj_message, oclient);
2022 if (retval != MAPI_E_SUCCESS) return false;
2024 /* Step 4: save the message */
2025 retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
2026 if (retval != MAPI_E_SUCCESS) return false;
2028 mapi_object_release(&obj_message);
2029 mapi_object_release(&obj_folder);
2035 * Delete an item given its unique ID
2037 static bool openchangeclient_deleteitems(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store,
2038 struct oclient *oclient)
2040 enum MAPISTATUS retval;
2041 mapi_object_t obj_folder;
2042 mapi_object_t obj_message;
2047 const char *item = NULL;
2049 item = oclient->delete;
2052 DEBUG(0, ("Missing ID\n"));
2053 errno = MAPI_E_INVALID_PARAMETER;
2057 fid_str = strsep((char **)&item, "/");
2058 if (!fid_str || !item) {
2059 DEBUG(0, (" Invalid ID: %s\n", fid_str ? fid_str : "null"));
2060 errno = MAPI_E_INVALID_PARAMETER;
2064 fid = strtoull(fid_str, NULL, 16);
2065 mid = strtoull(item, NULL, 16);
2067 /* Step 1: search the folder from Top Information Store */
2068 mapi_object_init(&obj_folder);
2069 retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
2070 if (retval != MAPI_E_SUCCESS) return false;
2072 retval = folder_lookup(mem_ctx, fid, obj_store, id_tis, &obj_folder);
2073 if (retval != MAPI_E_SUCCESS) return false;
2075 /* Step 2: search the message within returned folder */
2076 mapi_object_init(&obj_message);
2077 retval = message_lookup(mem_ctx, mid, &obj_folder, &obj_message);
2078 if (retval != MAPI_E_SUCCESS) return false;
2080 /* Step 3: delete the message */
2081 retval = DeleteMessage(&obj_folder, &mid, 1);
2082 if (retval != MAPI_E_SUCCESS) return false;
2084 mapi_object_release(&obj_message);
2085 mapi_object_release(&obj_folder);
2094 * Assume msg is received in Inbox folder since we only register
2095 * notifications for this folder.
2099 static enum MAPISTATUS openchangeclient_findmail(mapi_object_t *obj_store,
2102 enum MAPISTATUS retval;
2103 TALLOC_CTX *mem_ctx;
2104 struct SRowSet SRowSet;
2105 struct SPropValue *lpProp;
2106 struct mapi_SPropValue_array properties_array;
2108 const mapi_id_t *mid;
2109 mapi_object_t obj_inbox;
2110 mapi_object_t obj_table;
2111 mapi_object_t obj_message;
2112 struct SPropTagArray *SPropTagArray = NULL;
2117 mem_ctx = talloc_named(NULL, 0, "openchangeclient_findmail");
2119 /* Get Inbox folder */
2120 retval = GetDefaultFolder(obj_store, &fid, olFolderInbox);
2121 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
2124 mapi_object_init(&obj_inbox);
2125 retval = OpenFolder(obj_store, fid, &obj_inbox);
2126 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
2128 /* Retrieve contents table */
2129 mapi_object_init(&obj_table);
2130 retval = GetContentsTable(&obj_inbox, &obj_table, 0, &count);
2131 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
2133 SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
2136 retval = SetColumns(&obj_table, SPropTagArray);
2137 MAPIFreeBuffer(SPropTagArray);
2138 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
2140 while ((retval = QueryRows(&obj_table, 0xa, TBL_ADVANCE, &SRowSet)) != MAPI_E_NOT_FOUND && SRowSet.cRows) {
2141 for (i = 0; i < SRowSet.cRows; i++) {
2142 lpProp = get_SPropValue_SRowSet(&SRowSet, PR_MID);
2143 if (lpProp != NULL) {
2144 mid = (const uint64_t *)get_SPropValue(lpProp, PR_MID);
2145 if (*mid == msgid) {
2146 mapi_object_init(&obj_message);
2147 retval = OpenMessage(obj_store,
2148 SRowSet.aRow[i].lpProps[0].value.d,
2149 SRowSet.aRow[i].lpProps[1].value.d,
2151 if (GetLastError() == MAPI_E_SUCCESS) {
2152 retval = GetPropsAll(&obj_message, MAPI_UNICODE, &properties_array);
2153 if (retval != MAPI_E_SUCCESS) return retval;
2154 id = talloc_asprintf(mem_ctx, ": %"PRIX64"/%"PRIX64,
2155 SRowSet.aRow[i].lpProps[0].value.d,
2156 SRowSet.aRow[i].lpProps[1].value.d);
2157 mapidump_message(&properties_array, id, NULL);
2158 mapi_object_release(&obj_message);
2163 mapi_object_release(&obj_message);
2169 mapi_object_release(&obj_table);
2170 mapi_object_release(&obj_inbox);
2172 talloc_free(mem_ctx);
2173 return MAPI_E_SUCCESS;
2177 static int callback(uint16_t NotificationType, void *NotificationData, void *private_data)
2179 struct NewMailNotification *newmail;
2180 struct HierarchyTableChange *htable;
2181 struct ContentsTableChange *ctable;
2182 struct ContentsTableChange *stable;
2184 switch(NotificationType) {
2186 case fnevNewMail|fnevMbit:
2187 DEBUG(0, ("[+] New mail Received\n"));
2188 newmail = (struct NewMailNotification *) NotificationData;
2189 mapidump_newmail(newmail, "\t");
2190 openchangeclient_findmail((mapi_object_t *)private_data, newmail->MID);
2191 mapi_errstr("openchangeclient_findmail", GetLastError());
2193 case fnevObjectCreated:
2194 DEBUG(0, ("[+] Folder Created\n"));
2196 case fnevObjectDeleted:
2197 DEBUG(0, ("[+] Folder Deleted\n"));
2199 case fnevObjectModified:
2200 case fnevTbit|fnevObjectModified:
2201 case fnevUbit|fnevObjectModified:
2202 case fnevTbit|fnevUbit|fnevObjectModified:
2203 DEBUG(0, ("[+] Folder Modified\n"));
2205 case fnevObjectMoved:
2206 DEBUG(0, ("[+] Folder Moved\n"));
2208 case fnevObjectCopied:
2209 DEBUG(0, ("[+] Folder Copied\n"));
2211 case fnevSearchComplete:
2212 DEBUG(0, ("[+] Search complete in search folder\n"));
2214 case fnevTableModified:
2215 htable = (struct HierarchyTableChange *) NotificationData;
2216 DEBUG(0, ("[+] Hierarchy Table: "));
2217 switch (htable->TableEvent) {
2219 DEBUG(0, (" changed\n"));
2221 case TABLE_ROW_ADDED:
2222 DEBUG(0, ("row added\n"));
2224 case TABLE_ROW_DELETED:
2225 DEBUG(0, ("row deleted\n"));
2227 case TABLE_ROW_MODIFIED:
2228 DEBUG(0, ("row modified\n"));
2230 case TABLE_RESTRICT_DONE:
2231 DEBUG(0, ("restriction done\n"));
2238 case fnevStatusObjectModified:
2239 DEBUG(0, ("[+] ICS Notification\n"));
2241 case fnevMbit|fnevObjectCreated:
2242 DEBUG(0, ("[+] Message created\n"));
2244 case fnevMbit|fnevObjectDeleted:
2245 DEBUG(0, ("[+] Message deleted\n"));
2246 case fnevMbit|fnevObjectModified:
2247 DEBUG(0, ("[+] Message modified\n"));
2248 case fnevMbit|fnevObjectMoved:
2249 DEBUG(0, ("[+] Message moved\n"));
2250 case fnevMbit|fnevObjectCopied:
2251 DEBUG(0, ("[+] Message copied\n"));
2252 case fnevMbit|fnevTableModified:
2253 ctable = (struct ContentsTableChange *) NotificationData;
2254 DEBUG(0, ("[+] Contents Table: "));
2255 switch (ctable->TableEvent) {
2257 DEBUG(0, (" changed\n"));
2259 case TABLE_ROW_ADDED:
2260 DEBUG(0, ("row added\n"));
2262 case TABLE_ROW_DELETED:
2263 DEBUG(0, ("row deleted\n"));
2265 case TABLE_ROW_MODIFIED:
2266 DEBUG(0, ("row modified\n"));
2268 case TABLE_RESTRICT_DONE:
2269 DEBUG(0, ("restriction done\n"));
2276 case fnevMbit|fnevSbit|fnevObjectDeleted:
2277 DEBUG(0, ("[+] A message is no longer part of a search folder\n"));
2279 case fnevMbit|fnevSbit|fnevObjectModified:
2280 DEBUG(0, ("[+] A property on a message in a search folder has changed\n"));
2281 case fnevMbit|fnevSbit|fnevTableModified:
2282 stable = (struct ContentsTableChange *) NotificationData;
2283 DEBUG(0, ("[+] Search Table: "));
2284 switch (stable->TableEvent) {
2286 DEBUG(0, (" changed\n"));
2288 case TABLE_ROW_ADDED:
2289 DEBUG(0, ("row added\n"));
2291 case TABLE_ROW_DELETED:
2292 DEBUG(0, ("row deleted\n"));
2294 case TABLE_ROW_MODIFIED:
2295 DEBUG(0, ("row modified\n"));
2297 case TABLE_RESTRICT_DONE:
2298 DEBUG(0, ("restriction done\n"));
2306 printf("[+] Unsupported notification (0x%x)\n", NotificationType);
2314 static bool openchangeclient_notifications(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
2316 enum MAPISTATUS retval;
2317 mapi_object_t obj_inbox;
2319 uint32_t ulConnection;
2320 uint16_t ulEventMask;
2321 uint32_t notification = 0;
2322 struct mapi_session *session;
2324 /* Register notification */
2325 session = mapi_object_get_session(obj_store);
2326 retval = RegisterNotification(session);
2327 if (retval != MAPI_E_SUCCESS) return false;
2329 if (oclient->pf == true) {
2330 retval = openchangeclient_getpfdir(mem_ctx, obj_store, &obj_inbox, oclient->folder);
2331 if (retval != MAPI_E_SUCCESS) return retval;
2333 /* Retrieve Inbox folder ID */
2334 retval = GetDefaultFolder(obj_store, &fid, olFolderInbox);
2335 if (retval != MAPI_E_SUCCESS) return false;
2337 /* Open Inbox folder */
2338 mapi_object_init(&obj_inbox);
2339 retval = OpenFolder(obj_store, fid, &obj_inbox);
2340 if (retval != MAPI_E_SUCCESS) return false;
2343 /* subscribe Inbox to receive newmail notifications */
2344 ulEventMask = fnevNewMail|fnevObjectCreated|fnevObjectDeleted|
2345 fnevObjectModified|fnevObjectMoved|fnevObjectCopied|
2346 fnevSearchComplete|fnevTableModified|fnevStatusObjectModified;
2347 retval = Subscribe(obj_store, &ulConnection, ulEventMask, true, (mapi_notify_callback_t)callback,
2349 retval = Subscribe(&obj_inbox, &ulConnection, ulEventMask, true, (mapi_notify_callback_t)callback,
2351 if (retval != MAPI_E_SUCCESS) return false;
2353 /* wait for notifications: infinite loop */
2354 retval = RegisterAsyncNotification(mapi_object_get_session(obj_store), ¬ification);
2355 if( retval == MAPI_E_NOT_INITIALIZED ) {
2356 retval = MonitorNotification(mapi_object_get_session(obj_store), (void *)obj_store, NULL);
2358 if (retval != MAPI_E_SUCCESS) return false;
2360 retval = Unsubscribe(mapi_object_get_session(obj_store), ulConnection);
2361 if (retval != MAPI_E_SUCCESS) return false;
2363 mapi_object_release(&obj_inbox);
2369 static bool openchangeclient_mkdir(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
2371 enum MAPISTATUS retval;
2372 mapi_object_t obj_folder;
2373 mapi_object_t obj_child;
2374 mapi_object_t obj_tis;
2377 mapi_object_init(&obj_tis);
2378 mapi_object_init(&obj_folder);
2379 mapi_object_init(&obj_child);
2381 if (oclient->folder) {
2382 retval = GetDefaultFolder(obj_store, &id_inbox, olFolderTopInformationStore);
2383 if (retval != MAPI_E_SUCCESS) return false;
2385 retval = OpenFolder(obj_store, id_inbox, &obj_tis);
2386 if (retval != MAPI_E_SUCCESS) return false;
2388 retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_folder, oclient->folder);
2389 if (retval != MAPI_E_SUCCESS) return false;
2391 retval = GetDefaultFolder(obj_store, &id_inbox, olFolderInbox);
2392 if (retval != MAPI_E_SUCCESS) return false;
2394 retval = OpenFolder(obj_store, id_inbox, &obj_folder);
2395 if (retval != MAPI_E_SUCCESS) return false;
2398 retval = CreateFolder(&obj_folder, FOLDER_GENERIC, oclient->folder_name,
2399 oclient->folder_comment, OPEN_IF_EXISTS, &obj_child);
2400 if (retval != MAPI_E_SUCCESS) return false;
2402 mapi_object_release(&obj_child);
2403 mapi_object_release(&obj_folder);
2404 mapi_object_release(&obj_tis);
2410 static bool openchangeclient_rmdir(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
2412 enum MAPISTATUS retval;
2413 mapi_object_t obj_folder;
2414 mapi_object_t obj_child;
2415 mapi_object_t obj_tis;
2418 mapi_object_init(&obj_tis);
2419 mapi_object_init(&obj_folder);
2420 mapi_object_init(&obj_child);
2422 if (oclient->folder) {
2423 printf("Removing folder within %s\n", oclient->folder);
2424 retval = GetDefaultFolder(obj_store, &id_inbox, olFolderTopInformationStore);
2425 if (retval != MAPI_E_SUCCESS) return false;
2427 retval = OpenFolder(obj_store, id_inbox, &obj_tis);
2428 if (retval != MAPI_E_SUCCESS) return false;
2430 retval = openchangeclient_getdir(mem_ctx, &obj_tis, &obj_folder, oclient->folder);
2431 if (retval != MAPI_E_SUCCESS) return false;
2433 retval = GetDefaultFolder(obj_store, &id_inbox, olFolderInbox);
2434 if (retval != MAPI_E_SUCCESS) return false;
2436 retval = OpenFolder(obj_store, id_inbox, &obj_folder);
2437 if (retval != MAPI_E_SUCCESS) return false;
2440 retval = openchangeclient_getdir(mem_ctx, &obj_folder, &obj_child, oclient->folder_name);
2441 if (retval != MAPI_E_SUCCESS) return false;
2443 retval = EmptyFolder(&obj_child);
2444 if (retval != MAPI_E_SUCCESS) return false;
2446 printf("obj_child fid = 0x%"PRIx64"\n", mapi_object_get_id(&obj_child));
2448 retval = DeleteFolder(&obj_folder, mapi_object_get_id(&obj_child),
2450 if (retval != MAPI_E_SUCCESS) return false;
2452 mapi_object_release(&obj_child);
2453 mapi_object_release(&obj_folder);
2454 mapi_object_release(&obj_tis);
2459 static bool openchangeclient_userlist(TALLOC_CTX *mem_ctx,
2460 struct mapi_session *session)
2462 struct SPropTagArray *SPropTagArray;
2463 struct SRowSet *SRowSet;
2467 uint32_t rowsFetched = 0;
2468 uint32_t totalRecs = 0;
2470 GetGALTableCount(session, &totalRecs);
2471 printf("Total Number of entries in GAL: %d\n", totalRecs);
2473 SPropTagArray = set_SPropTagArray(mem_ctx, 0xc,
2476 PR_DISPLAY_NAME_UNICODE,
2477 PR_EMAIL_ADDRESS_UNICODE,
2480 PR_ADDRTYPE_UNICODE,
2481 PR_OFFICE_TELEPHONE_NUMBER_UNICODE,
2482 PR_OFFICE_LOCATION_UNICODE,
2484 PR_COMPANY_NAME_UNICODE,
2485 PR_ACCOUNT_UNICODE);
2488 ulFlags = TABLE_START;
2491 GetGALTable(session, SPropTagArray, &SRowSet, count, ulFlags);
2492 if ((!SRowSet) || (!(SRowSet->aRow))) {
2495 rowsFetched = SRowSet->cRows;
2497 for (i = 0; i < rowsFetched; i++) {
2498 mapidump_PAB_entry(&SRowSet->aRow[i]);
2501 ulFlags = TABLE_CUR;
2502 MAPIFreeBuffer(SRowSet);
2503 } while (rowsFetched == count);
2504 mapi_errstr("GetPABTable", GetLastError());
2506 MAPIFreeBuffer(SPropTagArray);
2512 static bool openchangeclient_ocpf_syntax(struct oclient *oclient)
2515 struct ocpf_file *element;
2516 uint32_t context_id;
2519 if (!oclient->ocpf_files || !oclient->ocpf_files->next) {
2520 errno = MAPI_E_INVALID_PARAMETER;
2524 /* Step 1. Initialize OCPF context */
2527 errno = MAPI_E_CALL_FAILED;
2531 /* Step2. Parse OCPF files */
2532 for (element = oclient->ocpf_files; element->next; element = element->next) {
2533 ret = ocpf_new_context(element->filename, &context_id, OCPF_FLAGS_READ);
2535 errno = MAPI_E_INVALID_PARAMETER;
2538 ret = ocpf_parse(context_id);
2540 DEBUG(0, ("ocpf_parse failed ...\n"));
2541 errno = MAPI_E_INVALID_PARAMETER;
2545 /* Dump OCPF contents */
2546 ocpf_dump(context_id);
2548 ret = ocpf_del_context(context_id);
2552 /* Step4. Release OCPF context */
2553 ret = ocpf_release();
2555 errno = MAPI_E_CALL_FAILED;
2563 static bool openchangeclient_ocpf_sender(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
2565 enum MAPISTATUS retval;
2567 struct ocpf_file *element;
2568 mapi_object_t obj_folder;
2569 mapi_object_t obj_message;
2570 uint32_t cValues = 0;
2571 struct SPropValue *lpProps;
2572 uint32_t context_id;
2575 if (!oclient->ocpf_files || !oclient->ocpf_files->next) {
2576 errno = MAPI_E_INVALID_PARAMETER;
2580 /* Step1. Initialize OCPF context */
2583 errno = MAPI_E_CALL_FAILED;
2587 /* Step2. Parse OCPF files */
2588 for (element = oclient->ocpf_files; element->next; element = element->next) {
2589 ret = ocpf_new_context(element->filename, &context_id, OCPF_FLAGS_READ);
2590 ret = ocpf_parse(context_id);
2592 errno = MAPI_E_INVALID_PARAMETER;
2597 /* Step3. Open destination folder using ocpf API */
2598 mapi_object_init(&obj_folder);
2599 retval = ocpf_OpenFolder(context_id, obj_store, &obj_folder);
2600 if (retval != MAPI_E_SUCCESS) return false;
2602 /* Step4. Create the message */
2603 mapi_object_init(&obj_message);
2604 retval = CreateMessage(&obj_folder, &obj_message);
2605 if (retval != MAPI_E_SUCCESS) return false;
2607 /* Step5, Set message recipients */
2608 retval = ocpf_set_Recipients(mem_ctx, context_id, &obj_message);
2609 if (retval != MAPI_E_SUCCESS && GetLastError() != MAPI_E_NOT_FOUND) return false;
2610 errno = MAPI_E_SUCCESS;
2612 /* Step6. Set message properties */
2613 retval = ocpf_set_SPropValue(mem_ctx, context_id, &obj_folder, &obj_message);
2614 if (retval != MAPI_E_SUCCESS) return false;
2616 /* Step7. Set message properties */
2617 lpProps = ocpf_get_SPropValue(context_id, &cValues);
2619 retval = SetProps(&obj_message, 0, lpProps, cValues);
2620 MAPIFreeBuffer(lpProps);
2621 if (retval != MAPI_E_SUCCESS) return false;
2623 /* Step8. Save message */
2624 retval = SaveChangesMessage(&obj_folder, &obj_message, KeepOpenReadOnly);
2625 if (retval != MAPI_E_SUCCESS) return false;
2627 mapi_object_release(&obj_message);
2628 mapi_object_release(&obj_folder);
2630 ocpf_del_context(context_id);
2636 static bool openchangeclient_ocpf_dump(TALLOC_CTX *mem_ctx, mapi_object_t *obj_store, struct oclient *oclient)
2638 enum MAPISTATUS retval;
2640 mapi_object_t obj_folder;
2641 mapi_object_t obj_message;
2643 const char *fid_str;
2646 const char *item = NULL;
2647 char *filename = NULL;
2648 struct mapi_SPropValue_array lpProps;
2649 uint32_t context_id;
2652 /* retrieve the FID/MID for ocpf_dump parameter */
2653 item = oclient->ocpf_dump;
2655 fid_str = strsep((char **)&item, "/");
2656 if (!fid_str || !item) {
2657 DEBUG(0, (" Invalid ID: %s\n", fid_str ? fid_str : "null"));
2658 errno = MAPI_E_INVALID_PARAMETER;
2662 fid = strtoull(fid_str, NULL, 16);
2663 mid = strtoull(item, NULL, 16);
2665 /* Step 1. search the folder from Top Information Store */
2666 mapi_object_init(&obj_folder);
2667 retval = GetDefaultFolder(obj_store, &id_tis, olFolderTopInformationStore);
2668 if (retval != MAPI_E_SUCCESS) return false;
2670 retval = folder_lookup(mem_ctx, fid, obj_store, id_tis, &obj_folder);
2671 if (retval != MAPI_E_SUCCESS) return false;
2673 /* Step 2. search the message */
2674 mapi_object_init(&obj_message);
2675 retval = message_lookup(mem_ctx, mid, &obj_folder, &obj_message);
2676 if (retval != MAPI_E_SUCCESS) return false;
2678 /* Step 3. retrieve all message properties */
2679 retval = GetPropsAll(&obj_message, MAPI_UNICODE, &lpProps);
2681 /* Step 4. save the message */
2684 filename = talloc_asprintf(mem_ctx, "%"PRIx64".ocpf", mid);
2685 DEBUG(0, ("OCPF output file: %s\n", filename));
2687 ret = ocpf_new_context(filename, &context_id, OCPF_FLAGS_CREATE);
2688 talloc_free(filename);
2689 ret = ocpf_write_init(context_id, fid);
2691 ret = ocpf_write_auto(context_id, &obj_message, &lpProps);
2692 if (ret == OCPF_SUCCESS) {
2693 ret = ocpf_write_commit(context_id);
2696 ret = ocpf_del_context(context_id);
2698 ret = ocpf_release();
2700 mapi_object_release(&obj_message);
2701 mapi_object_release(&obj_folder);
2707 static bool openchangeclient_freebusy(mapi_object_t *obj_store, struct oclient *oclient)
2709 enum MAPISTATUS retval;
2711 const char *message_name;
2713 const uint32_t *publish_start;
2714 const uint32_t *publish_end;
2715 const struct LongArray_r *busy_months;
2716 const struct BinaryArray_r *busy_events;
2717 const struct LongArray_r *tentative_months;
2718 const struct BinaryArray_r *tentative_events;
2719 const struct LongArray_r *oof_months;
2720 const struct BinaryArray_r *oof_events;
2722 uint32_t event_year;
2724 /* Step 1. Retrieve FreeBusy data for the given user */
2725 retval = GetUserFreeBusyData(obj_store, oclient->freebusy, &aRow);
2726 if (retval != MAPI_E_SUCCESS) return false;
2728 /* Step 2. Dump properties */
2729 message_name = (const char *) find_SPropValue_data(&aRow, PR_NORMALIZED_SUBJECT);
2730 publish_start = (const uint32_t *) find_SPropValue_data(&aRow, PR_FREEBUSY_PUBLISH_START);
2731 publish_end = (const uint32_t *) find_SPropValue_data(&aRow, PR_FREEBUSY_PUBLISH_END);
2732 busy_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_SCHDINFO_MONTHS_BUSY);
2733 busy_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_SCHDINFO_FREEBUSY_BUSY);
2734 tentative_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_SCHDINFO_MONTHS_TENTATIVE);
2735 tentative_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_SCHDINFO_FREEBUSY_TENTATIVE);
2736 oof_months = (const struct LongArray_r *) find_SPropValue_data(&aRow, PR_SCHDINFO_MONTHS_OOF);
2737 oof_events = (const struct BinaryArray_r *) find_SPropValue_data(&aRow, PR_SCHDINFO_FREEBUSY_OOF);
2739 year = GetFreeBusyYear(publish_start);
2741 DEBUG(0, ("FreeBusy (%s):\n", message_name));
2742 mapidump_date_SPropValue(aRow.lpProps[1], "* FreeBusy Last Modification Time", "\t");
2743 mapidump_freebusy_date(*publish_start, "\t* FreeBusy Publishing Start:");
2744 mapidump_freebusy_date(*publish_end, "\t *FreeBusy Publishing End: ");
2746 if (busy_months && ((*(const uint32_t *) busy_months) != MAPI_E_NOT_FOUND) &&
2747 busy_events && ((*(const uint32_t *) busy_events) != MAPI_E_NOT_FOUND)) {
2748 DEBUG(0, ("\t* Busy Events:\n"));
2749 for (i = 0; i < busy_months->cValues; i++) {
2750 event_year = mapidump_freebusy_year(busy_months->lpl[i], year);
2751 DEBUG(0, ("\t\t* %s %u:\n", mapidump_freebusy_month(busy_months->lpl[i], event_year), event_year));
2752 mapidump_freebusy_event(&busy_events->lpbin[i], busy_months->lpl[i], event_year, "\t\t\t* ");
2756 if (tentative_months && ((*(const uint32_t *) tentative_months) != MAPI_E_NOT_FOUND) &&
2757 tentative_events && ((*(const uint32_t *) tentative_events) != MAPI_E_NOT_FOUND)) {
2758 DEBUG(0, ("\t* Tentative Events:\n"));
2759 for (i = 0; i < tentative_months->cValues; i++) {
2760 event_year = mapidump_freebusy_year(tentative_months->lpl[i], year);
2761 DEBUG(0, ("\t\t* %s %u:\n", mapidump_freebusy_month(tentative_months->lpl[i], event_year), event_year));
2762 mapidump_freebusy_event(&tentative_events->lpbin[i], tentative_months->lpl[i], event_year, "\t\t\t* ");
2766 if (oof_months && ((*(const uint32_t *) oof_months) != MAPI_E_NOT_FOUND) &&
2767 oof_events && ((*(const uint32_t *) oof_events) != MAPI_E_NOT_FOUND)) {
2768 DEBUG(0, ("\t* Out Of Office Events:\n"));
2769 for (i = 0; i < oof_months->cValues; i++) {
2770 event_year = mapidump_freebusy_year(oof_months->lpl[i], year);
2771 DEBUG(0, ("\t\t* %s %u:\n", mapidump_freebusy_month(oof_months->lpl[i], event_year), event_year));
2772 mapidump_freebusy_event(&oof_events->lpbin[i], oof_months->lpl[i], event_year, "\t\t\t* ");
2776 MAPIFreeBuffer(aRow.lpProps);
2782 static void list_argument(const char *label, struct oc_element *oc_items)
2786 printf("Use one of the following %s values:\n", label);
2787 for (i = 0; oc_items[i].status; i++) {
2788 printf("%s\n", oc_items[i].status);
2793 static uint32_t oc_get_argument(const char *name, struct oc_element *oc_items, const char *label)
2797 for (i = 0; oc_items[i].status; i++) {
2798 if (!strncasecmp(oc_items[i].status, name, strlen(oc_items[i].status))) {
2799 return oc_items[i].index;
2802 list_argument(label, oc_items);
2807 int main(int argc, const char *argv[])
2809 TALLOC_CTX *mem_ctx;
2810 enum MAPISTATUS retval;
2811 struct mapi_session *session = NULL;
2812 mapi_object_t obj_store;
2813 struct oclient oclient;
2816 bool opt_sendmail = false;
2817 bool opt_sendappointment = false;
2818 bool opt_sendcontact = false;
2819 bool opt_sendtask = false;
2820 bool opt_sendnote = false;
2821 bool opt_fetchmail = false;
2822 bool opt_deletemail = false;
2823 bool opt_mailbox = false;
2824 bool opt_dumpdata = false;
2825 bool opt_notifications = false;
2826 bool opt_mkdir = false;
2827 bool opt_rmdir = false;
2828 bool opt_userlist = false;
2829 bool opt_ocpf_syntax = false;
2830 bool opt_ocpf_sender = false;
2831 const char *opt_profdb = NULL;
2832 char *opt_profname = NULL;
2833 const char *opt_username = NULL;
2834 const char *opt_password = NULL;
2835 const char *opt_attachments = NULL;
2836 const char *opt_fetchitems = NULL;
2837 const char *opt_html_file = NULL;
2838 const char *opt_mapi_to = NULL;
2839 const char *opt_mapi_cc = NULL;
2840 const char *opt_mapi_bcc = NULL;
2841 const char *opt_debug = NULL;
2843 enum {OPT_PROFILE_DB=1000, OPT_PROFILE, OPT_SENDMAIL, OPT_PASSWORD, OPT_SENDAPPOINTMENT,
2844 OPT_SENDCONTACT, OPT_SENDTASK, OPT_FETCHMAIL, OPT_STOREMAIL, OPT_DELETEMAIL,
2845 OPT_ATTACH, OPT_HTML_INLINE, OPT_HTML_FILE, OPT_MAPI_TO, OPT_MAPI_CC,
2846 OPT_MAPI_BCC, OPT_MAPI_SUBJECT, OPT_MAPI_BODY, OPT_MAILBOX,
2847 OPT_FETCHITEMS, OPT_MAPI_LOCATION, OPT_MAPI_STARTDATE, OPT_MAPI_ENDDATE,
2848 OPT_MAPI_BUSYSTATUS, OPT_NOTIFICATIONS, OPT_DEBUG, OPT_DUMPDATA,
2849 OPT_MAPI_EMAIL, OPT_MAPI_FULLNAME, OPT_MAPI_CARDNAME,
2850 OPT_MAPI_TASKSTATUS, OPT_MAPI_IMPORTANCE, OPT_MAPI_LABEL, OPT_PF,
2851 OPT_FOLDER, OPT_MAPI_COLOR, OPT_SENDNOTE, OPT_MKDIR, OPT_RMDIR,
2852 OPT_FOLDER_NAME, OPT_FOLDER_COMMENT, OPT_USERLIST, OPT_MAPI_PRIVATE,
2853 OPT_UPDATE, OPT_DELETEITEMS, OPT_OCPF_FILE, OPT_OCPF_SYNTAX,
2854 OPT_OCPF_SENDER, OPT_OCPF_DUMP, OPT_FREEBUSY, OPT_FORCE, OPT_FETCHSUMMARY,
2857 struct poptOption long_options[] = {
2859 {"database", 'f', POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", NULL },
2860 {"pf", 0, POPT_ARG_NONE, NULL, OPT_PF, "access public folders instead of mailbox", NULL },
2861 {"profile", 'p', POPT_ARG_STRING, NULL, OPT_PROFILE, "set the profile name", NULL },
2862 {"password", 'P', POPT_ARG_STRING, NULL, OPT_PASSWORD, "set the profile password", NULL },
2863 {"username", 0, POPT_ARG_STRING, NULL, OPT_USERNAME, "set the username of the mailbox to use", NULL },
2864 {"sendmail", 'S', POPT_ARG_NONE, NULL, OPT_SENDMAIL, "send a mail", NULL },
2865 {"sendappointment", 0, POPT_ARG_NONE, NULL, OPT_SENDAPPOINTMENT, "send an appointment", NULL },
2866 {"sendcontact", 0, POPT_ARG_NONE, NULL, OPT_SENDCONTACT, "send a contact", NULL },
2867 {"sendtask", 0, POPT_ARG_NONE, NULL, OPT_SENDTASK, "send a task", NULL },
2868 {"sendnote", 0, POPT_ARG_NONE, NULL, OPT_SENDNOTE, "send a note", NULL },
2869 {"fetchmail", 'F', POPT_ARG_NONE, NULL, OPT_FETCHMAIL, "fetch user INBOX mails", NULL },
2870 {"fetchsummary", 0, POPT_ARG_NONE, NULL, OPT_FETCHSUMMARY, "fetch message summaries only", NULL },
2871 {"storemail", 'G', POPT_ARG_STRING, NULL, OPT_STOREMAIL, "retrieve a mail on the filesystem", NULL },
2872 {"fetch-items", 'i', POPT_ARG_STRING, NULL, OPT_FETCHITEMS, "fetch specified user INBOX items", NULL },
2873 {"freebusy", 0, POPT_ARG_STRING, NULL, OPT_FREEBUSY, "display free / busy information for the specified user", NULL },
2874 {"force", 0, POPT_ARG_NONE, NULL, OPT_FORCE, "force openchangeclient behavior in some circumstances", NULL },
2875 {"delete", 0, POPT_ARG_STRING, NULL, OPT_DELETEITEMS, "delete a message given its unique ID", NULL },
2876 {"update", 'u', POPT_ARG_STRING, NULL, OPT_UPDATE, "update the specified item", NULL },
2877 {"mailbox", 'm', POPT_ARG_NONE, NULL, OPT_MAILBOX, "list mailbox folder summary", NULL },
2878 {"deletemail", 'D', POPT_ARG_NONE, NULL, OPT_DELETEMAIL, "delete a mail from user INBOX", NULL },
2879 {"attachments", 'A', POPT_ARG_STRING, NULL, OPT_ATTACH, "send a list of attachments", NULL },
2880 {"html-inline", 'I', POPT_ARG_STRING, NULL, OPT_HTML_INLINE, "send PR_HTML content", NULL },
2881 {"html-file", 'W', POPT_ARG_STRING, NULL, OPT_HTML_FILE, "use HTML file as content", NULL },
2882 {"to", 't', POPT_ARG_STRING, NULL, OPT_MAPI_TO, "set the To recipients", NULL },
2883 {"cc", 'c', POPT_ARG_STRING, NULL, OPT_MAPI_CC, "set the Cc recipients", NULL },
2884 {"bcc", 'b', POPT_ARG_STRING, NULL, OPT_MAPI_BCC, "set the Bcc recipients", NULL },
2885 {"subject", 's', POPT_ARG_STRING, NULL, OPT_MAPI_SUBJECT, "set the mail subject", NULL },
2886 {"body", 'B', POPT_ARG_STRING, NULL, OPT_MAPI_BODY, "set the mail body", NULL },
2887 {"location", 0, POPT_ARG_STRING, NULL, OPT_MAPI_LOCATION, "set the item location", NULL },
2888 {"label", 0, POPT_ARG_STRING, NULL, OPT_MAPI_LABEL, "set the event label", NULL },
2889 {"dtstart", 0, POPT_ARG_STRING, NULL, OPT_MAPI_STARTDATE, "set the event start date", NULL },
2890 {"dtend", 0, POPT_ARG_STRING, NULL, OPT_MAPI_ENDDATE, "set the event end date", NULL },
2891 {"busystatus", 0, POPT_ARG_STRING, NULL, OPT_MAPI_BUSYSTATUS, "set the item busy status", NULL },
2892 {"taskstatus", 0, POPT_ARG_STRING, NULL, OPT_MAPI_TASKSTATUS, "set the task status", NULL },
2893 {"importance", 0, POPT_ARG_STRING, NULL, OPT_MAPI_IMPORTANCE, "Set the item importance", NULL },
2894 {"email", 0, POPT_ARG_STRING, NULL, OPT_MAPI_EMAIL, "set the email address", NULL },
2895 {"fullname", 0, POPT_ARG_STRING, NULL, OPT_MAPI_FULLNAME, "set the full name", NULL },
2896 {"cardname", 0, POPT_ARG_STRING, NULL, OPT_MAPI_CARDNAME, "set a contact card name", NULL },
2897 {"color", 0, POPT_ARG_STRING, NULL, OPT_MAPI_COLOR, "set the note color", NULL },
2898 {"notifications", 0, POPT_ARG_NONE, NULL, OPT_NOTIFICATIONS, "monitor INBOX newmail notifications", NULL },
2899 {"folder", 0, POPT_ARG_STRING, NULL, OPT_FOLDER, "set the folder to use instead of inbox", NULL },
2900 {"mkdir", 0, POPT_ARG_NONE, NULL, OPT_MKDIR, "create a folder", NULL },
2901 {"rmdir", 0, POPT_ARG_NONE, NULL, OPT_RMDIR, "delete a folder", NULL },
2902 {"userlist", 0, POPT_ARG_NONE, NULL, OPT_USERLIST, "list Address Book entries", NULL },
2903 {"folder-name", 0, POPT_ARG_STRING, NULL, OPT_FOLDER_NAME, "set the folder name", NULL },
2904 {"folder-comment", 0, POPT_ARG_STRING, NULL, OPT_FOLDER_COMMENT, "set the folder comment", NULL },
2905 {"debuglevel", 'd', POPT_ARG_STRING, NULL, OPT_DEBUG, "set Debug Level", NULL },
2906 {"dump-data", 0, POPT_ARG_NONE, NULL, OPT_DUMPDATA, "dump the hex data", NULL },
2907 {"private", 0, POPT_ARG_NONE, NULL, OPT_MAPI_PRIVATE, "set the private flag on messages", NULL },
2908 {"ocpf-file", 0, POPT_ARG_STRING, NULL, OPT_OCPF_FILE, "set OCPF file", NULL },
2909 {"ocpf-dump", 0, POPT_ARG_STRING, NULL, OPT_OCPF_DUMP, "dump message into OCPF file", NULL },
2910 {"ocpf-syntax", 0, POPT_ARG_NONE, NULL, OPT_OCPF_SYNTAX, "check OCPF files syntax", NULL },
2911 {"ocpf-sender", 0, POPT_ARG_NONE, NULL, OPT_OCPF_SENDER, "send message using OCPF files contents", NULL },
2912 POPT_OPENCHANGE_VERSION
2913 {NULL, 0, 0, NULL, 0, NULL, NULL}
2916 mem_ctx = talloc_named(NULL, 0, "openchangeclient");
2918 init_oclient(&oclient);
2920 pc = poptGetContext("openchangeclient", argc, argv, long_options, 0);
2922 while ((opt = poptGetNextOpt(pc)) != -1) {
2928 oclient.folder = poptGetOptArg(pc);
2931 opt_debug = poptGetOptArg(pc);
2934 opt_dumpdata = true;
2937 opt_userlist = true;
2945 case OPT_FOLDER_NAME:
2946 oclient.folder_name = poptGetOptArg(pc);
2948 case OPT_FOLDER_COMMENT:
2949 oclient.folder_comment = poptGetOptArg(pc);
2951 case OPT_NOTIFICATIONS:
2952 opt_notifications = true;
2954 case OPT_PROFILE_DB:
2955 opt_profdb = poptGetOptArg(pc);
2958 opt_profname = talloc_strdup(mem_ctx, poptGetOptArg(pc));
2961 opt_password = poptGetOptArg(pc);
2964 opt_username = talloc_strdup(mem_ctx, poptGetOptArg(pc));
2969 case OPT_FETCHITEMS:
2970 opt_fetchitems = poptGetOptArg(pc);
2972 case OPT_FETCHSUMMARY:
2973 oclient.summary = true;
2975 case OPT_DELETEITEMS:
2976 oclient.delete = poptGetOptArg(pc);
2979 oclient.freebusy = poptGetOptArg(pc);
2982 oclient.update = poptGetOptArg(pc);
2985 opt_sendmail = true;
2987 case OPT_SENDAPPOINTMENT:
2988 opt_sendappointment = true;
2990 case OPT_SENDCONTACT:
2991 opt_sendcontact = true;
2994 opt_sendtask = true;
2997 opt_sendnote = true;
3000 opt_fetchmail = true;
3003 oclient.store_folder = poptGetOptArg(pc);
3005 case OPT_DELETEMAIL:
3006 opt_deletemail = true;
3009 opt_attachments = poptGetOptArg(pc);
3011 case OPT_HTML_INLINE:
3012 oclient.pr_html_inline = poptGetOptArg(pc);
3015 opt_html_file = poptGetOptArg(pc);
3018 opt_mapi_to = poptGetOptArg(pc);
3021 opt_mapi_cc = poptGetOptArg(pc);
3024 opt_mapi_bcc = poptGetOptArg(pc);
3026 case OPT_MAPI_SUBJECT:
3027 oclient.subject = poptGetOptArg(pc);
3030 oclient.pr_body = poptGetOptArg(pc);
3032 case OPT_MAPI_LOCATION:
3033 oclient.location = poptGetOptArg(pc);
3035 case OPT_MAPI_STARTDATE:
3036 oclient.dtstart = poptGetOptArg(pc);
3038 case OPT_MAPI_ENDDATE:
3039 oclient.dtend = poptGetOptArg(pc);
3041 case OPT_MAPI_BUSYSTATUS:
3042 oclient.busystatus = oc_get_argument(poptGetOptArg(pc),
3046 case OPT_MAPI_LABEL:
3047 oclient.label = oc_get_argument(poptGetOptArg(pc),
3051 case OPT_MAPI_IMPORTANCE:
3052 oclient.importance = oc_get_argument(poptGetOptArg(pc),
3056 case OPT_MAPI_TASKSTATUS:
3057 oclient.taskstatus = oc_get_argument(poptGetOptArg(pc),
3061 case OPT_MAPI_COLOR:
3062 oclient.color = oc_get_argument(poptGetOptArg(pc),
3066 case OPT_MAPI_EMAIL:
3067 oclient.email = poptGetOptArg(pc);
3069 case OPT_MAPI_FULLNAME:
3070 oclient.full_name = poptGetOptArg(pc);
3072 case OPT_MAPI_CARDNAME:
3073 oclient.card_name = poptGetOptArg(pc);
3075 case OPT_MAPI_PRIVATE:
3076 oclient.private = true;
3080 struct ocpf_file *element;
3082 if (!oclient.ocpf_files) {
3083 oclient.ocpf_files = talloc_zero(mem_ctx, struct ocpf_file);
3086 element = talloc_zero(mem_ctx, struct ocpf_file);
3087 element->filename = talloc_strdup(mem_ctx, poptGetOptArg(pc));
3088 DLIST_ADD(oclient.ocpf_files, element);
3091 case OPT_OCPF_SYNTAX:
3092 opt_ocpf_syntax = true;
3094 case OPT_OCPF_SENDER:
3095 opt_ocpf_sender = true;
3098 oclient.ocpf_dump = poptGetOptArg(pc);
3101 oclient.force = true;
3106 /* Sanity check on options */
3109 opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
3112 if (opt_sendmail && !opt_mapi_to && !opt_mapi_cc && !opt_mapi_bcc) {
3113 printf("You need to specify at least one recipient\n");
3117 if (opt_sendmail && (!oclient.pr_body && !oclient.pr_html_inline && !opt_html_file)) {
3118 printf("No body specified (body, html-inline or html-file)\n");
3122 if ((opt_sendmail && oclient.pf == true && !oclient.folder) ||
3123 (oclient.pf == true && !oclient.folder && !opt_mailbox && !oclient.freebusy)) {
3124 printf("--folder option is mandatory\n");
3128 if (opt_html_file && oclient.pr_body) {
3129 printf("PR_BODY and PR_HTML can't be set at the same time\n");
3133 if (oclient.pr_body && oclient.pr_html_inline) {
3134 printf("Inline HTML and PR_BODY content can't be set simulteanously\n");
3138 if (opt_html_file && oclient.pr_html_inline) {
3139 printf("PR_HTML from file and stdin can't be specified at the same time\n");
3143 if (opt_html_file) {
3144 oclient_read_file(mem_ctx, opt_html_file, &oclient, PR_HTML);
3147 if (opt_attachments) {
3148 if (oclient_parse_attachments(mem_ctx, opt_attachments, &oclient) == false) {
3149 printf("Unable to parse one of the specified attachments\n");
3154 if (opt_mkdir && !oclient.folder_name) {
3155 printf("mkdir requires --folder-name to be defined\n");
3159 /* One of the rare options which doesn't require MAPI to get
3162 if (opt_ocpf_syntax) {
3163 bool ret = openchangeclient_ocpf_syntax(&oclient);
3164 mapi_errstr("OCPF Syntax", GetLastError());
3172 * Initialize MAPI subsystem
3175 retval = MAPIInitialize(&oclient.mapi_ctx, opt_profdb);
3176 if (retval != MAPI_E_SUCCESS) {
3177 mapi_errstr("MAPIInitialize", GetLastError());
3182 SetMAPIDumpData(oclient.mapi_ctx, opt_dumpdata);
3185 SetMAPIDebugLevel(oclient.mapi_ctx, atoi(opt_debug));
3188 /* If no profile is specified try to load the default one from
3192 if (!opt_profname) {
3193 retval = GetDefaultProfile(oclient.mapi_ctx, &opt_profname);
3194 if (retval != MAPI_E_SUCCESS) {
3195 mapi_errstr("GetDefaultProfile", GetLastError());
3200 retval = MapiLogonEx(oclient.mapi_ctx, &session, opt_profname, opt_password);
3201 talloc_free(opt_profname);
3202 if (retval != MAPI_E_SUCCESS) {
3203 mapi_errstr("MapiLogonEx", GetLastError());
3208 if (false == openchangeclient_userlist(mem_ctx, session)) {
3216 * Open Default Message Store
3219 mapi_object_init(&obj_store);
3220 if (oclient.pf == true) {
3221 retval = OpenPublicFolder(session, &obj_store);
3222 if (retval != MAPI_E_SUCCESS) {
3223 mapi_errstr("OpenPublicFolder", GetLastError());
3226 } else if (opt_username) {
3227 retval = OpenUserMailbox(session, opt_username, &obj_store);
3228 if (retval != MAPI_E_SUCCESS) {
3229 mapi_errstr("OpenUserMailbox", GetLastError());
3233 retval = OpenMsgStore(session, &obj_store);
3234 if (retval != MAPI_E_SUCCESS) {
3235 mapi_errstr("OpenMsgStore", GetLastError());
3241 * OCPF sending command
3243 if (opt_ocpf_sender) {
3244 bool ret = openchangeclient_ocpf_sender(mem_ctx, &obj_store, &oclient);
3245 mapi_errstr("OCPF Sender", GetLastError());
3251 if (oclient.ocpf_dump) {
3252 bool ret = openchangeclient_ocpf_dump(mem_ctx, &obj_store, &oclient);
3253 mapi_errstr("OCPF Dump", GetLastError());
3259 if (opt_fetchitems) {
3260 bool ret = openchangeclient_fetchitems(mem_ctx, &obj_store, opt_fetchitems, &oclient);
3261 mapi_errstr("fetchitems", GetLastError());
3267 if (oclient.delete) {
3268 bool ret = openchangeclient_deleteitems(mem_ctx, &obj_store, &oclient);
3269 mapi_errstr("deleteitems", GetLastError());
3276 if (oclient.pf == true) {
3277 bool ret = openchangeclient_pf(mem_ctx, &obj_store);
3278 mapi_errstr("public folder", GetLastError());
3283 bool ret = openchangeclient_mailbox(mem_ctx, &obj_store);
3284 mapi_errstr("mailbox", GetLastError());
3291 /* MAPI email operations */
3293 /* recipients management */
3294 oclient.mapi_to = get_cmdline_recipients(mem_ctx, opt_mapi_to);
3295 oclient.mapi_cc = get_cmdline_recipients(mem_ctx, opt_mapi_cc);
3296 oclient.mapi_bcc = get_cmdline_recipients(mem_ctx, opt_mapi_bcc);
3298 retval = openchangeclient_sendmail(mem_ctx, &obj_store, &oclient);
3299 mapi_errstr("sendmail", GetLastError());
3300 if (retval != true) {
3305 if (opt_fetchmail) {
3306 retval = openchangeclient_fetchmail(&obj_store, &oclient);
3307 mapi_errstr("fetchmail", GetLastError());
3308 if (retval != true) {
3313 if (opt_deletemail) {
3314 bool ret = openchangeclient_deletemail(mem_ctx, &obj_store, &oclient);
3315 mapi_errstr("deletemail", GetLastError());
3321 /* MAPI calendar operations */
3322 if (opt_sendappointment) {
3324 if (!oclient.dtstart && !oclient.update) {
3325 printf("You need to specify a start date (e.g: 2007-06-01 22:30:00)\n");
3329 if (!oclient.dtend && !oclient.update) {
3330 printf("Setting default end date\n");
3331 oclient.dtend = oclient.dtstart;
3334 if (!oclient.update) {
3335 ret = openchangeclient_sendappointment(mem_ctx, &obj_store, &oclient);
3336 mapi_errstr("sendappointment", GetLastError());
3338 ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_APPOINTMENT);
3339 mapi_errstr("update appointment", GetLastError());
3346 if (oclient.freebusy) {
3347 bool ret = openchangeclient_freebusy(&obj_store, &oclient);
3348 mapi_errstr("freebusy", GetLastError());
3355 /* MAPI contact operations */
3356 if (opt_sendcontact) {
3358 if (!oclient.update) {
3359 ret = openchangeclient_sendcontact(mem_ctx, &obj_store, &oclient);
3360 mapi_errstr("sendcontact", GetLastError());
3362 ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_CONTACT);
3363 mapi_errstr("update contact", GetLastError());
3370 /* MAPI task operations */
3373 if (!oclient.dtstart && !oclient.update) {
3374 printf("You need to specify a start date (e.g: 2007-06-01 22:30:00)\n");
3378 if (!oclient.dtend && !oclient.update) {
3379 printf("Setting default end date\n");
3380 oclient.dtend = oclient.dtstart;
3383 if (!oclient.update) {
3384 ret = openchangeclient_sendtask(mem_ctx, &obj_store, &oclient);
3385 mapi_errstr("sendtask", GetLastError());
3387 ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_TASK);
3388 mapi_errstr("update task", GetLastError());
3395 /* MAPI note operations */
3398 if (!oclient.update) {
3399 ret = openchangeclient_sendnote(mem_ctx, &obj_store, &oclient);
3400 mapi_errstr("sendnote", GetLastError());
3402 ret = openchangeclient_updateitem(mem_ctx, &obj_store, &oclient, IPF_STICKYNOTE);
3403 mapi_errstr("update note", GetLastError());
3410 /* Monitor newmail notifications */
3411 if (opt_notifications) {
3412 openchangeclient_notifications(mem_ctx, &obj_store, &oclient);
3413 mapi_errstr("notifications", GetLastError());
3414 if (retval != true) {
3419 /* Folder operations */
3421 openchangeclient_mkdir(mem_ctx, &obj_store, &oclient);
3422 mapi_errstr("mkdir", GetLastError());
3423 if (retval != true) {
3429 openchangeclient_rmdir(mem_ctx, &obj_store, &oclient);
3430 mapi_errstr("rmdir", GetLastError());
3431 if (retval != true) {
3436 /* Uninitialize MAPI subsystem */
3439 poptFreeContext(pc);
3441 mapi_object_release(&obj_store);
3443 MAPIUninitialize(oclient.mapi_ctx);
3445 talloc_free(mem_ctx);