Sieve: add redirect router option for inbox name
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 22 Jul 2024 19:56:29 +0000 (20:56 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 22 Jul 2024 22:56:18 +0000 (23:56 +0100)
doc/doc-docbook/filter.xfpt
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
doc/doc-txt/OptionLists.txt
src/src/routers/redirect.c
src/src/sieve.c
src/src/structs.h
test/confs/0428
test/log/0428
test/mail/0428.inbox.changed [new file with mode: 0644]
test/scripts/0000-Basic/0428

index 77b295ce9b2b4e12d61e42faa3353f6d5b1ad2e7..87c2682038a4f291152ccdf5fc73dfefb420c106 100644 (file)
@@ -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.
 
index 4abe2c9cbcb36ab8a022539c0478142627399352..cc5198ac5cd81d0609df28684a422f1f3cb60be6 100644 (file)
@@ -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
 
 
 
index 778c3259e7c65c85be8510d41457e0ae7d5b5906..012d71d68b1eacdef7278bf3cb3b042c817d1e3e 100644 (file)
@@ -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-<platform> file.
+     Add "USE_SQLITE = y" and "DBMLIB = -lsqlite3" in Local/Makefile, to
+     override the settings done in the OS/Makefile-<platform> file
 
 Version 4.97
 ------------
index 987f096ba122f8ab6597f30d569943aa211883d7..e7b28476055a526ac642c702ab43d3a1d40c62e2 100644 (file)
@@ -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
index 08b7726b751ddad4824fea957797cff53274cbbf..4da658781a5105d220565d88186a47e884545271 100644 (file)
@@ -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,
index db37f44fa4a2da097a28e2671a82a5229bb1b017..dbe64cffa10578e425769ec2ca7e0b2cfc7635bf 100644 (file)
@@ -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
   }
index c11a5c6b1ea7382a97e1f5597dd9d2e74affc862..95a1c10997cccf64ad2723d2978c77091961d380 100644 (file)
@@ -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() */
index bb2c414fe2212ab827ab41a337af5f7c8afc1881..0f6614bcf1ef309bad6773f6aaf5987a2a78ec16 100644 (file)
@@ -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
index 7b0f948fc3d40ab9cebbfcbff1df9f821fc2bd8f..7d20a6927f7e6f86f272cd589b14d5f531272d3d 100644 (file)
@@ -51,3 +51,6 @@
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 => TESTSUITE/test-mail/userx14 <userx14-suffix2@test.ex> R=r2_14 T=t1
 1999-03-02 09:44:33 10HmbN-000000005vi-0000 => TESTSUITE/test-mail/userx-sawsuffix <userx14-suffix@test.ex> 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 <userx_inbox@test.ex> 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 (file)
index 0000000..262d1a5
--- /dev/null
@@ -0,0 +1,15 @@
+From CALLER@test.ex Tue Mar 02 09:44:33 1999
+Return-path: <CALLER@test.ex>
+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 <CALLER@test.ex>)
+       id 10HmbO-000000005vi-0000
+       for userx_inbox@test.ex;
+       Tue, 2 Mar 1999 09:44:33 +0000
+Message-Id: <E10HmbO-000000005vi-0000@mail.test.ex>
+From: CALLER_NAME <CALLER@test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+Test 15
+
index 24c1b12653d39a546539acc32c40cd26d04b2619..f5aaa4124d71bc7fc436be51a1e58606da232989 100644 (file)
@@ -101,3 +101,6 @@ exim -odi -f someone@test.ex userx14-suffix userx14-suffix2
         }   
 Test 14
 ****
+exim -odi userx_inbox
+Test 15
+****