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"
 
 
 .section "Semantics of keep" "SEC11"
-The &(keep)& command is equivalent to
+.new
+The &(keep)& command is by default equivalent to
 .code
 fileinto "inbox";
 .endd
 .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.
 
 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.
 
 
 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.
 .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
 .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
 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.
 
 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
 &*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.
 
 &*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.
 
 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
 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
 
  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).
 
  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
 ------------
 
 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
 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
 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) },
       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) },
   { "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;
 
 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.vacation_dir = ob->sieve_vacation_directory;
-sieve.enotify_mailto_owner = ob->sieve_enotify_mailto_owner;
 sieve.useraddress = ob->sieve_useraddress;
 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,
 
 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
   BOOL require_vacation;
   BOOL vacation_ran;
 #endif
+  const uschar *inbox;
   const uschar *vacation_directory;
   const uschar *subaddress;
   const uschar *useraddress;
   const uschar *vacation_directory;
   const uschar *subaddress;
   const uschar *useraddress;
@@ -963,9 +964,10 @@ Returns:      nothing
 */
 
 static void
 */
 
 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
 
 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;
     }
 
     return;
     }
@@ -2775,7 +2779,7 @@ while (*filter->pc)
       return -1;
     if (exec)
       {
       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;
       }
     }
       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
     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
 
   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;
 
 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\" "
 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;
   }
 
   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)))
 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;
   }
 
   return FF_ERROR;
   }
 
+GET_OPTION("sieve_useraddress");
 sieve.useraddress = sb && sb->useraddress
   ? sb->useraddress : CUS "$local_part_prefix$local_part$local_part_suffix";
 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
 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)
     {
 #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;
     }
     msg = US"Implicit keep";
     r = FF_DELIVERED;
     }
@@ -3583,7 +3601,7 @@ else
   r = FF_ERROR;
   *error = msg;
 #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
   }
   r = FF_DELIVERED;
 #endif
   }
index c11a5c6b1ea7382a97e1f5597dd9d2e74affc862..95a1c10997cccf64ad2723d2978c77091961d380 100644 (file)
@@ -896,10 +896,11 @@ typedef struct redirect_block {
 /* Sieve control data */
 
 typedef struct sieve_block {
 /* Sieve control data */
 
 typedef struct sieve_block {
-  const uschar * vacation_dir;
+  const uschar * inbox;
   const uschar * enotify_mailto_owner;
   const uschar * enotify_mailto_owner;
-  const uschar * useraddress;
   const uschar * subaddress;
   const uschar * subaddress;
+  const uschar * useraddress;
+  const uschar * vacation_dir;
 } sieve_block;
 
 /* Structure for passing arguments to check_host() */
 } 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
 
   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
 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 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
 ****
         }   
 Test 14
 ****
+exim -odi userx_inbox
+Test 15
+****