diff options
Diffstat (limited to 'libmu_sieve/actions.c')
-rw-r--r-- | libmu_sieve/actions.c | 108 |
1 files changed, 105 insertions, 3 deletions
diff --git a/libmu_sieve/actions.c b/libmu_sieve/actions.c index 344924fb1..4ceb49c96 100644 --- a/libmu_sieve/actions.c +++ b/libmu_sieve/actions.c @@ -1,5 +1,5 @@ /* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999-2019 Free Software Foundation, Inc. + Copyright (C) 1999-2024 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -73,6 +73,104 @@ sieve_action_discard (mu_sieve_machine_t mach) return 0; } +static void +sieve_mailbox_deallocator (void *ptr) +{ + if (ptr) + { + mu_mailbox_t mbox = ptr; + mu_mailbox_close (mbox); + mu_mailbox_destroy (&mbox); + } +} + +static int +sieve_mailbox_open (mu_sieve_machine_t mach, char const *filename, int flags, + mu_mailbox_t *ret_mbox) +{ + int rc; + mu_mailbox_t mbox; + + if ((rc = mu_mailbox_create_default (&mbox, filename))) + { + mu_debug (MU_DEBCAT_MESSAGE, MU_DEBUG_ERROR, + ("mu_mailbox_create_default (%s) failed: %s\n", + filename, + mu_strerror (rc))); + return rc; + } + + flags |= MU_STREAM_APPEND | MU_STREAM_CREAT; + if ((rc = mu_mailbox_open (mbox, flags)) != 0) + { + mu_debug (MU_DEBCAT_MESSAGE, MU_DEBUG_ERROR, + ("mu_mailbox_open (%s) failed: %s", filename, + mu_strerror (rc))); + if (rc == ENFILE || rc == EMFILE) + { + if (mu_assoc_pop (mach->mailboxes, NULL, NULL) == 0) + { + if ((rc = mu_mailbox_open (mbox, flags)) == 0) + goto ret; + else + { + mu_debug (MU_DEBCAT_MESSAGE, MU_DEBUG_ERROR, + ("second mu_mailbox_open (%s) failed: %s", filename, + mu_strerror (rc))); + } + } + } + mu_mailbox_destroy (&mbox); + return rc; + } + ret: + *ret_mbox = mbox; + return 0; +} + +static int +sieve_get_mailbox (mu_sieve_machine_t mach, char const *filename, int flags, + mu_mailbox_t *ret_mbox) +{ + int rc; + mu_mailbox_t mbox, *mbox_ptr; + + if (!mach->mailboxes) + { + rc = mu_assoc_create (&mach->mailboxes, MU_ASSOC_LRU); + if (rc) + { + mu_sieve_error (mach, _("failed to create mailbox storage table: %s"), + mu_strerror (rc)); + mu_sieve_abort (mach); + } + mu_assoc_set_destroy_item (mach->mailboxes, sieve_mailbox_deallocator); + + } + + switch (rc = mu_assoc_install_ref (mach->mailboxes, filename, &mbox_ptr)) + { + case 0: + if ((rc = sieve_mailbox_open (mach, filename, flags, &mbox)) != 0) + mu_assoc_shift (mach->mailboxes, NULL, NULL); + else + *mbox_ptr = mbox; + break; + + case MU_ERR_EXISTS: + mbox = *mbox_ptr; + rc = 0; + break; + + default: + mu_sieve_error (mach, _("failed to retrieve mailbox %s: %s"), + filename, mu_strerror (rc)); + mu_sieve_abort (mach); + } + *ret_mbox = mbox; + return rc; +} + static int sieve_action_fileinto (mu_sieve_machine_t mach) { @@ -80,7 +178,8 @@ sieve_action_fileinto (mu_sieve_machine_t mach) int mbflags = 0; char *filename; char *perms; - + mu_mailbox_t mbox; + mu_sieve_get_arg (mach, 0, SVT_STRING, &filename); if (mu_sieve_get_tag (mach, "permissions", SVT_STRING, &perms)) @@ -100,8 +199,11 @@ sieve_action_fileinto (mu_sieve_machine_t mach) if (mu_sieve_is_dry_run (mach)) return 0; - rc = mu_message_save_to_mailbox (mach->msg, filename, mbflags); + rc = sieve_get_mailbox (mach, filename, mbflags, &mbox); if (rc) + return rc; + + if ((rc = mu_mailbox_append_message (mbox, mach->msg)) != 0) mu_sieve_error (mach, _("cannot save to mailbox: %s"), mu_strerror (rc)); else |