2
OpenChange Service Manager Plugin for Dovecot
6
Copyright (C) Julien Kerihuel 2011.
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
Step 1. Compile the plugin
24
gcc -fPIC -shared -DHAVE_CONFIG_H `echo $DOVECOT_CFLAGS $LIBDOVECOT_INCLUDE $LIBDOVECOT_STORAGE_INCLUDE` ocsmanager-plugin.c -L/usr/lib/dovecot/modules/ -l15_notify_plugin -o ocsmanager_plugin.so
26
Step 2: Install the plugin
27
sudo cp ocsmanager_plugin.so /usr/lib/dovecot/modules/ocsmanager_plugin.so
29
Step 3: Configure ocsmanager plugin options in dovecot.conf
31
ocsmanager_backend = SOGo
32
ocsmanager_newmail = /home/openchange/openchange/sogo-good/mapiproxy/services/client/newmail.py
33
ocsmanager_config = /home/openchange/openchange/sogo-good/mapiproxy/services/client/ocsmanager.cfg
36
Step 4: Restart dovecot
39
#include "ocsmanager-plugin.h"
41
#define OCSMANAGER_USER_CONTEXT(obj) \
42
MODULE_CONTEXT(obj, ocsmanager_user_module)
44
enum ocsmanager_field {
45
OCSMANAGER_FIELD_UID = 0x1,
46
OCSMANAGER_FIELD_BOX = 0x2,
47
OCSMANAGER_FIELD_MSGID = 0x4,
48
OCSMANAGER_FIELD_PSIZE = 0x8,
49
OCSMANAGER_FIELD_VSIZE = 0x10,
50
OCSMANAGER_FIELD_FLAGS = 0x20,
51
OCSMANAGER_FIELD_FROM = 0x40,
52
OCSMANAGER_FIELD_SUBJECT = 0x80
55
#define OCSMANAGER_DEFAULT_FIELDS \
56
(OCSMANAGER_FIELD_UID | OCSMANAGER_FIELD_BOX | \
57
OCSMANAGER_FIELD_MSGID | OCSMANAGER_FIELD_PSIZE)
59
enum ocsmanager_event {
60
OCSMANAGER_EVENT_DELETE = 0x1,
61
OCSMANAGER_EVENT_UNDELETE = 0x2,
62
OCSMANAGER_EVENT_EXPUNGE = 0x4,
63
OCSMANAGER_EVENT_SAVE = 0x8,
64
OCSMANAGER_EVENT_COPY = 0x10,
65
OCSMANAGER_EVENT_MAILBOX_CREATE = 0x20,
66
OCSMANAGER_EVENT_MAILBOX_DELETE = 0x40,
67
OCSMANAGER_EVENT_MAILBOX_RENAME = 0x80,
68
OCSMANAGER_EVENT_FLAG_CHANGE = 0x100
71
#define OCSMANAGER_DEFAULT_EVENTS (OCSMANAGER_EVENT_SAVE)
73
struct ocsmanager_user {
74
union mail_user_module_context module_ctx;
75
enum ocsmanager_field fields;
76
enum ocsmanager_event events;
83
struct ocsmanager_message {
84
struct ocsmanager_message *prev;
85
struct ocsmanager_message *next;
86
enum ocsmanager_event event;
89
char *destination_folder;
96
struct ocsmanager_mail_txn_context {
98
struct ocsmanager_message *messages;
99
struct ocsmanager_message *messages_tail;
102
static MODULE_CONTEXT_DEFINE_INIT(ocsmanager_user_module,
103
&mail_user_module_register);
105
static void ocsmanager_mail_user_created(struct mail_user *user)
107
struct ocsmanager_user *ocsuser;
110
i_debug("ocsmanager_mail_user_created");
111
i_debug("username = %s", user->username);
113
ocsuser = p_new(user->pool, struct ocsmanager_user, 1);
114
MODULE_CONTEXT_SET(user, ocsmanager_user_module, ocsuser);
116
ocsuser->fields = OCSMANAGER_DEFAULT_FIELDS;
117
ocsuser->events = OCSMANAGER_DEFAULT_EVENTS;
118
ocsuser->username = p_strdup(user->pool, user->username);
119
str = mail_user_plugin_getenv(user, "ocsmanager_backend");
121
i_fatal("Missing ocsmanager_backend parameter in dovecot.conf");
123
ocsuser->backend = str;
125
str = mail_user_plugin_getenv(user, "ocsmanager_newmail");
127
i_fatal("Missing ocsmanager_newmail parameter in dovecot.conf");
131
str = mail_user_plugin_getenv(user, "ocsmanager_config");
133
i_fatal("Missing ocsmanager_config parameter in dovecot.conf");
135
ocsuser->config = str;
138
static void ocsmanager_mail_save(void *txn, struct mail *mail)
140
i_debug("ocsmanager_mail_save");
141
i_debug("message UID = %d\n", mail->uid);
144
static void ocsmanager_mail_copy(void *txn, struct mail *src, struct mail *dst)
146
struct ocsmanager_mail_txn_context *ctx = (struct ocsmanager_mail_txn_context *) txn;
147
struct ocsmanager_user *mctx = OCSMANAGER_USER_CONTEXT(dst->box->storage->user);
148
struct ocsmanager_message *msg;
151
if (strcmp(src->box->storage->name, "raw") == 0) {
152
/* special case: lda/lmtp is saving a mail */
153
msg = p_new(ctx->pool, struct ocsmanager_message, 1);
154
msg->event = OCSMANAGER_EVENT_COPY;
156
msg->username = p_strdup(ctx->pool, mctx->username);
157
msg->backend = p_strdup(ctx->pool, mctx->backend);
158
msg->destination_folder = p_strdup(ctx->pool, mailbox_get_name(dst->box));
159
msg->bin = p_strdup(ctx->pool, mctx->bin);
160
msg->config = p_strdup(ctx->pool, mctx->config);
162
/* FIXME: Quick hack of the night */
163
msg->username[0] = toupper(msg->username[0]);
164
for (i = 0; i < strlen(msg->destination_folder); i++) {
165
msg->destination_folder[i] = tolower(msg->destination_folder[i]);
168
DLLIST2_APPEND(&ctx->messages, &ctx->messages_tail, msg);
172
static void *ocsmanager_mail_transaction_begin(struct mailbox_transaction_context *t ATTR_UNUSED)
175
struct ocsmanager_mail_txn_context *ctx;
177
pool = pool_alloconly_create("ocsmanager", 2048);
178
ctx = p_new(pool, struct ocsmanager_mail_txn_context, 1);
184
static void ocsmanager_mail_transaction_commit(void *txn,
185
struct mail_transaction_commit_changes *changes)
187
struct ocsmanager_mail_txn_context *ctx = (struct ocsmanager_mail_txn_context *)txn;
189
struct ocsmanager_message *msg;
191
struct seq_range_iter iter;
194
seq_range_array_iter_init(&iter, &changes->saved_uids);
195
for (msg = ctx->messages; msg != NULL; msg = msg->next) {
196
if (msg->event == OCSMANAGER_EVENT_COPY) {
197
if (!seq_range_array_iter_nth(&iter, n++, &uid)) uid = 0;
200
i_debug("# uid = %d", msg->uid);
201
i_debug("# folder = %s", msg->destination_folder);
202
i_debug("# username = %s", msg->username);
203
i_debug("# backend = %s", msg->backend);
205
/* FIXME: I'm ashamed but I'm tired */
206
command = p_strdup_printf(ctx->pool, "python %s --config %s --backend %s --user %s --folder %s --msgid %d", msg->bin, msg->config, msg->backend, msg->username, msg->destination_folder, msg->uid);
210
i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
212
pool_unref(&ctx->pool);
215
static void ocsmanager_mail_transaction_rollback(void *txn)
217
struct ocsmanager_mail_txn_context *ctx = (struct ocsmanager_mail_txn_context *) txn;
219
pool_unref(&ctx->pool);
222
static const struct notify_vfuncs ocsmanager_vfuncs = {
223
.mail_transaction_begin = ocsmanager_mail_transaction_begin,
224
.mail_save = ocsmanager_mail_save,
225
.mail_copy = ocsmanager_mail_copy,
226
.mail_transaction_commit = ocsmanager_mail_transaction_commit,
227
.mail_transaction_rollback = ocsmanager_mail_transaction_rollback,
230
static struct notify_context *ocsmanager_ctx;
232
static struct mail_storage_hooks ocsmanager_mail_storage_hooks = {
233
.mail_user_created = ocsmanager_mail_user_created
236
void ocsmanager_plugin_init(struct module *module)
238
i_debug("oscmanager_plugin_init");
239
ocsmanager_ctx = notify_register(&ocsmanager_vfuncs);
240
mail_storage_hooks_add(module, &ocsmanager_mail_storage_hooks);
243
void ocsmanager_plugin_deinit(void)
245
i_debug("oscmanager_plugin_deinit");
246
mail_storage_hooks_remove(&ocsmanager_mail_storage_hooks);
247
notify_unregister(ocsmanager_ctx);
250
const char *ocsmanager_plugin_dependencies[] = { "notify", NULL };