mail-log-plugin.c revision 5bd2cf0f30371cb0374b026322a6f52fdb20755f
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen (MAIL_LOG_EVENT_DELETE | MAIL_LOG_EVENT_UNDELETE | \
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MAIL_LOG_EVENT_EXPUNGE | MAIL_LOG_EVENT_SAVE | MAIL_LOG_EVENT_COPY | \
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen MAIL_LOG_EVENT_MAILBOX_DELETE | MAIL_LOG_EVENT_MAILBOX_RENAME)
7db932bd4934cd967eeae643300aef5b91caeaeaTimo Sirainenstatic const char *field_names[] = {
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenstatic const char *event_names[] = {
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen "mailbox_create",
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen "mailbox_delete",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "mailbox_rename",
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen "flag_change",
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen struct mail_log_message *messages, *messages_tail;
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mail_log_user_module,
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainenstatic enum mail_log_field mail_log_field_find(const char *name)
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen unsigned int i;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return 1 << i;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic enum mail_log_event mail_log_event_find(const char *name)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen unsigned int i;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* v1.x backwards compatibility */
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen return 1 << i;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenstatic enum mail_log_field mail_log_parse_fields(const char *str)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *const *tmp;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen for (tmp = t_strsplit_spaces(str, ", "); *tmp != NULL; tmp++) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen i_fatal("Unknown field in mail_log_fields: '%s'", *tmp);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic enum mail_log_event mail_log_parse_events(const char *str)
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen const char *const *tmp;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen for (tmp = t_strsplit_spaces(str, ", "); *tmp != NULL; tmp++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_fatal("Unknown event in mail_log_events: '%s'", *tmp);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void mail_log_mail_user_created(struct mail_user *user)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const char *str;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen muser = p_new(user->pool, struct mail_log_user, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MODULE_CONTEXT_SET(user, mail_log_user_module, muser);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen str = mail_user_plugin_getenv(user, "mail_log_fields");
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen muser->fields = str == NULL ? MAIL_LOG_DEFAULT_FIELDS :
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen str = mail_user_plugin_getenv(user, "mail_log_events");
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen muser->events = str == NULL ? MAIL_LOG_DEFAULT_EVENTS :
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainenstatic void mail_log_append_mailbox_name(string_t *str, struct mail *mail)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen str_sanitize(mailbox_str, MAILBOX_NAME_LOG_LEN));
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenmail_log_append_mail_header(string_t *str, struct mail *mail,
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen if (mail_get_first_header(mail, header, &value) <= 0)
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen str_printfa(str, "%s=%s", name, str_sanitize(value, HEADER_LOG_LEN));
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainenmail_log_append_uid(struct mail_log_mail_txn_context *ctx,
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen struct mail_log_message *msg, string_t *str, uint32_t uid)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* we don't know the uid yet, assign it later */
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen msg->pretext = p_strdup(ctx->pool, str_c(str));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmail_log_append_mail_message_real(struct mail_log_mail_txn_context *ctx,
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen MAIL_LOG_USER_CONTEXT(mail->box->storage->user);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen msg = p_new(ctx->pool, struct mail_log_message, 1);
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if ((muser->fields & MAIL_LOG_FIELD_BOX) != 0) {
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen if ((muser->fields & MAIL_LOG_FIELD_UID) != 0) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen mail_log_append_uid(ctx, msg, text, mail->uid);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen /* with mbox mail->uid contains the uid, but handle
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen this consistently with all mailbox formats */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if ((muser->fields & MAIL_LOG_FIELD_MSGID) != 0) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen mail_log_append_mail_header(text, mail, "msgid", "Message-ID");
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen if ((muser->fields & MAIL_LOG_FIELD_PSIZE) != 0) {
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen if ((muser->fields & MAIL_LOG_FIELD_VSIZE) != 0) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if ((muser->fields & MAIL_LOG_FIELD_FROM) != 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen mail_log_append_mail_header(text, mail, "from", "From");
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if ((muser->fields & MAIL_LOG_FIELD_SUBJECT) != 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen mail_log_append_mail_header(text, mail, "subject", "Subject");
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen if ((muser->fields & MAIL_LOG_FIELD_FLAGS) != 0) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen DLLIST2_APPEND(&ctx->messages, &ctx->messages_tail, msg);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenstatic void mail_log_add_dummy_msg(struct mail_log_mail_txn_context *ctx,
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen msg = p_new(ctx->pool, struct mail_log_message, 1);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen DLLIST2_APPEND(&ctx->messages, &ctx->messages_tail, msg);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenmail_log_append_mail_message(struct mail_log_mail_txn_context *ctx,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen MAIL_LOG_USER_CONTEXT(mail->box->storage->user);
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainen mail_log_append_mail_message_real(ctx, mail, event, desc);
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainenmail_log_mail_transaction_begin(struct mailbox_transaction_context *t ATTR_UNUSED)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen pool = pool_alloconly_create("mail-log", 2048);
3e25b17126e9536736d5da03697613e4c3af5f76Timo Sirainen ctx = p_new(pool, struct mail_log_mail_txn_context, 1);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void mail_log_mail_save(void *txn, struct mail *mail)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_log_append_mail_message(ctx, mail, MAIL_LOG_EVENT_SAVE, "save");
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainenstatic void mail_log_mail_copy(void *txn, struct mail *src, struct mail *dst)
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen if (strcmp(src->box->storage->name, "raw") == 0) {
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen /* special case: lda/lmtp is saving a mail */
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen mail_log_append_mail_message(ctx, dst, MAIL_LOG_EVENT_COPY, desc);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenstatic void mail_log_mail_expunge(void *txn, struct mail *mail)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_log_append_mail_message(ctx, mail, MAIL_LOG_EVENT_EXPUNGE,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic void mail_log_mail_update_flags(void *txn, struct mail *mail,
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen enum mail_flags new_flags = mail_get_flags(mail);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (((old_flags ^ new_flags) & MAIL_DELETED) == 0) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "flag_change");
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen mail_log_append_mail_message(ctx, mail, MAIL_LOG_EVENT_DELETE,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_log_append_mail_message(ctx, mail, MAIL_LOG_EVENT_UNDELETE,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmail_log_mail_update_keywords(void *txn, struct mail *mail,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_log_append_mail_message(ctx, mail, MAIL_LOG_EVENT_FLAG_CHANGE,
f4bbeadda12fbd7c219063db68f3e78646d83c2cTimo Sirainen "flag_change");
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainenstatic void mail_log_save(const struct mail_log_message *msg, uint32_t uid)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen /* not logging this save/copy */
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen else if (uid != 0)
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen i_info("%s%u%s", msg->pretext, uid, msg->text);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen struct mail_transaction_commit_changes *changes)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen unsigned int n = 0;
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen seq_range_array_iter_init(&iter, &changes->saved_uids);
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen for (msg = ctx->messages; msg != NULL; msg = msg->next) {
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen if (!seq_range_array_iter_nth(&iter, n++, &uid))
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainenstatic void mail_log_mail_transaction_rollback(void *txn)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen struct mail_log_user *muser = MAIL_LOG_USER_CONTEXT(box->storage->user);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if ((muser->events & MAIL_LOG_EVENT_MAILBOX_CREATE) == 0)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen str_sanitize(box->name, MAILBOX_NAME_LOG_LEN));
14175321ddb88619015866978c05a27786ca4814Timo Sirainenmail_log_mailbox_delete_commit(void *txn ATTR_UNUSED, struct mailbox *box)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen struct mail_log_user *muser = MAIL_LOG_USER_CONTEXT(box->storage->user);
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if ((muser->events & MAIL_LOG_EVENT_MAILBOX_DELETE) == 0)
14175321ddb88619015866978c05a27786ca4814Timo Sirainen str_sanitize(box->name, MAILBOX_NAME_LOG_LEN));
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen struct mailbox *dest, bool rename_children ATTR_UNUSED)
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen struct mail_log_user *muser = MAIL_LOG_USER_CONTEXT(src->storage->user);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen if ((muser->events & MAIL_LOG_EVENT_MAILBOX_RENAME) == 0)
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen str_sanitize(src->name, MAILBOX_NAME_LOG_LEN),
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen str_sanitize(dest->name, MAILBOX_NAME_LOG_LEN));
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainenstatic const struct notify_vfuncs mail_log_vfuncs = {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen .mail_transaction_begin = mail_log_mail_transaction_begin,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen .mail_update_flags = mail_log_mail_update_flags,
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen .mail_update_keywords = mail_log_mail_update_keywords,
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen .mail_transaction_commit = mail_log_mail_transaction_commit,
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen .mail_transaction_rollback = mail_log_mail_transaction_rollback,
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen .mailbox_delete_commit = mail_log_mailbox_delete_commit,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenstatic struct mail_storage_hooks mail_log_mail_storage_hooks = {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen .mail_user_created = mail_log_mail_user_created
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenvoid mail_log_plugin_init(struct module *module)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen mail_log_ctx = notify_register(&mail_log_vfuncs);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen mail_storage_hooks_add(module, &mail_log_mail_storage_hooks);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen mail_storage_hooks_remove(&mail_log_mail_storage_hooks);
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainenconst char *mail_log_plugin_dependencies[] = { "notify", NULL };