diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 157f2d0eadcf59b8c4347c808184e67627efbe7b..7b9da9eb5e2b8669a554d0c1c91cc15bc9617ff1 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -1,10 +1,12 @@
 #include "lib.h"
+#include "str-sanitize.h"
 
 #include "sieve-commands.h"
 #include "sieve-commands-private.h"
 #include "sieve-validator.h" 
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-result.h"
 
 /* Forward declarations */
 
@@ -46,6 +48,24 @@ const struct sieve_opcode cmd_redirect_opcode = {
 	cmd_redirect_opcode_execute 
 };
 
+/* Redirect action */
+
+static void act_redirect_print
+	(const struct sieve_action *action, void *context);	
+static int act_redirect_execute
+	(const struct sieve_action *action,	const struct sieve_action_exec_env *aenv, 
+		void *context);
+		
+struct act_redirect_context {
+	const char *to_address;
+};
+
+const struct sieve_action act_redirect = {
+	"redirect",
+	act_redirect_print,
+	act_redirect_execute
+};
+
 /* Validation */
 
 static bool cmd_redirect_validate
@@ -94,14 +114,16 @@ static bool cmd_redirect_opcode_dump
 }
 
 /*
- * Execution
+ * Intepretation
  */
 
 static bool cmd_redirect_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	struct act_redirect_context *act;
 	string_t *redirect;
+	pool_t pool;
 
 	t_push();
 
@@ -111,7 +133,45 @@ static bool cmd_redirect_opcode_execute
 	}
 
 	printf(">> REDIRECT \"%s\"\n", str_c(redirect));
-
+	
+	pool = sieve_result_pool(renv->result);
+	act = p_new(pool, struct act_redirect_context, 1);
+	act->to_address = p_strdup(pool, str_c(redirect));
+	
+	sieve_result_add_action(renv->result, &act_redirect, (void *) act);
+	
 	t_pop();
 	return TRUE;
 }
+
+/*
+ * Action
+ */
+
+static void act_redirect_print
+(const struct sieve_action *action ATTR_UNUSED, void *context)	
+{
+	struct act_redirect_context *ctx = (struct act_redirect_context *) context;
+	
+	printf("* redirect message to: %s\n", ctx->to_address);
+}
+
+static int act_redirect_execute
+(const struct sieve_action *action ATTR_UNUSED, 
+	const struct sieve_action_exec_env *aenv, void *context)
+{
+	const struct sieve_message_data *msgdata = aenv->msgdata;
+	struct act_redirect_context *ctx = (struct act_redirect_context *) context;
+	int res;
+	
+	if ((res = aenv->mailenv->
+		send_forward(msgdata, ctx->to_address)) == 0) {
+		i_info("msgid=%s: forwarded to <%s>",
+			msgdata->id == NULL ? "" : str_sanitize(msgdata->id, 80),
+				str_sanitize(ctx->to_address, 80));
+  }
+  
+	return res;
+}
+
+
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 669a268e14ab00a36a3a1f46db78e7b196e660e5..2f740922384b41f60431bbad33d5d7fe8eb61eed 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -231,14 +231,19 @@ bool sieve_interpreter_execute_operation
 }		
 
 bool sieve_interpreter_run
-(struct sieve_interpreter *interp, struct sieve_message_data *msgdata,
-	struct sieve_result *result) 
+(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata,
+	const struct sieve_mail_environment *menv, struct sieve_result **result) 
 {
+	bool is_topmost = ( *result == NULL );
 	sieve_interpreter_reset(interp);
 	
+	if ( *result == NULL )
+		*result = sieve_result_create();
+	else
+		sieve_result_ref(*result);
 	interp->runenv.msgdata = msgdata;
-	interp->runenv.result = result;		
-	sieve_result_ref(result);
+	interp->runenv.result = *result;		
+	interp->runenv.mailenv = menv;
 	
 	while ( !interp->stopped && 
 		interp->pc < sieve_binary_get_code_size(interp->runenv.sbin) ) {
@@ -246,16 +251,22 @@ bool sieve_interpreter_run
 		
 		if ( !sieve_interpreter_execute_operation(interp) ) {
 			printf("Execution aborted.\n");
-			sieve_result_unref(&result);
+			sieve_result_unref(result);
 			return FALSE;
 		}
 	}
 	
 	interp->runenv.result = NULL;
 	interp->runenv.msgdata = NULL;
+	interp->runenv.mailenv = NULL;
+	
+	if ( is_topmost ) {
+		sieve_result_print(*result);
+		sieve_result_execute(*result, msgdata, menv);
+	}
+	
+	sieve_result_unref(result);
 	
-	sieve_result_unref(&result);
-
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index 0f0f5fee6583fbf8b1b4fdae720740f2a76870fe..5d4e0a5f8c8c0d4f5acb409a3b915c6fe5439576 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -17,6 +17,7 @@ struct sieve_runtime_env {
 	struct sieve_interpreter *interp;
 	struct sieve_binary *sbin;
 	const struct sieve_message_data *msgdata;
+	const struct sieve_mail_environment *mailenv;
 	struct sieve_result *result;
 };
 
@@ -59,7 +60,7 @@ void sieve_interpreter_dump_code(struct sieve_interpreter *interp);
 bool sieve_interpreter_execute_operation(struct sieve_interpreter *interp); 
 
 bool sieve_interpreter_run
-(struct sieve_interpreter *interp, struct sieve_message_data *msgdata,
-	struct sieve_result *result);
+(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata,
+	const struct sieve_mail_environment *menv, struct sieve_result **result);
 
 #endif /* __SIEVE_INTERPRETER_H */
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 15e34c851be4786d795c7f4caa321bd2086b80d7..d7a24d0fef4853659495d4012f02846f7b559784 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -3,8 +3,10 @@
 
 #include "sieve-result.h"
 
+#include <stdio.h>
+
 struct sieve_result_action {
-	struct sieve_action *action;
+	const struct sieve_action *action;
 	void *context;
 
 	struct sieve_result_action *prev, *next; 
@@ -13,6 +15,7 @@ struct sieve_result_action {
 struct sieve_result {
 	pool_t pool;
 	
+	struct sieve_action_exec_env action_env;
 	struct sieve_result_action *first_action;
 	struct sieve_result_action *last_action;
 	
@@ -27,7 +30,7 @@ struct sieve_result *sieve_result_create(void)
 	pool = pool_alloconly_create("sieve_result", 4096);	
 	result = p_new(pool, struct sieve_result, 1);
 	result->pool = pool;
-	
+		
 	result->first_action = NULL;
 	result->last_action = NULL;
 	
@@ -49,9 +52,13 @@ void sieve_result_unref(struct sieve_result **result)
 	*result = NULL;
 }
 
+inline pool_t sieve_result_pool(struct sieve_result *result)
+{
+	return result->pool;
+}
 
 void sieve_result_add_action
-	(struct sieve_result *result, struct sieve_action *action, void *context)		
+(struct sieve_result *result, const struct sieve_action *action, void *context)		
 {
 	struct sieve_result_action *raction;
 	
@@ -74,15 +81,18 @@ void sieve_result_add_action
 	}	
 }	
 
-bool sieve_result_dump(struct sieve_result *result)
+bool sieve_result_print(struct sieve_result *result)
 {
 	struct sieve_result_action *rac = result->first_action;
 	
-	while ( rac != NULL ) {
-		if ( rac->action->dump != NULL ) {
-			
+	printf("\nPerformed actions:\n");
+	while ( rac != NULL ) {		
+		const struct sieve_action *act = rac->action;
+	
+		if ( act->print != NULL ) {
+			act->print(act, rac->context);	
 		} else {
-			printf("ACTION: %s (no further information)\n", rac->action->name); 
+			printf("* %s\n", act->name); 
 		}
 		rac = rac->next;	
 	}
@@ -90,17 +100,25 @@ bool sieve_result_dump(struct sieve_result *result)
 	return TRUE;
 }
 
-bool sieve_result_execute(struct sieve_result *result)
-{
-	struct sieve_result_action *raction = result->first_action;
+bool sieve_result_execute
+	(struct sieve_result *result, const struct sieve_message_data *msgdata,
+		const struct sieve_mail_environment *menv)
+{ 
+	struct sieve_result_action *rac = result->first_action;
+	
+	result->action_env.msgdata = msgdata;
+	result->action_env.mailenv = menv;
 	
-	while ( raction != NULL ) {
-		if ( raction->action->execute != NULL ) {
-			
+	printf("\n");
+	while ( rac != NULL ) {
+		const struct sieve_action *act = rac->action;
+	
+		if ( act->execute != NULL ) {
+			(void) act->execute(act, &result->action_env, rac->context);
 		} else {
-			i_warning("Action %s performs absolutely nothing.", raction->action->name);	
+			i_warning("Action %s performs absolutely nothing.", act->name);	
 		}
-		raction = raction->next;	
+		rac = rac->next;	
 	}
 	
 	return TRUE;
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index 197a431081fbe526ce80d41445308265a5864000..6790cad49570abad2f3c0e9fee185e08e3caa831 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -1,28 +1,38 @@
 #ifndef __SIEVE_RESULT_H
 #define __SIEVE_RESULT_H
 
-#include "sieve-interpreter.h"
+#include "sieve-common.h"
 
 struct sieve_result;
 
+struct sieve_action_exec_env {
+	const struct sieve_message_data *msgdata;
+	const struct sieve_mail_environment *mailenv;
+};
+
 struct sieve_action {
 	const char *name;
 
+	void (*print)
+		(const struct sieve_action *action, void *context);	
 	int (*execute)
-		(struct sieve_interpreter *interpreter, struct sieve_result *result, void *context);	
-	int (*dump)
-		(struct sieve_interpreter *interpreter, struct sieve_result *result, void *context);	
+		(const struct sieve_action *action, 
+			const struct sieve_action_exec_env *aenv, void *context);	
 };
 
 struct sieve_result *sieve_result_create(void);
 void sieve_result_ref(struct sieve_result *result); 
 void sieve_result_unref(struct sieve_result **result); 
+inline pool_t sieve_result_pool(struct sieve_result *result);
 
 void sieve_result_add_action
-	(struct sieve_result *result, struct sieve_action *action, void *context);		
+	(struct sieve_result *result, const struct sieve_action *action, 
+		void *context);		
 
-bool sieve_result_dump(struct sieve_result *result);
+bool sieve_result_print(struct sieve_result *result);
 
-bool sieve_result_execute(struct sieve_result *result);
+bool sieve_result_execute
+	(struct sieve_result *result, const struct sieve_message_data *msgdata,
+		const struct sieve_mail_environment *menv);
 
 #endif
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 9c0d4eb76a76aadfe92a7879a31e35ed3d2d0114..798f8f19b56d49eceeb35e4aaf92b537021f0bd6 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -144,14 +144,15 @@ void sieve_dump(struct sieve_binary *binary)
 }
 	
 bool sieve_execute
-	(struct sieve_binary *binary, struct sieve_message_data *msgdata) 
+	(struct sieve_binary *binary, const struct sieve_message_data *msgdata,
+		const struct sieve_mail_environment *menv) 
 {
-	struct sieve_result *sres = sieve_result_create();
+	struct sieve_result *sres = NULL;
 	struct sieve_interpreter *interpreter = sieve_interpreter_create(binary);			
 	bool result = TRUE;
 							
 	printf("Code Execute:\n\n");
-	if ( !sieve_interpreter_run(interpreter, msgdata, sres) ) {
+	if ( !sieve_interpreter_run(interpreter, msgdata, menv, &sres) ) {
 		result = FALSE;
 	}
 				
diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h
index beb591927f479b596e7eb89ceb9f757010b750a9..7610fcdbef4e212be234323a441510f67094889e 100644
--- a/src/lib-sieve/sieve.h
+++ b/src/lib-sieve/sieve.h
@@ -11,6 +11,16 @@ struct sieve_message_data {
 	const char *return_path;
 	const char *to_address;
 	const char *auth_user;
+	const char *id;
+};
+
+struct sieve_mail_environment {
+	/* Interface for sending mail (callbacks if you like) */
+	int (*send_rejection)
+		(const struct sieve_message_data *msgdata, const char *recipient, 
+			const char *reason);
+	int (*send_forward)
+		(const struct sieve_message_data *msgdata, const char *forwardto);
 };	
 
 bool sieve_init(const char *plugins);
@@ -19,6 +29,7 @@ void sieve_deinit(void);
 struct sieve_binary *sieve_compile(int fd);
 void sieve_dump(struct sieve_binary *binary);
 bool sieve_execute
-	(struct sieve_binary *binary, struct sieve_message_data *msgdata);
+	(struct sieve_binary *binary, const struct sieve_message_data *msgdata,
+		const struct sieve_mail_environment *menv);
 
 #endif
diff --git a/src/sieve-bin/Makefile.am b/src/sieve-bin/Makefile.am
index df92ad1828c5d231135d8d69777ef548f20d7ceb..e6efa88a869604175926fbd2b0d830656abe28ca 100644
--- a/src/sieve-bin/Makefile.am
+++ b/src/sieve-bin/Makefile.am
@@ -8,7 +8,8 @@ AM_CPPFLAGS = \
 	-I$(dovecot_incdir)/src/lib-index \
 	-I$(dovecot_incdir)/src/lib-storage \
 	-I$(dovecot_incdir)/src/lib-storage/index \
-	-I$(dovecot_incdir)/src/lib-storage/index/raw 
+	-I$(dovecot_incdir)/src/lib-storage/index/raw \
+	-I$(dovecot_incdir)/src/deliver
 
 sievec_LDFLAGS = -export-dynamic -Wl,--start-group 
 sieve_test_LDFLAGS = -export-dynamic -Wl,--start-group
@@ -41,5 +42,5 @@ sievec_SOURCES = \
 	sievec.c 
 
 sieve_test_SOURCES = \
-	sieve_test.c
+	sieve_test.c 
 
diff --git a/src/sieve-bin/sieve_test.c b/src/sieve-bin/sieve_test.c
index 3ebdc4dc1707caeeeaaf5689de557fba73a7fb86..cea391d5d5f30c32089dd07c3e923fdf77f8890d 100644
--- a/src/sieve-bin/sieve_test.c
+++ b/src/sieve-bin/sieve_test.c
@@ -118,23 +118,31 @@ static struct istream *create_raw_stream(int fd)
 }
 
 static void sieve_test
-	(struct sieve_binary *sbin, struct sieve_message_data *msgdata)
+	(struct sieve_binary *sbin, const struct sieve_message_data *msgdata,
+		const struct sieve_mail_environment *mailenv)
 {
-	const char *const *headers;
-
-	printf("HEADERS\n");
-	if (mail_get_headers_utf8(msgdata->mail, "from", &headers) >= 0) {	
-		int i;
-		for ( i = 0; headers[i] != NULL; i++ ) {
-			printf("HEADER: From: %s\n", headers[i]);
-		} 
-	}
-	
-	if ( sieve_execute(sbin, msgdata) ) {
+	if ( sieve_execute(sbin, msgdata, mailenv) ) {
 		printf("Script executed to an end succesfully.\n");
 	}
 }
 
+static int sieve_send_rejection
+(const struct sieve_message_data *msgdata ATTR_UNUSED, 
+	const char *recipient, const char *reason)
+{
+	i_info("<<NOT PERFORMED>> Rejected mail to %s with reason \"%s\"\n", 
+		recipient, reason);  
+	return 0;
+}
+
+static int sieve_send_forward
+(const struct sieve_message_data *msgdata ATTR_UNUSED, 
+	const char *forwardto)
+{
+	i_info("<<NOT PERFORMED>> Forwarded mail to %s.", forwardto);
+	return 0;
+}
+
 int main(int argc, char **argv) 
 {
 	const char *envelope_sender = DEFAULT_ENVELOPE_SENDER;
@@ -153,6 +161,7 @@ int main(int argc, char **argv)
 	int fd;
 	struct sieve_binary *sbin;
 	struct sieve_message_data msgdata;
+	struct sieve_mail_environment mailenv;
 
 	lib_init();
 	ioloop = io_loop_create();
@@ -237,14 +246,22 @@ int main(int argc, char **argv)
 	/* */
 	i_stream_seek(input, 0);
 
+	/* Collect necessary message data */
+	memset(&msgdata, 0, sizeof(msgdata));
 	msgdata.mail = mail;
 	msgdata.return_path = "nico@example.com";
 	msgdata.to_address = "sirius+sieve@rename-it.nl";
 	msgdata.auth_user = "stephan";
-	sieve_test(sbin, &msgdata);
+	(void)mail_get_first_header(mail, "Message-ID", &msgdata.id);
+	
+	memset(&mailenv, 0, sizeof(mailenv));
+	mailenv.send_forward = sieve_send_forward;
+	mailenv.send_rejection = sieve_send_rejection;
+	
+	/* Run the test */
+	sieve_test(sbin, &msgdata, &mailenv);
 
 	sieve_deinit();
-	//ret = deliver_save(ns, &storage, mailbox, mail, 0, NULL);
 
 	i_stream_unref(&input);