lazy-expunge-plugin.c revision 71748cca1bacd74451fd228db5536828bdfeb190
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2006-2016 Dovecot authors, see the included COPYING file */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MODULE_CONTEXT(obj, lazy_expunge_mail_storage_module)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MODULE_CONTEXT(obj, lazy_expunge_mailbox_list_module)
7fa573e6ea36024f618492e7d3649a69c1b41028Timo Sirainen MODULE_CONTEXT(obj, lazy_expunge_mail_user_module)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char *env;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen union mailbox_transaction_module_context module_ctx;
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen struct mailbox_transaction_context *dest_trans;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenconst char *lazy_expunge_plugin_version = DOVECOT_ABI_VERSION;
d694a52bce62c52080c3f87a56dcf77030fd2712Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_storage_module,
009217abb57a24a4076092e8e4e165545747839eStephan Boschstatic MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_module,
6303191abcb37164f435ccdc56e9dbddf1288851Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mailbox_list_module,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_user_module,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic const char *
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenget_dest_vname(struct mailbox_list *list, struct mailbox *src_box)
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* use the (canonical / unaliased) storage name */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* replace hierarchy separators with destination virtual separator */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen src_sep = mailbox_list_get_hierarchy_sep(src_box->list);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen unsigned int i;
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen /* add expunge namespace prefix. the name is now a proper vname */
00fa8dcbc66f56daa737487c9dec7166c37de79eTimo Sirainen return t_strconcat(list->ns->prefix, name, NULL);
97db4761382024093f441e4bc78ba8b6a056504dTimo Sirainenstatic struct mailbox *
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenmailbox_open_or_create(struct mailbox_list *list, struct mailbox *src_box,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen const char **error_r)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch box = mailbox_alloc(list, name, MAILBOX_FLAG_NO_INDEX_FILES |
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen MAILBOX_FLAG_SAVEONLY | MAILBOX_FLAG_IGNORE_ACLS);
cd94aeaa294f7cc507206b4b2075852f00e14d61Timo Sirainen *error_r = mailbox_get_last_error(box, &error);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen *error_r = t_strdup_printf("Failed to open mailbox %s: %s",
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen /* try creating and re-opening it. */
de754cb78f75e8b3b994cddafe41c9ed1467c33dTimo Sirainen *error_r = t_strdup_printf("Failed to create mailbox %s: %s", name,
7a94f950fd1dcc81537acfc8adb030b5e703d722Timo Sirainenstatic unsigned int
aebfda1f6e3a924c31e8f54237b81fabf4b2264cTimo Sirainenlazy_expunge_count_in_transaction(struct lazy_expunge_transaction *lt,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen lt->pool = pool_alloconly_create("lazy expunge transaction",
087939d3fa9c4056419386c9d6c81f147de534cdTimo Sirainen hash_table_create(<->guids, lt->pool, 0, str_hash, strcmp);
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen refcountp = hash_table_lookup(lt->guids, guid);
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen refcount = POINTER_CAST_TO(refcountp, unsigned int) + 1;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen hash_table_insert(lt->guids, guid, refcountp);
c49a19168dab6fda80aee16ad799a8a56d3bc18fTimo Sirainen hash_table_update(lt->guids, guid, refcountp);
02ccba3d3be96444abd15b5254864c9151bbeb30Timo Sirainenstatic int lazy_expunge_mail_is_last_instace(struct mail *_mail)
80980955bb1bbcc1bd73623fe0912f334194ddd2Timo Sirainen unsigned long refcount;
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen if (mail_get_special(_mail, MAIL_FETCH_REFCOUNT, &value) < 0) {
ca843e046e98b12f4730f4b87ee2e1a659c26e78Timo Sirainen errstr = mailbox_get_last_error(_mail->box, &error);
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* already expunged - just ignore it */
c0a708fa3f7b8f4fbca32052da5faf7a0125189dTimo Sirainen mail_storage_set_critical(_mail->box->storage,
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen "lazy_expunge: Couldn't lookup message's refcount: %s",
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen /* refcounts not supported by backend. assume all mails are
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen the last instance. */
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen i_panic("Invalid mail refcount number: %s", value);
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen /* this probably isn't the last instance of the mail, but
9132f9df4e12ed5293c70957813aa3736444a13cTimo Sirainen it's possible that the same mail was copied to this mailbox
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen multiple times and we're deleting more than one instance
f059a046515f4b2b15a6c2a10a6f12f6166e39a5Timo Sirainen within this transaction. in those cases each expunge will
a05fec120ecd8c4ed6331c42100cba42adf22893Stephan Bosch see the same refcount, so we need to adjust the refcount
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen by tracking the expunged message GUIDs. */
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen if (mail_get_special(_mail, MAIL_FETCH_GUID, &value) < 0) {
a05fec120ecd8c4ed6331c42100cba42adf22893Stephan Bosch mail_storage_set_critical(_mail->box->storage,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "lazy_expunge: Couldn't lookup message's GUID");
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* GUIDs not supported by backend, but refcounts are?
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen not with our current backends. */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen mail_storage_set_critical(_mail->box->storage,
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen "lazy_expunge: Message unexpectedly has no GUID");
ad004e44be109684521494b5af2ad1da39b8bb27Timo Sirainen refcount -= lazy_expunge_count_in_transaction(lt, value);
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic bool lazy_expunge_is_internal_mailbox(struct mailbox *box)
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* lazy_expunge not enabled at all */
9f627b360ed38fdc54cb02ec5e67246c3f0d5b0fTimo Sirainen /* lazy-expunge namespace */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen strcmp(luser->lazy_mailbox_vname, box->vname) == 0) {
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen /* lazy-expunge mailbox */
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainenstatic void lazy_expunge_mail_expunge(struct mail *_mail)
decb23442f9e6cd5c4845a9cb162029b8c6d5f0fTimo Sirainen struct mail_namespace *ns = _mail->box->list->ns;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen struct mail_private *mail = (struct mail_private *)_mail;
e248fe370c4047cee921a91b48edc37944ab0526Timo Sirainen union mail_module_context *mmail = LAZY_EXPUNGE_MAIL_CONTEXT(mail);
if (ret == 0) {
static struct mailbox_transaction_context *
struct mailbox_transaction_context *t;
int ret;
return ret;
llist);
const char *env;
void lazy_expunge_plugin_deinit(void)