mail-log-plugin.c revision 1f6c210c30992e95b806d2f517e2b3625ed941c5
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MODULE_CONTEXT(obj, mail_log_mailbox_list_module)
e237ebeb97f42950eef3efd0d3db85590160d5fbTimo Sirainen (MAIL_LOG_EVENT_DELETE | MAIL_LOG_EVENT_UNDELETE | \
e237ebeb97f42950eef3efd0d3db85590160d5fbTimo Sirainen MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY | \
e237ebeb97f42950eef3efd0d3db85590160d5fbTimo Sirainen MAIL_LOG_EVENT_MAILBOX_DELETE | MAIL_LOG_EVENT_MAILBOX_RENAME)
e237ebeb97f42950eef3efd0d3db85590160d5fbTimo Sirainenstatic const char *field_names[] = {
e237ebeb97f42950eef3efd0d3db85590160d5fbTimo Sirainenstatic const char *event_names[] = {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "mailbox_delete",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "mailbox_rename",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "flag_change",
e237ebeb97f42950eef3efd0d3db85590160d5fbTimo Sirainen union mailbox_transaction_module_context module_ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ARRAY_DEFINE(group_changes, struct mail_log_group_changes);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int changes;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconst char *mail_log_plugin_version = PACKAGE_VERSION;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void (*mail_log_next_hook_mail_storage_created)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void (*mail_log_next_hook_mailbox_list_created)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_storage_module,
e2bdacc34dde56aa664059ab56e8b77e82bd1805Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_mail_module, &mail_module_register);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_mailbox_list_module,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic enum mail_log_field mail_log_field_find(const char *name)
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen unsigned int i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 1 << i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic enum mail_log_event mail_log_event_find(const char *name)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 1 << i;
5e702db5540b2303e25554dee21bbf35a4813381Timo Sirainenstatic const char *mail_log_event_get_name(enum mail_log_event event)
46908da82cd45dd90ca7e438c8453bc9669868ecTimo Sirainen unsigned int i;
0001f76bf725c5cf403bade8556f142dd43144eeTimo Sirainenmail_log_action_get_group(struct mail_log_transaction_context *lt,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i, count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen p_array_init(<->group_changes, lt->pool, 8);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen group = array_get_modifiable(<->group_changes, &count);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < count; i++) {
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen group = array_append_space(<->group_changes);
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainenmail_log_action_add_group(struct mail_log_transaction_context *lt,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen group = mail_log_action_get_group(lt, event, data);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen seq_range_array_add(&group->uids, 0, mail->uid);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
e6440616c02bb1404dc35debf45d9741260c7831Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mail_log_append_mailbox_name(string_t *str, struct mailbox *box)
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen /* most operations are for INBOX, and POP3 has only INBOX,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen so don't add it. */
06eb8c1371aa06478d8840b1373cab7c2752d5edTimo Sirainen str_sanitize(mailbox_str, MAILBOX_NAME_LOG_LEN));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmail_log_group(struct mailbox *box, const struct mail_log_group_changes *group)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i, count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, "%s: ", mail_log_event_get_name(group->event));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; i < count; i++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen str_printfa(str, "size=%"PRIuUOFF_T", ", group->psize_total);
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen str_printfa(str, "size=%"PRIuUOFF_T", ", group->vsize_total);
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen unsigned int i, count;
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen group = array_get(<->group_changes, &count);
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen for (i = 0; i < count; i++) {
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainenstatic void mail_log_add_hdr(struct mail *mail, string_t *str,
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen if (mail_get_first_header(mail, header, &value) <= 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen str_printfa(str, "%s=%s, ", name, str_sanitize(value, HEADER_LOG_LEN));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mail_log_action(struct mailbox_transaction_context *dest_trans,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(dest_trans);
f1612f8421207632e1dc9addd6c23e7f7098a54cTimo Sirainen mail_log_action_add_group(lt, mail, event, data);
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen str_printfa(str, "%s: ", mail_log_event_get_name(event));
f71c2d4e6b802bf8e622bcd5df29286262d05d5aTimo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 && mail->uid != 0)
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_FLAGS) != 0) {
3c40cf45bb10548bf434aea0fca32b99acc99a35Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0)
3c40cf45bb10548bf434aea0fca32b99acc99a35Timo Sirainen mail_log_add_hdr(mail, str, "msgid", "Message-ID");
3c40cf45bb10548bf434aea0fca32b99acc99a35Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_FROM) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_SUBJECT) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_log_add_hdr(mail, str, "subject", "Subject");
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
fb5efc6ed69da679d9da31ef62daa7024de18212Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
5833a4972491fdb7b78eac2280f31dc4b9fa2bb7Timo Sirainen str_printfa(str, "size=%"PRIuUOFF_T", ", size);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen str_printfa(str, "vsize=%"PRIuUOFF_T", ", size);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mail_log_mail_expunge(struct mail *_mail)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmail_log_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen lmail->super.update_flags(_mail, modify_type, flags);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) != 0) T_BEGIN {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if ((old_flags & ~MAIL_DELETED) != (new_flags & ~MAIL_DELETED)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmail_log_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen const char *const *old_keywords, *const *new_keywords;
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen unsigned int i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen lmail->super.update_keywords(_mail, modify_type, keywords);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; old_keywords[i] != NULL && new_keywords[i] != NULL; i++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(old_keywords[i], new_keywords[i]) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (old_keywords[i] != NULL || new_keywords[i] != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct mail *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmail_log_mail_alloc(struct mailbox_transaction_context *t,
553cf4f8a8850efffdc714ec1d1ae45a5fc7905dTimo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen _mail = lbox->super.mail_alloc(t, wanted_fields, wanted_headers);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen lmail = p_new(mail->pool, union mail_module_context, 1);
08df28a63b3efb0f0ee30c3e7ef44c0a1e7bb459Timo Sirainen mail->v.update_flags = mail_log_mail_update_flags;
08df28a63b3efb0f0ee30c3e7ef44c0a1e7bb459Timo Sirainen mail->v.update_keywords = mail_log_mail_update_keywords;
08df28a63b3efb0f0ee30c3e7ef44c0a1e7bb459Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, mail_log_mail_module, lmail);
553cf4f8a8850efffdc714ec1d1ae45a5fc7905dTimo Sirainenmail_log_copy(struct mailbox_transaction_context *t, struct mail *mail,
553cf4f8a8850efffdc714ec1d1ae45a5fc7905dTimo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
61279c3c77aa4a6f8d1de82b468ab01b14418318Timo Sirainen union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
553cf4f8a8850efffdc714ec1d1ae45a5fc7905dTimo Sirainen if (lbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_log_action(t, mail, MAIL_LOG_EVENT_COPY, name);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmail_log_save_begin(struct mail_save_context *ctx, struct istream *input)
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen lt->tmp_mail = mail_alloc(ctx->transaction, 0, NULL);
T_BEGIN {
} T_END;
static struct mailbox_transaction_context *
struct mailbox_transaction_context *t;
static struct mailbox *
return NULL;
return box;
const char *newname)
const char *const *tmp;
if (field == 0)
return fields;
const char *const *tmp;
if (event == 0)
return events;
const char *str;
void mail_log_plugin_init(void)
void mail_log_plugin_deinit(void)