mail-log-plugin.c revision 70ed959d547ae7ff8bbe14c30c45caca3b43322c
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen/* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen MODULE_CONTEXT(obj, mail_log_mailbox_list_module)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#define MAIL_LOG_DEFAULT_EVENTS MAIL_LOG_EVENT_MASK_ALL
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic const char *field_names[] = {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic const char *event_names[] = {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "mailbox_delete",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen union mailbox_transaction_module_context module_ctx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ARRAY_DEFINE(group_changes, struct mail_log_group_changes);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int changes;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenconst char *mail_log_plugin_version = PACKAGE_VERSION;
ce89e2964b6bc4925d2dd690417200a110d041c5Timo Sirainenstatic void (*mail_log_next_hook_mail_storage_created)
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainenstatic void (*mail_log_next_hook_mailbox_list_created)
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_storage_module,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_mail_module, &mail_module_register);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_mailbox_list_module,
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainenstatic enum mail_log_field mail_log_field_find(const char *name)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int i;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 1 << i;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic enum mail_log_event mail_log_event_find(const char *name)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen unsigned int i;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return 1 << i;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic const char *mail_log_event_get_name(enum mail_log_event event)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int i;
bd354c19cb93c07ade79477674328a54146ea332Timo Sirainenmail_log_action_get_group(struct mail_log_transaction_context *lt,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen unsigned int i, count;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen p_array_init(<->group_changes, lt->pool, 8);
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen group = array_get_modifiable(<->group_changes, &count);
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen for (i = 0; i < count; i++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen group = array_append_space(<->group_changes);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenmail_log_action_add_group(struct mail_log_transaction_context *lt,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen group = mail_log_action_get_group(lt, event, data);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen seq_range_array_add(&group->uids, 0, mail->uid);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic void mail_log_append_mailbox_name(string_t *str, struct mailbox *box)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* most operations are for INBOX, and POP3 has only INBOX,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen so don't add it. */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_sanitize(mailbox_str, MAILBOX_NAME_LOG_LEN));
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenmail_log_group(struct mailbox *box, const struct mail_log_group_changes *group)
2efe0618b62fb1e3cd41a692f02d674a54c7720eTimo Sirainen unsigned int i, count;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen str_printfa(str, "%s: ", mail_log_event_get_name(group->event));
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0 &&
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen for (i = 0; i < count; i++) {
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_printfa(str, "size=%"PRIuUOFF_T", ", group->psize_total);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen str_printfa(str, "size=%"PRIuUOFF_T", ", group->vsize_total);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen unsigned int i, count;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen group = array_get(<->group_changes, &count);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; i < count; i++) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void mail_log_action(struct mailbox_transaction_context *dest_trans,
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(dest_trans);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen pool = pool_alloconly_create("mail log transaction", 1024);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen lt = p_new(pool, struct mail_log_transaction_context, 1);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen MODULE_CONTEXT_SET(dest_trans, mail_log_storage_module, lt);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen mail_log_action_add_group(lt, mail, event, data);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_printfa(str, "%s: ", mail_log_event_get_name(event));
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_UID) != 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_BOX) != 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_MSGID) != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (mail_get_first_header(mail, "Message-ID", &msgid) <= 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_PSIZE) != 0 &&
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_printfa(str, "size=%"PRIuUOFF_T", ", size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((mail_log_set.fields & MAIL_LOG_FIELD_VSIZE) != 0 &&
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (event & (MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_COPY)) != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen str_printfa(str, "vsize=%"PRIuUOFF_T", ", size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic void mail_log_mail_expunge(struct mail *_mail)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenmail_log_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen lmail->super.update_flags(_mail, modify_type, flags);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) == 0)
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainenstatic struct mail *
c1ebcdad1b4d950eb22219704dd9d64a89d0568fTimo Sirainenmail_log_mail_alloc(struct mailbox_transaction_context *t,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen _mail = lbox->super.mail_alloc(t, wanted_fields, wanted_headers);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen lmail = p_new(mail->pool, union mail_module_context, 1);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail->v.update_flags = mail_log_mail_update_flags;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, mail_log_mail_module, lmail);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenmail_log_copy(struct mailbox_transaction_context *t, struct mail *mail,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen enum mail_flags flags, struct mail_keywords *keywords,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (lbox->super.copy(t, mail, flags, keywords, dest_mail) < 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_log_action(t, mail, MAIL_LOG_EVENT_COPY, name);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenmail_log_transaction_commit(struct mailbox_transaction_context *t,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_log_transaction_context *lt = MAIL_LOG_CONTEXT(t);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen union mailbox_module_context *lbox = MAIL_LOG_CONTEXT(t->box);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (lt->changes > 0 && mail_log_set.group_events)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return lbox->super.transaction_commit(t, uid_validity_r,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenmail_log_transaction_rollback(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)