expire-plugin.c revision 31a574fda352ef4f71dbff9c30e15e4744e132c0
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2012 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "lib.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "ioloop.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "array.h"
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen#include "str.h"
a1607f6001a9949e1cf9d49eb0aa936dbb4c77ffTimo Sirainen#include "master-service.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "dict.h"
00d58fcfe8191d6ce7efa801d289a5c0fe88d1aeTimo Sirainen#include "mail-namespace.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "index-mail.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "index-storage.h"
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen#include "expire-set.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include "expire-plugin.h"
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#include <stdlib.h>
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define EXPIRE_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, expire_storage_module)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define EXPIRE_MAIL_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, expire_mail_module)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#define EXPIRE_USER_CONTEXT(obj) \
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen MODULE_CONTEXT(obj, expire_mail_user_module)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstruct expire_mail_user {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen union mail_user_module_context module_ctx;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct dict *db;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen struct expire_set *set;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct expire_mailbox {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_module_context module_ctx;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct expire_transaction_context {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_transaction_module_context module_ctx;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen unsigned int saves:1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen unsigned int first_expunged:1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
4462bd7b4c7ef3de006f060e155a90e5de7cae21Timo Sirainenconst char *expire_plugin_version = DOVECOT_VERSION;
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(expire_storage_module,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen &mail_storage_module_register);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(expire_mail_module, &mail_module_register);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(expire_mail_user_module,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen &mail_user_module_register);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic struct mailbox_transaction_context *
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenexpire_mailbox_transaction_begin(struct mailbox *box,
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen enum mailbox_transaction_flags flags)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct mailbox_transaction_context *t;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen t = xpr_box->module_ctx.super.transaction_begin(box, flags);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen xt = i_new(struct expire_transaction_context, 1);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(t, expire_storage_module, xt);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return t;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainenstatic void first_nonexpunged_timestamp(struct mailbox_transaction_context *t,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen time_t *stamp_r)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen struct mail_index_view *view = t->view;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen const struct mail_index_header *hdr;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen struct mail *mail;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen uint32_t seq;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen mail = mail_alloc(t, 0, NULL);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* find the first non-expunged mail. we're here because the first
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen mail was expunged, so don't bother checking it. */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen hdr = mail_index_get_header(view);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen for (seq = 2; seq <= hdr->messages_count; seq++) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!mail_index_is_expunged(view, seq)) {
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen mail_set_seq(mail, seq);
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen if (mail_get_save_date(mail, stamp_r) == 0)
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen break;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen mail_free(&mail);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen if (seq > hdr->messages_count) {
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen /* everything expunged */
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen *stamp_r = 0;
e07bf3772a2bc075de4915ad0961beb8d083c22dTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainenstatic void first_save_timestamp(struct mailbox *box, time_t *stamp_r)
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen{
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen struct mailbox_transaction_context *t;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen const struct mail_index_header *hdr;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen struct mail *mail;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen *stamp_r = ioloop_time;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen t = mailbox_transaction_begin(box, 0);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen mail = mail_alloc(t, 0, NULL);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* find the first non-expunged mail. we're here because the first
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen mail was expunged, so don't bother checking it. */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen hdr = mail_index_get_header(box->view);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen if (hdr->messages_count > 0) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen mail_set_seq(mail, 1);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen (void)mail_get_save_date(mail, stamp_r);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen mail_free(&mail);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen (void)mailbox_transaction_commit(&t);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen}
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic int
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenexpire_mailbox_transaction_commit(struct mailbox_transaction_context *t,
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen struct mail_transaction_commit_changes *changes_r)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen struct mail_user *user = t->box->storage->user;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(user);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen struct mailbox *box = t->box;
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen time_t new_stamp = 0;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen bool update_dict = FALSE;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen int ret;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (xt->first_expunged) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* first mail expunged. dict needs updating. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen first_nonexpunged_timestamp(t, &new_stamp);
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen if (new_stamp == 0 && xt->saves) {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen /* everything was expunged, but also within this
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen transaction a new message was saved */
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen new_stamp = ioloop_time;
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen }
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen if (user->mail_debug) {
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen i_debug("expire: Expunging first message in %s, "
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen "updating timestamp to %ld",
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen box->vname, (long)new_stamp);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen update_dict = TRUE;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen if (xpr_box->module_ctx.super.transaction_commit(t, changes_r) < 0) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_free(xt);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return -1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen /* transaction is freed now */
d66be2bebfa96e7d3d20e2153f60e6e25dcc9a18Timo Sirainen t = NULL;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen if (xt->first_expunged || xt->saves) T_BEGIN {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen const char *key, *value;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen key = t_strconcat(DICT_EXPIRE_PREFIX,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen box->storage->user->username, "/",
5d49cbcf87354f0ddf3b71bc5f0cefdc02b14f68Timo Sirainen mailbox_get_vname(box), NULL);
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen if (xt->first_expunged) {
fd35227c47190afc832579ca5c76524792701bf7Timo Sirainen /* new_stamp is already set */
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen } else {
ce3faaaaab3e2d45b023396287e02f88e5c76e74Timo Sirainen i_assert(xt->saves);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen /* saved new mails. dict needs to be updated only if
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen this is the first mail in the database */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen ret = dict_lookup(euser->db, pool_datastack_create(),
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen key, &value);
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if (ret <= 0) {
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen /* first time saving here with expire enabled.
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen also handle lookup errors by just assuming
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen it didn't exist */
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if (ret < 0) {
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen i_warning("expire: dict lookup failed, "
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen "assuming update is needed");
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen }
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen first_save_timestamp(box, &new_stamp);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen update_dict = TRUE;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen } else if (strcmp(value, "0") == 0) {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* we're saving the first mail to this mailbox.
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen ioloop_time may not be exactly the first
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen message's save time, but a few seconds
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen difference doesn't matter */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen new_stamp = ioloop_time;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen update_dict = TRUE;
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen } else {
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen /* already exists */
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen }
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen if (user->mail_debug && update_dict) {
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen i_debug("expire: Saving first message to %s, "
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen "updating timestamp to %ld",
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen box->vname, (long)new_stamp);
2e263a9d901483a902720a30c474761bd3324fe8Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen if (update_dict) {
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen struct dict_transaction_context *dctx;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dctx = dict_transaction_begin(euser->db);
bbd4c4cf902539c25c471157eb9849459734759cTimo Sirainen dict_set(dctx, key, dec2str(new_stamp));
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen if (dict_transaction_commit(&dctx) < 0)
3e7565a7b39694bcdf448d8eb2a7f0774733297bTimo Sirainen i_error("expire: dict commit failed");
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_free(xt);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen return 0;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic void
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenexpire_mailbox_transaction_rollback(struct mailbox_transaction_context *t)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(t->box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt = EXPIRE_CONTEXT(t);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen xpr_box->module_ctx.super.transaction_rollback(t);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen i_free(xt);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void expire_mail_expunge(struct mail *_mail)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *xpr_mail = EXPIRE_MAIL_CONTEXT(mail);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt =
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen EXPIRE_CONTEXT(_mail->transaction);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen if (_mail->seq == 1) {
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen /* first mail expunged, database needs to be updated */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen xt->first_expunged = TRUE;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen xpr_mail->super.expunge(_mail);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainenstatic void expire_mail_allocated(struct mail *_mail)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(_mail->box);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_vfuncs *v = mail->vlast;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mail_module_context *xpr_mail;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen if (xpr_box == NULL)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen xpr_mail = p_new(mail->pool, union mail_module_context, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen xpr_mail->super = *v;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen mail->vlast = &xpr_mail->super;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->expunge = expire_mail_expunge;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET_SELF(mail, expire_mail_module, xpr_mail);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainenstatic int expire_save_finish(struct mail_save_context *ctx)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen struct expire_transaction_context *xt =
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen EXPIRE_CONTEXT(ctx->transaction);
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(ctx->transaction->box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen xt->saves = TRUE;
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen return xpr_box->module_ctx.super.save_finish(ctx);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstatic int
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainenexpire_copy(struct mail_save_context *ctx, struct mail *mail)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen struct expire_transaction_context *xt =
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen EXPIRE_CONTEXT(ctx->transaction);
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen struct expire_mailbox *xpr_box = EXPIRE_CONTEXT(ctx->transaction->box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cbc61fcb33b370d049c16a3c44568b4deb4e2b33Timo Sirainen xt->saves = TRUE;
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen return xpr_box->module_ctx.super.copy(ctx, mail);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic void expire_mailbox_allocate_init(struct mailbox *box)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mailbox_vfuncs *v = box->vlast;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_mailbox *xpr_box;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen xpr_box = p_new(box->pool, struct expire_mailbox, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen xpr_box->module_ctx.super = *v;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen box->vlast = &xpr_box->module_ctx.super;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_begin = expire_mailbox_transaction_begin;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_commit = expire_mailbox_transaction_commit;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->transaction_rollback = expire_mailbox_transaction_rollback;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->save_finish = expire_save_finish;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->copy = expire_copy;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT_SET(box, expire_storage_module, xpr_box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainenstatic void expire_mailbox_allocated(struct mailbox *box)
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen{
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen struct expire_mail_user *euser =
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen EXPIRE_USER_CONTEXT(box->storage->user);
56963ffad65b860c827553dfaf09fb766cb7e20eTimo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (euser != NULL && expire_set_lookup(euser->set, box->vname))
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen expire_mailbox_allocate_init(box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic void expire_mail_user_deinit(struct mail_user *user)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct expire_mail_user *euser = EXPIRE_USER_CONTEXT(user);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dict_deinit(&euser->db);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen expire_set_deinit(&euser->set);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen euser->module_ctx.super.deinit(user);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainenstatic const char *const *expire_get_patterns(struct mail_user *user)
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen{
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen ARRAY_TYPE(const_string) patterns;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *str;
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen char set_name[6+MAX_INT_STRLEN+1];
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen unsigned int i;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen t_array_init(&patterns, 16);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str = mail_user_set_plugin_getenv(user->set, "expire");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen for (i = 2; str != NULL; i++) {
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen array_append(&patterns, &str, 1);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen if (i_snprintf(set_name, sizeof(set_name), "expire%u", i) < 0)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen i_unreached();
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen str = mail_user_set_plugin_getenv(user->set, set_name);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen }
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen array_append_zero(&patterns);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen return array_idx(&patterns, 0);
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen}
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen
9514dbd41faad453406fc3a10aca791417a9ce75Timo Sirainenstatic void expire_mail_namespaces_created(struct mail_namespace *ns)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
9514dbd41faad453406fc3a10aca791417a9ce75Timo Sirainen struct mail_user *user = ns->user;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct expire_mail_user *euser;
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen const char *dict_uri;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen dict_uri = mail_user_plugin_getenv(user, "expire_dict");
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen if (mail_user_plugin_getenv(user, "expire") == NULL) {
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen if (user->mail_debug)
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen i_debug("expire: No expire setting - plugin disabled");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen } else if (dict_uri == NULL) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_error("expire plugin: expire_dict setting missing");
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen } else {
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen euser = p_new(user->pool, struct expire_mail_user, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen euser->module_ctx.super = *v;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen user->vlast = &euser->module_ctx.super;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->deinit = expire_mail_user_deinit;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
f6d57a2c182f63cd52819f0abb3c3d9f828afe19Timo Sirainen euser->set = expire_set_init(expire_get_patterns(user));
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen /* we're using only shared dictionary, the username
783278c012551bc2f25f065a8d3ec1a3cfc0d296Timo Sirainen doesn't matter. */
4073f0dbf3277f981a8fcee3b89ea15aaf380a7fTimo Sirainen euser->db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "",
4073f0dbf3277f981a8fcee3b89ea15aaf380a7fTimo Sirainen user->set->base_dir);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (euser->db == NULL)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_error("expire plugin: dict_init(%s) failed", dict_uri);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen else
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen MODULE_CONTEXT_SET(user, expire_mail_user_module, euser);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenstatic struct mail_storage_hooks expire_mail_storage_hooks = {
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen .mail_namespaces_created = expire_mail_namespaces_created,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen .mailbox_allocated = expire_mailbox_allocated,
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen .mail_allocated = expire_mail_allocated
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenvoid expire_plugin_init(struct module *module)
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen{
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen mail_storage_hooks_add(module, &expire_mail_storage_hooks);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenvoid expire_plugin_deinit(void)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen mail_storage_hooks_remove(&expire_mail_storage_hooks);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}