/* Copyright (C) 2010 Timo Sirainen, LGPLv2.1 */ /* Note: a pretty evil way to change the header value, but should work. export DOVECOT=~/cvs/dovecot-2.0 gcc -fPIC -shared -g -Wall -I$DOVECOT -I$DOVECOT/src/lib \ -I$DOVECOT/src/lib-storage -I$DOVECOT/src/lib-mail \ -I$DOVECOT/src/lib-imap -I$DOVECOT/src/lib-index -DHAVE_CONFIG_H \ modify-plugin.c -o modify_plugin.so */ #include "lib.h" #include "str.h" #include "istream.h" #include "istream-header-filter.h" #include "message-header-parser.h" #include "mail-storage-private.h" #define MODIFY_CONTEXT(obj) \ MODULE_CONTEXT(obj, modify_storage_module) static MODULE_CONTEXT_DEFINE_INIT(modify_storage_module, &mail_storage_module_register); static int modify_mailbox_open(struct mailbox *box) { union mailbox_module_context *zbox = MODIFY_CONTEXT(box); if (zbox->super.open(box) < 0) return -1; if (strcmp(box->name, "spam") == 0) { /* force copying to go through mail_save_begin() */ box->disable_reflink_copy_to = TRUE; } return 0; } static void filter_callback(struct message_header_line *hdr, bool *matched, void *context) { string_t *str; if (hdr == NULL || strcasecmp(hdr->name, "subject") != 0) return; str = t_str_new(128); str_append_n(str, hdr->value, hdr->value_len); str_append(str, " (hello world)"); hdr->value = str_data(str); hdr->value_len = str_len(str); } struct istream *create_modifier_stream(struct istream *input) { return i_stream_create_header_filter(input, HEADER_FILTER_EXCLUDE, NULL, 0, filter_callback, NULL); } static int modify_mail_save_begin(struct mail_save_context *ctx, struct istream *input) { struct mailbox_transaction_context *t = ctx->transaction; union mailbox_module_context *zbox = MODIFY_CONTEXT(t->box); struct istream *new_input; if (strcmp(t->box->name, "spam") == 0) { new_input = create_modifier_stream(input); i_stream_unref(&input); input = new_input; } return zbox->super.save_begin(ctx, input); } static void modify_mailbox_allocated(struct mailbox *box) { struct mailbox_vfuncs *v = box->vlast; union mailbox_module_context *zbox; zbox = p_new(box->pool, union mailbox_module_context, 1); zbox->super = *v; box->vlast = &zbox->super; v->open = modify_mailbox_open; v->save_begin = modify_mail_save_begin; MODULE_CONTEXT_SET_SELF(box, modify_storage_module, zbox); } static struct mail_storage_hooks modify_mail_storage_hooks = { .mailbox_allocated = modify_mailbox_allocated }; void modify_plugin_init(struct module *module); void modify_plugin_deinit(void); void modify_plugin_init(struct module *module) { mail_storage_hooks_add(module, &modify_mail_storage_hooks); } void modify_plugin_deinit(void) { mail_storage_hooks_remove(&modify_mail_storage_hooks); }