From c7ff32cf0e6d2089261b223012aa8fdc3ed37933 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 22 Jul 2024 20:56:29 +0100 Subject: [PATCH] Sieve: add redirect router option for inbox name --- doc/doc-docbook/filter.xfpt | 6 +++++- doc/doc-docbook/spec.xfpt | 22 +++++++++++++++++++++- doc/doc-txt/NewStuff | 22 +++++++++++++--------- doc/doc-txt/OptionLists.txt | 5 +++++ src/src/routers/redirect.c | 6 ++++-- src/src/sieve.c | 36 +++++++++++++++++++++++++++--------- src/src/structs.h | 5 +++-- test/confs/0428 | 9 +++++++++ test/log/0428 | 3 +++ test/mail/0428.inbox.changed | 15 +++++++++++++++ test/scripts/0000-Basic/0428 | 3 +++ 11 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 test/mail/0428.inbox.changed diff --git a/doc/doc-docbook/filter.xfpt b/doc/doc-docbook/filter.xfpt index 77b295ce9..87c268203 100644 --- a/doc/doc-docbook/filter.xfpt +++ b/doc/doc-docbook/filter.xfpt @@ -355,10 +355,14 @@ contains an additional address besides the one the test checks for. .section "Semantics of keep" "SEC11" -The &(keep)& command is equivalent to +.new +The &(keep)& command is by default equivalent to .code fileinto "inbox"; .endd +but, when called from a redirect router, the destination can be set +by using the &%sieve_inbox%& option on the router. +.wen It saves the message and resets the implicit keep flag. It does not set the implicit keep flag; there is no command to set it once it has been reset. diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 4abe2c9cb..cc5198ac5 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -22223,6 +22223,12 @@ subject to address rewriting. Otherwise, they are treated like new addresses and are rewritten according to the global rewriting rules. +.option sieve_inbox redirect string&!! &"inbox"& +.new +The value of this option is passed to a Sieve filter to specify the +name of the mailbox used for "keep" operations (explicit or implicit). +.wen + .option sieve_subaddress redirect string&!! unset The value of this option is passed to a Sieve filter to specify the :subaddress part of an address. @@ -23259,7 +23265,11 @@ fileinto "folder23"; .endd In this situation, the expansion of &%file%& or &%directory%& in the transport must transform the relative path into an appropriate absolute filename. In the -case of Sieve filters, the name &'inbox'& must be handled. It is the name that +case of Sieve filters, the name &'inbox'& must be handled. It is the +.new +default +.wen +name that is used as a result of a &"keep"& action in the filter. This example shows one way of handling this requirement: .code @@ -23275,6 +23285,12 @@ With this setting of &%file%&, &'inbox'& refers to the standard mailbox location, absolute paths are used without change, and other folders are in the &_mail_& directory within the home directory. +.new +An alternative for the &"keep"& aspect is to use the &%sieve_inbox%& option +on the redirect router that calls the Sieve filter, +to explicitly set the filename used. +.wen + &*Note 1*&: While processing an Exim filter, a relative path such as &_folder23_& is turned into an absolute path if a home directory is known to the router. In particular, this is the case if &%check_local_user%& is set. If @@ -23285,6 +23301,10 @@ path to the transport. &*Note 2*&: An absolute path in &$address_file$& is not treated specially; the &%file%& or &%directory%& option is still used if it is set. +.new +&*Note 3*&: Permitting a user to enable writes to an absolute path +may be a security issue. +.wen diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index 778c3259e..012d71d68 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -6,6 +6,10 @@ Before a formal release, there may be quite a lot of detail so that people can test from the snapshots or the Git before the documentation is updated. Once the documentation is updated, this file is reduced to a short list. +Version 4.98 +------------ + 1. A sieve_inbox option for redirect routers + Version 4.98 ------------ 1. The dkim_status ACL condition may now be used in data ACLs @@ -14,23 +18,23 @@ Version 4.98 3. The dkim_timestamps signing option now accepts zero to include a current timestamp but no expiry timestamp. Code by Simon Arlott; testsuite - additions by jgh. + additions by jgh - 4. The recipients_max main option is now expanded. + 4. The recipients_max main option is now expanded - 5. Setting variables for "exim -be" can set a tainted value. + 5. Setting variables for "exim -be" can set a tainted value - 6. A dns:fail event. + 6. A dns:fail event - 7. The dsearch lookup supports search for a sub-path. + 7. The dsearch lookup supports search for a sub-path - 8. Include mailtest utility for simple connection checking. + 8. Include mailtest utility for simple connection checking - 9. Add SMTP WELLKNOWN extension. + 9. Add SMTP WELLKNOWN extension 10. Sqlite3 can be used for the hints databases (vs. DBD, NDB, GBDM, TDB). - Add "USE_SQLITE = y" and "DBMLIB = -lsqlite3" in Local/Makefile, to override - the settings done in the OS/Makefile- file. + Add "USE_SQLITE = y" and "DBMLIB = -lsqlite3" in Local/Makefile, to + override the settings done in the OS/Makefile- file Version 4.97 ------------ diff --git a/doc/doc-txt/OptionLists.txt b/doc/doc-txt/OptionLists.txt index 987f096ba..e7b284760 100644 --- a/doc/doc-txt/OptionLists.txt +++ b/doc/doc-txt/OptionLists.txt @@ -535,6 +535,11 @@ server_set_id string* unset authenticator set string* unset routers 4.93 shadow_condition string* unset transports shadow_transport string unset transports +sieve_inbox string* "inbox" redirect 4.99 +sieve_enotify_mailto_owner string* "inbox" redirect +sieve_subaddress string* "inbox" redirect +sieve_useraddress string* "inbox" redirect +sieve_vacation_directory string* "inbox" redirect size_addition integer 1024 smtp 1.91 skip_syntax_errors boolean false redirect 4.00 smtp_accept_keepalive boolean true main diff --git a/src/src/routers/redirect.c b/src/src/routers/redirect.c index 08b7726b7..4da658781 100644 --- a/src/src/routers/redirect.c +++ b/src/src/routers/redirect.c @@ -92,6 +92,7 @@ optionlist redirect_router_options[] = { LOFF(bit_options) }, { "sieve_enotify_mailto_owner", opt_stringptr, LOFF(sieve_enotify_mailto_owner) }, + { "sieve_inbox", opt_stringptr, LOFF(sieve_inbox) }, { "sieve_subaddress", opt_stringptr, LOFF(sieve_subaddress) }, { "sieve_useraddress", opt_stringptr, LOFF(sieve_useraddress) }, { "sieve_vacation_directory", opt_stringptr, LOFF(sieve_vacation_directory) }, @@ -566,10 +567,11 @@ redirect.pw = pw; redirect.string = (redirect.isfile = (ob->file != NULL)) ? ob->file : ob->data; +sieve.inbox = ob->sieve_inbox; +sieve.subaddress = ob->sieve_subaddress; sieve.vacation_dir = ob->sieve_vacation_directory; -sieve.enotify_mailto_owner = ob->sieve_enotify_mailto_owner; sieve.useraddress = ob->sieve_useraddress; -sieve.subaddress = ob->sieve_subaddress; +sieve.enotify_mailto_owner = ob->sieve_enotify_mailto_owner; frc = rda_interpret(&redirect, options, ob->include_directory, &sieve, &ugid, &generated, &addr->message, ob->skip_syntax_errors ? &eblock : NULL, diff --git a/src/src/sieve.c b/src/src/sieve.c index db37f44fa..dbe64cffa 100644 --- a/src/src/sieve.c +++ b/src/src/sieve.c @@ -80,6 +80,7 @@ struct Sieve { BOOL require_vacation; BOOL vacation_ran; #endif + const uschar *inbox; const uschar *vacation_directory; const uschar *subaddress; const uschar *useraddress; @@ -963,9 +964,10 @@ Returns: nothing */ static void -add_addr(address_item **generated, uschar *addr, int file, int maxage, int maxmessages, int maxstorage) +add_addr(address_item ** generated, const uschar * addr, int file, int maxage, + int maxmessages, int maxstorage) { -address_item *new_addr; +address_item * new_addr; for (new_addr = *generated; new_addr; new_addr = new_addr->next) if ( Ustrcmp(new_addr->address, addr) == 0 @@ -975,8 +977,10 @@ for (new_addr = *generated; new_addr; new_addr = new_addr->next) ) ) { - if ((filter_test != FTEST_NONE && debug_selector != 0) || (debug_selector & D_filter) != 0) - debug_printf_indent("Repeated %s `%s' ignored.\n", file ? "fileinto" : "redirect", addr); + if ( filter_test != FTEST_NONE && debug_selector != 0 + || (debug_selector & D_filter) != 0) + debug_printf_indent("Repeated %s `%s' ignored.\n", + file ? "fileinto" : "redirect", addr); return; } @@ -2775,7 +2779,7 @@ while (*filter->pc) return -1; if (exec) { - add_addr(generated, US"inbox", 1, 0, 0, 0); + add_addr(generated, filter->inbox, 1, 0, 0, 0); filter->keep = 0; } } @@ -3513,6 +3517,7 @@ Arguments: enotify_mailto_owner owner of mailto notifications useraddress string expression for :user part of address subaddress string expression for :subaddress part of address + inbox string expression for "keep" generated where to hang newly-generated addresses error where to pass back an error text @@ -3536,16 +3541,27 @@ DEBUG(D_route) debug_printf_indent("Sieve: start of processing\n"); expand_level++; sieve.filter = filter; +GET_OPTION("sieve_vacation_directory"); if (!sb || !sb->vacation_dir) sieve.vacation_directory = NULL; else if (!(sieve.vacation_directory = expand_cstring(sb->vacation_dir))) { *error = string_sprintf("failed to expand \"%s\" " - "(sieve_vacation_directory): %s", sb->vacation_dir, - expand_string_message); + "(sieve_vacation_directory): %s", sb->vacation_dir, expand_string_message); + return FF_ERROR; + } + +GET_OPTION("sieve_vacation_directory"); +if (!sb || !sb->inbox) + sieve.inbox = US"inbox"; +else if (!(sieve.inbox = expand_cstring(sb->inbox))) + { + *error = string_sprintf("failed to expand \"%s\" " + "(sieve_inbox): %s", sb->inbox, expand_string_message); return FF_ERROR; } +GET_OPTION("sieve_enotify_mailto_owner"); if (!sb || !sb->enotify_mailto_owner) sieve.enotify_mailto_owner = NULL; else if (!(sieve.enotify_mailto_owner = expand_cstring(sb->enotify_mailto_owner))) @@ -3556,8 +3572,10 @@ else if (!(sieve.enotify_mailto_owner = expand_cstring(sb->enotify_mailto_owner) return FF_ERROR; } +GET_OPTION("sieve_useraddress"); sieve.useraddress = sb && sb->useraddress ? sb->useraddress : CUS "$local_part_prefix$local_part$local_part_suffix"; +GET_OPTION("sieve_subaddress"); sieve.subaddress = sb ? sb->subaddress : NULL; #ifdef COMPILE_SYNTAX_CHECKER @@ -3567,7 +3585,7 @@ if (parse_start(&sieve, 1, generated) == 1) #endif if (sieve.keep) { - add_addr(generated, US"inbox", 1, 0, 0, 0); + add_addr(generated, sieve.inbox, 1, 0, 0, 0); msg = US"Implicit keep"; r = FF_DELIVERED; } @@ -3583,7 +3601,7 @@ else r = FF_ERROR; *error = msg; #else - add_addr(generated, US"inbox", 1, 0, 0, 0); + add_addr(generated, sieve.inbox, 1, 0, 0, 0); r = FF_DELIVERED; #endif } diff --git a/src/src/structs.h b/src/src/structs.h index c11a5c6b1..95a1c1099 100644 --- a/src/src/structs.h +++ b/src/src/structs.h @@ -896,10 +896,11 @@ typedef struct redirect_block { /* Sieve control data */ typedef struct sieve_block { - const uschar * vacation_dir; + const uschar * inbox; const uschar * enotify_mailto_owner; - const uschar * useraddress; const uschar * subaddress; + const uschar * useraddress; + const uschar * vacation_dir; } sieve_block; /* Structure for passing arguments to check_host() */ diff --git a/test/confs/0428 b/test/confs/0428 index bb2c414fe..0f6614bcf 100644 --- a/test/confs/0428 +++ b/test/confs/0428 @@ -134,6 +134,15 @@ r2_14: file_transport = t1 reply_transport = t3 +r2_15: + driver = redirect + local_parts = userx_inbox + allow_filter + data = "#Sieve filter\nkeep;\n" + user = CALLER + sieve_inbox = inbox.changed + file_transport = t1 + r2: driver = redirect allow_filter diff --git a/test/log/0428 b/test/log/0428 index 7b0f948fc..7d20a6927 100644 --- a/test/log/0428 +++ b/test/log/0428 @@ -51,3 +51,6 @@ 1999-03-02 09:44:33 10HmbN-000000005vi-0000 => TESTSUITE/test-mail/userx14 R=r2_14 T=t1 1999-03-02 09:44:33 10HmbN-000000005vi-0000 => TESTSUITE/test-mail/userx-sawsuffix R=r2_14 T=t1 1999-03-02 09:44:33 10HmbN-000000005vi-0000 Completed +1999-03-02 09:44:33 10HmbO-000000005vi-0000 <= CALLER@test.ex U=CALLER P=local S=sss +1999-03-02 09:44:33 10HmbO-000000005vi-0000 => TESTSUITE/test-mail/inbox.changed R=r2_15 T=t1 +1999-03-02 09:44:33 10HmbO-000000005vi-0000 Completed diff --git a/test/mail/0428.inbox.changed b/test/mail/0428.inbox.changed new file mode 100644 index 000000000..262d1a50d --- /dev/null +++ b/test/mail/0428.inbox.changed @@ -0,0 +1,15 @@ +From CALLER@test.ex Tue Mar 02 09:44:33 1999 +Return-path: +Envelope-to: userx_inbox@test.ex +Delivery-date: Tue, 2 Mar 1999 09:44:33 +0000 +Received: from CALLER by mail.test.ex with local (Exim x.yz) + (envelope-from ) + id 10HmbO-000000005vi-0000 + for userx_inbox@test.ex; + Tue, 2 Mar 1999 09:44:33 +0000 +Message-Id: +From: CALLER_NAME +Date: Tue, 2 Mar 1999 09:44:33 +0000 + +Test 15 + diff --git a/test/scripts/0000-Basic/0428 b/test/scripts/0000-Basic/0428 index 24c1b1265..f5aaa4124 100644 --- a/test/scripts/0000-Basic/0428 +++ b/test/scripts/0000-Basic/0428 @@ -101,3 +101,6 @@ exim -odi -f someone@test.ex userx14-suffix userx14-suffix2 } Test 14 **** +exim -odi userx_inbox +Test 15 +**** -- 2.30.2