2 Stand-alone MAPI application
6 Copyright (C) Julien Kerihuel 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/>.
23 This sample code shows how to use multiple sessions in OpenChange
24 and shows notification system works with multiple sessions.
26 To use this sample code, run in the console:
27 ./multiple_notification --profileA=XXX --profileB=YYY
29 Send an email using any MAPI compliant client (openchangeclient for
30 example) to recipients matching profileA and profileB.
32 If everything works properly, you should see the output above:
33 $ ./multiple_notification --profileA=XXX --profileB=YYY
34 profileA: New mail Received
35 profileB: New mail received
37 For further example on how to retrieve and analyse
40 #include <libmapi/libmapi.h>
42 #include <samba/popt.h>
44 #define DEFAULT_PROFDB "%s/.openchange/profiles.ldb"
46 static int callback(uint16_t NotificationType, void *NotificationData, void *private_data)
48 switch (NotificationType) {
50 case fnevNewMail|fnevMbit:
51 DEBUG(0, ("%s: New mail Received\n", (const char *)private_data));
60 void *monitor(void *val)
62 enum MAPISTATUS retval;
63 mapi_object_t *obj_store;
65 obj_store = (mapi_object_t *) val;
66 retval = MonitorNotification(mapi_object_get_session(obj_store), (void *)obj_store, NULL);
67 if (retval != MAPI_E_SUCCESS) {
68 mapi_errstr("MonitorNotification", GetLastError());
74 int main(int ac, const char *av[])
76 enum MAPISTATUS retval;
78 struct mapi_context *mapi_ctx;
79 struct mapi_session *sessionA = NULL;
80 struct mapi_session *sessionB = NULL;
81 mapi_object_t obj_storeA;
82 mapi_object_t obj_storeB;
83 uint32_t ulConnectionA;
84 uint32_t ulConnectionB;
87 const char *opt_profdb = NULL;
88 const char *profileA = NULL;
89 const char *profileB = NULL;
93 enum { OPT_PROFILE_DB=1000, OPT_PROFILEA, OPT_PROFILEB };
95 struct poptOption long_options[] = {
97 {"database", 0, POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", NULL},
98 {"profileA", 0, POPT_ARG_STRING, NULL, OPT_PROFILEA, "profile A", NULL},
99 {"profileB", 0, POPT_ARG_STRING, NULL, OPT_PROFILEB, "profile B", NULL},
100 {NULL, 0, 0, NULL, 0, NULL, NULL}
103 /* Step 1. Retrieve and parse command line options */
104 mem_ctx = talloc_named(NULL, 0, "multiple_notif");
106 pc = poptGetContext("multiple_notif", ac, av, long_options, 0);
107 while ((opt = poptGetNextOpt(pc)) != -1) {
110 opt_profdb = poptGetOptArg(pc);
113 profileA = poptGetOptArg(pc);
116 profileB = poptGetOptArg(pc);
122 opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
125 if (!profileA || !profileB) {
126 printf("You need to specify 2 profiles (--profileA and --profileB options\n");
130 /* Step 2. Initialize MAPI subsystem */
131 retval = MAPIInitialize(&mapi_ctx, opt_profdb);
132 if (retval != MAPI_E_SUCCESS) {
133 mapi_errstr("MAPIInitialize", GetLastError());
137 retval = MapiLogonEx(mapi_ctx, &sessionA, profileA, NULL);
138 if (retval != MAPI_E_SUCCESS) {
139 mapi_errstr("MapiLogonEx for profileA", GetLastError());
143 retval = MapiLogonEx(mapi_ctx, &sessionB, profileB, NULL);
144 if (retval != MAPI_E_SUCCESS) {
145 mapi_errstr("MapiLogonEx for profileB", GetLastError());
149 /* Step 3. Open the stores */
150 mapi_object_init(&obj_storeA);
151 retval = OpenMsgStore(sessionA, &obj_storeA);
152 if (retval != MAPI_E_SUCCESS) {
153 mapi_errstr("OpenMsgStore profileA", GetLastError());
157 mapi_object_init(&obj_storeB);
158 retval = OpenMsgStore(sessionB, &obj_storeB);
159 if (retval != MAPI_E_SUCCESS) {
160 mapi_errstr("OpenMsgStore profileB", GetLastError());
164 /* Step 4. Register for notifications */
165 retval = RegisterNotification(sessionA, 0);
166 if (retval != MAPI_E_SUCCESS) {
167 mapi_errstr("RegisterNotification profileA", GetLastError());
171 retval = RegisterNotification(sessionB, 0);
172 if (retval != MAPI_E_SUCCESS) {
173 mapi_errstr("RegisterNotification profileB", GetLastError());
177 /* Step 5. Subscribe for newmail notifications */
178 retval = Subscribe(&obj_storeA, &ulConnectionA, fnevNewMail, true,
179 (mapi_notify_callback_t)callback, (void *) "profileA");
180 if (retval != MAPI_E_SUCCESS) {
181 mapi_errstr("Subscribe profileA", GetLastError());
185 retval = Subscribe(&obj_storeB, &ulConnectionB, fnevNewMail, true,
186 (mapi_notify_callback_t)callback, (void *) "profileB");
187 if (retval != MAPI_E_SUCCESS) {
188 mapi_errstr("Subscribe profileB", GetLastError());
192 /* Step 6. Create threads A and B and wait for notifications */
193 if (pthread_create(&pthreadA, NULL, monitor, (void *)&obj_storeA)) {
194 mapi_errstr("Thread creation for profile A failed", GetLastError());
198 if (pthread_create(&pthreadB, NULL, monitor, (void *)&obj_storeB)) {
199 mapi_errstr("Thread creation for profile B failed", GetLastError());
205 MAPIUninitialize(mapi_ctx);