bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen/* There are several race conditions in this plugin, but they should be
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen happening pretty rarely and usually it's not a big problem if the results
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen are temporarily wrong. Fixing the races would likely be a lot of work,
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen so it's not really worth it. */
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo 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
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen#define EXPIRE_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, expire_storage_module)
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi#define EXPIRE_CONTEXT_REQUIRE(obj) \
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi MODULE_CONTEXT_REQUIRE(obj, expire_storage_module)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#define EXPIRE_MAIL_CONTEXT(obj) \
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi MODULE_CONTEXT_REQUIRE(obj, expire_mail_module)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen#define EXPIRE_USER_CONTEXT(obj) \
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi MODULE_CONTEXT_REQUIRE(obj, expire_mail_user_module)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainenstruct expire_mail_index_header {
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen uint32_t timestamp;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen};
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo 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;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen bool expire_cache;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct expire_mailbox {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_module_context module_ctx;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen uint32_t expire_ext_id;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainenstruct expire_transaction_context {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen union mailbox_transaction_module_context module_ctx;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool saves:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool first_expunged:1;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen};
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *expire_plugin_version = DOVECOT_ABI_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,
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi enum mailbox_transaction_flags flags,
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi const char *reason)
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen{
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_mailbox *xpr_box = EXPIRE_CONTEXT_REQUIRE(box);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct mailbox_transaction_context *t;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen struct expire_transaction_context *xt;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi t = xpr_box->module_ctx.super.transaction_begin(box, flags, reason);
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
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainenstatic void first_save_timestamp(struct mailbox *box, time_t *stamp_r)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen{
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct mailbox_transaction_context *t;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen const struct mail_index_header *hdr;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct mail *mail;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen *stamp_r = ioloop_time;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi t = mailbox_transaction_begin(box, 0, __func__);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail = mail_alloc(t, 0, NULL);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen /* find the first non-expunged mail. we're here because the first
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail was expunged, so don't bother checking it. */
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen hdr = mail_index_get_header(box->view);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (hdr->messages_count > 0) {
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail_set_seq(mail, 1);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen (void)mail_get_save_date(mail, stamp_r);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen }
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail_free(&mail);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen (void)mailbox_transaction_commit(&t);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen}
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainenstatic uint32_t expire_get_ext_id(struct mailbox *box)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen{
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_mailbox *xpr_box = EXPIRE_CONTEXT_REQUIRE(box);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (xpr_box->expire_ext_id != (uint32_t)-1)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return xpr_box->expire_ext_id;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen xpr_box->expire_ext_id =
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail_index_ext_register(box->index, "expire",
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen sizeof(struct expire_mail_index_header), 0, 0);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return xpr_box->expire_ext_id;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen}
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainenstatic int expire_lookup(struct mailbox *box, const char *key,
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen time_t *new_stamp_r)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen{
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct expire_mail_user *euser =
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen EXPIRE_USER_CONTEXT(box->storage->user);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen const struct expire_mail_index_header *hdr;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen const void *data;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen size_t data_size;
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen const char *value, *error;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen int ret;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen /* default to ioloop_time for newly saved mails. it may not be exactly
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen the first message's save time, but a few seconds difference doesn't
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen matter */
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen *new_stamp_r = ioloop_time;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (euser->expire_cache) {
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail_index_get_header_ext(box->view, expire_get_ext_id(box),
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen &data, &data_size);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (data_size == sizeof(*hdr)) {
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen hdr = data;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (hdr->timestamp == 0)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return 0;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen /* preserve the original timestamp */
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen *new_stamp_r = hdr->timestamp;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return 1;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen }
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen /* cache doesn't exist yet */
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen }
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen ret = dict_lookup(euser->db, pool_datastack_create(),
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen key, &value, &error);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (ret <= 0) {
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen if (ret < 0) {
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen i_error("expire: dict_lookup(%s) failed: %s", key, error);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return -1;
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen }
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen first_save_timestamp(box, new_stamp_r);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return 0;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen }
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen return strcmp(value, "0") != 0 ? 1 : 0;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen}
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainenstatic void
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainenexpire_update(struct mailbox *box, const char *key, time_t timestamp)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen{
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct expire_mail_user *euser =
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen EXPIRE_USER_CONTEXT(box->storage->user);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct dict_transaction_context *dctx;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct mail_index_transaction *trans;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen struct expire_mail_index_header hdr;
661998e2ccd772ad92a9d4a75cb712692a8c94b3Timo Sirainen const char *error;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen dctx = dict_transaction_begin(euser->db);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen dict_set(dctx, key, dec2str(timestamp));
661998e2ccd772ad92a9d4a75cb712692a8c94b3Timo Sirainen if (dict_transaction_commit(&dctx, &error) < 0)
661998e2ccd772ad92a9d4a75cb712692a8c94b3Timo Sirainen i_error("expire: dict commit failed: %s", error);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen else if (euser->expire_cache) {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&hdr);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen hdr.timestamp = timestamp;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen trans = mail_index_transaction_begin(box->view,
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen mail_index_update_header_ext(trans, expire_get_ext_id(box),
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen 0, &hdr, sizeof(hdr));
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (mail_index_transaction_commit(&trans) < 0)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen i_error("expire: index transaction commit failed");
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen }
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen}
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo 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
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;
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_mailbox *xpr_box = EXPIRE_CONTEXT_REQUIRE(t->box);
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_transaction_context *xt = EXPIRE_CONTEXT_REQUIRE(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 {
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen const char *key;
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 */
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen ret = expire_lookup(box, key, &new_stamp);
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 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
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen if (update_dict)
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen expire_update(box, key, new_stamp);
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{
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_mailbox *xpr_box = EXPIRE_CONTEXT_REQUIRE(t->box);
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_transaction_context *xt = EXPIRE_CONTEXT_REQUIRE(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 =
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi EXPIRE_CONTEXT_REQUIRE(_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 =
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi EXPIRE_CONTEXT_REQUIRE(ctx->transaction);
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_mailbox *xpr_box = EXPIRE_CONTEXT_REQUIRE(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 =
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi EXPIRE_CONTEXT_REQUIRE(ctx->transaction);
de9dea4ff806dcdd471fb340c41b0eb57a6b56deAki Tuomi struct expire_mailbox *xpr_box = EXPIRE_CONTEXT_REQUIRE(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;
b78bed724fad909bf84008a3eb0f35b5a4379c39Timo Sirainen xpr_box->expire_ext_id = (uint32_t)-1;
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
17ac264fe7efd383f10c67548cadcc5aca505b92Timo Sirainenstatic void expire_mail_user_created(struct mail_user *user)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct expire_mail_user *euser;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen struct dict_settings dict_set;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen struct dict *db;
eca38954bcf972618f6b85932a3690acbd2b673aTimo Sirainen const char *dict_uri, *error;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang if (!mail_user_plugin_getenv_bool(user, "expire")) {
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen if (user->mail_debug)
b87daa509bf5b306189282a9df795d094a6d7150Timo Sirainen i_debug("expire: No expire setting - plugin disabled");
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen return;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen }
d34a07d36865fa4438d6c6af8408376188343eb9Baofeng
d34a07d36865fa4438d6c6af8408376188343eb9Baofeng dict_uri = mail_user_plugin_getenv(user, "expire_dict");
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen if (dict_uri == NULL) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen i_error("expire plugin: expire_dict setting missing");
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen return;
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen }
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen /* we're using only shared dictionary, the username doesn't matter. */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&dict_set);
20e04227229970d148801c507946666e2a9bd838Timo Sirainen dict_set.value_type = DICT_DATA_TYPE_UINT32;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen dict_set.username = "";
20e04227229970d148801c507946666e2a9bd838Timo Sirainen dict_set.base_dir = user->set->base_dir;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen if (dict_init(dict_uri, &dict_set, &db, &error) < 0) {
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen i_error("expire plugin: dict_init(%s) failed: %s",
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen dict_uri, error);
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen return;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen }
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen euser = p_new(user->pool, struct expire_mail_user, 1);
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen euser->module_ctx.super = *v;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen user->vlast = &euser->module_ctx.super;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen v->deinit = expire_mail_user_deinit;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen euser->db = db;
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen euser->set = expire_set_init(expire_get_patterns(user));
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang euser->expire_cache = mail_user_plugin_getenv_bool(user, "expire_cache");
877912710a33c5645c85d6902a0ec6c79fcd0649Timo Sirainen MODULE_CONTEXT_SET(user, expire_mail_user_module, euser);
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen}
cf7164ece50797a67fc4bfb5889022ac93a36a8aTimo Sirainen
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainenstatic struct mail_storage_hooks expire_mail_storage_hooks = {
17ac264fe7efd383f10c67548cadcc5aca505b92Timo Sirainen .mail_user_created = expire_mail_user_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}