mail-autoexpunge.c revision f5ddf3762f7fa7a389b91a6b8f5732a5d4a1b382
b9f30617c2c96d54acbc4f85ed17b939c4f28916Timo Sirainen/* Copyright (c) 2015-2017 Dovecot authors, see the included COPYING file */
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen#define AUTOEXPUNGE_LOCK_FNAME "dovecot.autoexpunge.lock"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic bool mailbox_autoexpunge_lock(struct mail_user *user,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* Try to lock the autoexpunging. If the lock already exists, another
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen process is already busy with expunging, so we don't have to do it.
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen The easiest place where to store the lock file to is the home
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen directory, but allow autoexpunging to work even if we can't get
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen it. The lock isn't really required; it 1) improves performance
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen so that multiple processes won't do the same work unnecessarily,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen and 2) it helps to avoid duplicate mails being added with
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen lazy_expunge. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((ret = mail_user_get_home(user, &home)) > 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_storage_settings *mail_set =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen lock_set.lock_method = mail_set->parsed_lock_method,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen lock->path = t_strdup_printf("%s/"AUTOEXPUNGE_LOCK_FNAME, home);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen lock->fd = file_create_locked(lock->path, &lock_set,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_error("autoexpunge: Couldn't lock %s: %s", lock->path, error);
02a0492affdff138f43903c19ca366363923044dTimo Sirainen } else if (ret == 0) {
02a0492affdff138f43903c19ca366363923044dTimo Sirainen i_warning("autoexpunge: User has no home directory, can't lock");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenmailbox_autoexpunge(struct mailbox *box, unsigned int interval_time,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen time_t timestamp, expire_time, last_rename_stamp = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((unsigned int)ioloop_time < interval_time)
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen /* first try to check quickly from mailbox list index if we should
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen bother opening this mailbox. */
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen if (mailbox_get_status(box, STATUS_MESSAGES, &status) < 0) {
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen if (mailbox_get_last_mail_error(box) == MAIL_ERROR_NOTFOUND) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen /* autocreated mailbox doesn't exist yet */
7ceee001c11865a88a311c50c4430867b2d32ce6Timo Sirainen if (interval_time == 0 && status.messages <= max_mails)
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen if (max_mails == 0 || status.messages <= max_mails) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_FIRST_SAVE_DATE,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FAST) < 0)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_get_header_ext(box->view, box->box_last_rename_stamp_ext_id,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (seq = 1; seq <= hdr->messages_count; seq++) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen if (max_mails > 0 && hdr->messages_count - seq + 1 > max_mails) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen /* max_mails is still being reached -> expunge.
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen don't even check saved-dates before we're
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen below max_mails. */
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen } else if (interval_time == 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* only max_mails is used. nothing further to do. */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else if (mail_get_save_date(mail, ×tamp) == 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (I_MAX(last_rename_stamp, timestamp) > expire_time)
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen } else if (mailbox_get_last_mail_error(box) == MAIL_ERROR_EXPUNGED) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* already expunged */
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainenmailbox_autoexpunge_set(struct mail_namespace *ns, const char *vname,
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen /* autoexpunge is configured by admin, so we can safely ignore
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen any ACLs the user might normally have against expunging in
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen the mailbox. */
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_IGNORE_ACLS);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mailbox_autoexpunge(box, autoexpunge, autoexpunge_max_mails) < 0) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen i_error("Failed to autoexpunge mailbox '%s': %s",
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainenmailbox_autoexpunge_wildcards(struct mail_namespace *ns,
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen iter_name = t_strconcat(ns->prefix, set->name, NULL);
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen iter = mailbox_list_iter_init(ns->list, iter_name,
97db4761382024093f441e4bc78ba8b6a056504dTimo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) T_BEGIN {
97db4761382024093f441e4bc78ba8b6a056504dTimo Sirainen mailbox_autoexpunge_set(ns, info->vname, set->autoexpunge,
1358e2c58ce29231485a5cfa454756d429ad3d2cTimo Sirainen i_error("Failed to iterate autoexpunge mailboxes '%s': %s",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen iter_name, mailbox_list_get_last_error(ns->list, NULL));
97db4761382024093f441e4bc78ba8b6a056504dTimo Sirainenmail_namespace_autoexpunge(struct mail_namespace *ns,
const char *vname;
return TRUE;
return FALSE;
return TRUE;