-/* $Cambridge: exim/src/src/routers/redirect.c,v 1.1 2004/10/07 13:10:02 ph10 Exp $ */
+/* $Cambridge: exim/src/src/routers/redirect.c,v 1.10 2005/04/28 13:06:32 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2004 */
+/* Copyright (c) University of Cambridge 1995 - 2005 */
/* See the file NOTICE for conditions of use and distribution. */
(void *)offsetof(redirect_router_options_block, file_transport_name) },
{ "forbid_blackhole", opt_bit | (RDON_BLACKHOLE << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
+ { "forbid_exim_filter", opt_bit | (RDON_EXIM_FILTER << 16),
+ (void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_file", opt_bool,
(void *)offsetof(redirect_router_options_block, forbid_file) },
+ { "forbid_filter_dlfunc", opt_bit | (RDON_DLFUNC << 16),
+ (void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_filter_existstest", opt_bit | (RDON_EXISTS << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_filter_logwrite",opt_bit | (RDON_LOG << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_filter_lookup", opt_bit | (RDON_LOOKUP << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
- #ifdef EXIM_PERL
{ "forbid_filter_perl", opt_bit | (RDON_PERL << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
- #endif
{ "forbid_filter_readfile", opt_bit | (RDON_READFILE << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_filter_readsocket", opt_bit | (RDON_READSOCK << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
{ "forbid_pipe", opt_bool,
(void *)offsetof(redirect_router_options_block, forbid_pipe) },
+ { "forbid_sieve_filter",opt_bit | (RDON_SIEVE_FILTER << 16),
+ (void *)offsetof(redirect_router_options_block, bit_options) },
{ "hide_child_in_errmsg", opt_bool,
(void *)offsetof(redirect_router_options_block, hide_child_in_errmsg) },
{ "ignore_eacces", opt_bit | (RDON_EACCES << 16),
(void *)offsetof(redirect_router_options_block, reply_transport_name) },
{ "rewrite", opt_bit | (RDON_REWRITE << 16),
(void *)offsetof(redirect_router_options_block, bit_options) },
+ { "sieve_subaddress", opt_stringptr,
+ (void *)offsetof(redirect_router_options_block, sieve_subaddress) },
+ { "sieve_useraddress", opt_stringptr,
+ (void *)offsetof(redirect_router_options_block, sieve_useraddress) },
{ "sieve_vacation_directory", opt_stringptr,
(void *)offsetof(redirect_router_options_block, sieve_vacation_directory) },
{ "skip_syntax_errors", opt_bool,
(void *)offsetof(redirect_router_options_block, skip_syntax_errors) },
+#ifdef EXPERIMENTAL_SRS
+ { "srs", opt_stringptr,
+ (void *)offsetof(redirect_router_options_block, srs) },
+ { "srs_alias", opt_stringptr,
+ (void *)offsetof(redirect_router_options_block, srs_alias) },
+ { "srs_condition", opt_stringptr,
+ (void *)offsetof(redirect_router_options_block, srs_condition) },
+ { "srs_db", opt_stringptr,
+ (void *)offsetof(redirect_router_options_block, srs_db) },
+#endif
{ "syntax_errors_text", opt_stringptr,
(void *)offsetof(redirect_router_options_block, syntax_errors_text) },
{ "syntax_errors_to", opt_stringptr,
NULL, /* include_directory */
NULL, /* pipe_transport_name */
NULL, /* reply_transport_name */
+ NULL, /* sieve_subaddress */
+ NULL, /* sieve_useraddress */
NULL, /* sieve_vacation_directory */
NULL, /* syntax_errors_text */
NULL, /* syntax_errors_to */
NULL, /* qualify_domain */
NULL, /* owners */
NULL, /* owngroups */
+#ifdef EXPERIMENTAL_SRS
+ NULL, /* srs */
+ NULL, /* srs_condition */
+ NULL, /* srs_db */
+ NULL, /* srs_alias */
+#endif
022, /* modemask */
RDO_REWRITE, /* bit_options */
FALSE, /* check_ancestor */
"%sone of \"file\" or \"data\" must be specified",
rblock->name, (ob->file == NULL)? "" : "only ");
-/* Onetime aliases can only be real addresses. Headers can't be manipulated. */
+/* Onetime aliases can only be real addresses. Headers can't be manipulated.
+The combination of one_time and unseen is not allowed. We can't check the
+expansion of "unseen" here, but we assume that if it is set to anything other
+than false, there is likely to be a problem. */
if (ob->one_time)
{
log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
"\"headers_add\" and \"headers_remove\" are not permitted with "
"\"one_time\"", rblock->name);
+ if (rblock->unseen || rblock->expand_unseen != NULL)
+ log_write(0, LOG_PANIC_DIE|LOG_CONFIG_FOR, "%s router:\n "
+ "\"unseen\" may not be used with \"one_time\"", rblock->name);
}
/* The defaults for check_owner and check_group depend on other settings. The
ugid.gid_set = TRUE;
}
+#ifdef EXPERIMENTAL_SRS
+ /* For reverse SRS, fill the srs_recipient expandsion variable,
+ on failure, return decline/fail as relevant */
+ if(ob->srs != NULL)
+ {
+ BOOL usesrs = TRUE;
+
+ if(ob->srs_condition != NULL)
+ usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
+
+ if(usesrs)
+ if(Ustrcmp(ob->srs, "reverse") == 0 || Ustrcmp(ob->srs, "reverseandforward") == 0)
+ {
+ uschar *res;
+ int n_srs;
+
+ srs_orig_recipient = addr->address;
+ eximsrs_init();
+ if(ob->srs_db)
+ eximsrs_db_set(TRUE, ob->srs_db);
+ if((n_srs = eximsrs_reverse(&res, addr->address)) != OK)
+ return n_srs;
+ srs_recipient = res;
+ eximsrs_done();
+ DEBUG(D_any)
+ debug_printf("SRS: Recipient '%s' rewritten to '%s'\n", srs_orig_recipient, srs_recipient);
+ }
+ }
+#endif
+
/* Call the function that interprets redirection data, either inline or from a
file. This is a separate function so that the system filter can use it. It will
run the function in a subprocess if necessary. If qualify_preserve_domain is
}
frc = rda_interpret(&redirect, options, ob->include_directory,
- ob->sieve_vacation_directory, &ugid, &generated, &(addr->message),
- ob->skip_syntax_errors? &eblock : NULL, &filtertype,
- string_sprintf("%s router (recipient is %s)", rblock->name, addr->address));
+ ob->sieve_vacation_directory, ob->sieve_useraddress, ob->sieve_subaddress,
+ &ugid, &generated, &(addr->message), ob->skip_syntax_errors? &eblock : NULL,
+ &filtertype, string_sprintf("%s router (recipient is %s)", rblock->name,
+ addr->address));
qualify_domain_recipient = save_qualify_domain_recipient;
if ((xrc = sort_errors_and_headers(rblock, addr, verify, &addr_prop)) != OK)
return xrc;
add_generated(rblock, addr_new, addr, generated, &addr_prop, &ugid, pw);
- if (addr->message == NULL) addr->message = US"forced rejection";
- else addr->user_message = addr->message;
+ if (addr->message == NULL)
+ addr->message = US"forced rejection";
+ else
+ {
+ addr->user_message = addr->message;
+ setflag(addr, af_pass_message);
+ }
return FAIL;
/* As in the case of a system filter, a freeze does not happen after a manual
(addr_prop.errors_address != NULL)? "\n" : "");
}
+#ifdef EXPERIMENTAL_SRS
+ /* On successful redirection, check for SRS forwarding and adjust sender */
+ if(ob->srs != NULL)
+ {
+ BOOL usesrs = TRUE;
+
+ if(ob->srs_condition != NULL)
+ usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
+
+ if(usesrs)
+ if((Ustrcmp(ob->srs, "forward") == 0 || Ustrcmp(ob->srs, "reverseandforward") == 0) && !verify)
+ {
+ uschar *res;
+ uschar *usedomain;
+ int n_srs;
+
+ srs_orig_sender = sender_address;
+ eximsrs_init();
+ if(ob->srs_db)
+ eximsrs_db_set(FALSE, ob->srs_db);
+
+ if(ob->srs_alias != NULL ? (usedomain = expand_string(ob->srs_alias)) == NULL : 1)
+ usedomain = deliver_domain;
+
+ if((n_srs = eximsrs_forward(&res, sender_address, usedomain)) != OK)
+ return n_srs;
+ sender_address = res;
+ DEBUG(D_any)
+ debug_printf("SRS: Sender '%s' rewritten to '%s'\n", srs_orig_sender, sender_address);
+ }
+ }
+#endif
+
/* Control gets here only when the address has been completely handled. Put the
original address onto the succeed queue so that any retry items that get
attached to it get processed. */