.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.
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.
.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
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 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
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
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
------------
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
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) },
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,
BOOL require_vacation;
BOOL vacation_ran;
#endif
+ const uschar *inbox;
const uschar *vacation_directory;
const uschar *subaddress;
const uschar *useraddress;
*/
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
)
)
{
- 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 -1;
if (exec)
{
- add_addr(generated, US"inbox", 1, 0, 0, 0);
+ add_addr(generated, filter->inbox, 1, 0, 0, 0);
filter->keep = 0;
}
}
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
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)))
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
#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;
}
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
}
/* 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() */
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
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
--- /dev/null
+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
+
}
Test 14
****
+exim -odi userx_inbox
+Test 15
+****