diff --git a/sieve/errors/action-conflicts.sieve b/sieve/errors/action-conflicts.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..03949471d5016f02e4270d07864f76fe7486e230
--- /dev/null
+++ b/sieve/errors/action-conflicts.sieve
@@ -0,0 +1,8 @@
+require "fileinto";
+require "reject";
+require "vacation";
+
+#fileinto "frop";
+reject "No nonsense in my mailbox.";
+vacation "I am gone for a while.";
+redirect "stephan@example.com";
diff --git a/sieve/errors/action-duplicates.sieve b/sieve/errors/action-duplicates.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..6d5370d7687e39f08ef5e38ff868ab9026103dc3
--- /dev/null
+++ b/sieve/errors/action-duplicates.sieve
@@ -0,0 +1,4 @@
+require "reject";
+
+reject "Message is not appreciated.";
+reject "No, really, it is not appreciated.";
diff --git a/src/lib-sieve/cmd-discard.c b/src/lib-sieve/cmd-discard.c
index d165b8228190ab2e553cce4cdb4c2e57cff0b91b..232f4e5a1cfe38ab74bd5b28791f333cd6d15937 100644
--- a/src/lib-sieve/cmd-discard.c
+++ b/src/lib-sieve/cmd-discard.c
@@ -53,7 +53,8 @@ static bool act_discard_commit
 		
 const struct sieve_action act_discard = {
 	"discard",
-	NULL,	NULL,
+	0,
+	NULL, NULL,
 	act_discard_print,
 	NULL, NULL,
 	act_discard_commit,
@@ -85,9 +86,7 @@ static bool opc_discard_execute
 {	
 	printf(">> DISCARD\n");
 	
-	(void) sieve_result_add_action(renv, &act_discard, NULL, NULL);
-
-	return TRUE;
+	return ( sieve_result_add_action(renv, &act_discard, NULL, NULL) >= 0 );
 }
 
 /*
diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c
index 87b369562cdc6eea1111aa22b224491d13dbfa69..e7f243c52288023d2bf8270fca32d14da4228791 100644
--- a/src/lib-sieve/cmd-keep.c
+++ b/src/lib-sieve/cmd-keep.c
@@ -66,18 +66,19 @@ static bool opc_keep_execute
 	sieve_size_t *address ATTR_UNUSED)
 {	
 	struct sieve_side_effects_list *slist = NULL;
-	
+	int ret = 0;	
+
 	printf(">> KEEP\n");
 	
 	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
 		return FALSE;
 	
 	if ( renv->mailenv != NULL && renv->mailenv->inbox != NULL )
-		(void) sieve_act_store_add_to_result(renv,	slist, renv->mailenv->inbox);
+		ret = sieve_act_store_add_to_result(renv,	slist, renv->mailenv->inbox);
 	else
-		(void) sieve_act_store_add_to_result(renv,	slist, "INBOX");
+		ret = sieve_act_store_add_to_result(renv,	slist, "INBOX");
 	
-	return TRUE;
+	return ret >= 0;
 }
 
 
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 6081794356c66eb8e87d84e991d2846fb13ff4ff..0bc9adf042e21faf429fe0750ddbea47d7b2bf6d 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -55,7 +55,7 @@ const struct sieve_opcode cmd_redirect_opcode = {
 
 /* Redirect action */
 
-static bool act_redirect_check_duplicate
+static int act_redirect_check_duplicate
 	(const struct sieve_runtime_env *renv,
 		const struct sieve_action *action1, void *context1, void *context2);
 static void act_redirect_print
@@ -70,6 +70,7 @@ struct act_redirect_context {
 
 const struct sieve_action act_redirect = {
 	"redirect",
+	SIEVE_ACTFLAG_TRIES_DELIVER,
 	act_redirect_check_duplicate, 
 	NULL,
 	act_redirect_print,
@@ -140,6 +141,7 @@ static bool cmd_redirect_opcode_execute
 	struct act_redirect_context *act;
 	string_t *redirect;
 	pool_t pool;
+	int ret = 0;
 
 	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
 		return FALSE;
@@ -158,17 +160,17 @@ static bool cmd_redirect_opcode_execute
 	act = p_new(pool, struct act_redirect_context, 1);
 	act->to_address = p_strdup(pool, str_c(redirect));
 	
-	(void) sieve_result_add_action(renv, &act_redirect, slist, (void *) act);
+	ret = sieve_result_add_action(renv, &act_redirect, slist, (void *) act);
 	
 	t_pop();
-	return TRUE;
+	return (ret >= 0);
 }
 
 /*
  * Action
  */
  
-static bool act_redirect_check_duplicate
+static int act_redirect_check_duplicate
 (const struct sieve_runtime_env *renv ATTR_UNUSED,
 	const struct sieve_action *action1 ATTR_UNUSED, 
 	void *context1, void *context2)
@@ -177,9 +179,9 @@ static bool act_redirect_check_duplicate
 	struct act_redirect_context *ctx2 = (struct act_redirect_context *) context2;
 	
 	if ( strcmp(ctx1->to_address, ctx2->to_address) == 0 ) 
-		return TRUE;
+		return 1;
 		
-	return FALSE;
+	return 0;
 }
 
 static void act_redirect_print
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index 052fd577a06fc34e61d14fe70a99c14475704fc4..08b7012e54b08a5c4bd0bf889d2de7afc5bcfc76 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -149,6 +149,7 @@ static bool ext_fileinto_opcode_execute
 {
 	struct sieve_side_effects_list *slist = NULL; 
 	string_t *folder;
+	int ret = 0;
 	
 	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
 		return FALSE;
@@ -162,10 +163,10 @@ static bool ext_fileinto_opcode_execute
 
 	printf(">> FILEINTO \"%s\"\n", str_c(folder));
 
-	(void) sieve_act_store_add_to_result(renv, slist, str_c(folder));
+	ret = sieve_act_store_add_to_result(renv, slist, str_c(folder));
 
 	t_pop();
-	return TRUE;
+	return ( ret >= 0 );
 }
 
 
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index c8ef054d7a7201793c81179451bb2c70e566abca..5aebe2e6d4ac44397d69c7bddb918e3461983ccb 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -90,11 +90,17 @@ struct sieve_opcode reject_opcode = {
 
 /* Reject action */
 
+static int act_reject_check_duplicate
+	(const struct sieve_runtime_env *renv, const struct sieve_action *action1,
+		void *context1, void *context2);
+int act_reject_check_conflict
+	(const struct sieve_runtime_env *renv, const struct sieve_action *action,
+    	const struct sieve_action *other_action, void *context);
 static void act_reject_print
 	(const struct sieve_action *action, void *context, bool *keep);	
 static bool act_reject_commit
-(const struct sieve_action *action ATTR_UNUSED, 
-	const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep);
+	(const struct sieve_action *action ATTR_UNUSED, 
+		const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep);
 		
 struct act_reject_context {
 	const char *reason;
@@ -102,8 +108,9 @@ struct act_reject_context {
 
 const struct sieve_action act_reject = {
 	"reject",
-	NULL, 
-	NULL,
+	SIEVE_ACTFLAG_SENDS_RESPONSE,
+	act_reject_check_duplicate, 
+	act_reject_check_conflict,
 	act_reject_print,
 	NULL, NULL,
 	act_reject_commit,
@@ -178,6 +185,7 @@ static bool ext_reject_opcode_execute
 	struct act_reject_context *act;
 	string_t *reason;
 	pool_t pool;
+	int ret;
 
 	t_push();
 	
@@ -196,15 +204,46 @@ static bool ext_reject_opcode_execute
 	act = p_new(pool, struct act_reject_context, 1);
 	act->reason = p_strdup(pool, str_c(reason));
 	
-	(void) sieve_result_add_action(renv, &act_reject, slist, (void *) act);
+	ret = sieve_result_add_action(renv, &act_reject, slist, (void *) act);
 	
 	t_pop();
-	return TRUE;
+	return ( ret >= 0 );
 }
 
 /*
  * Action
  */
+
+static int act_reject_check_duplicate
+(const struct sieve_runtime_env *renv ATTR_UNUSED,
+	const struct sieve_action *action1 ATTR_UNUSED,
+	void *context1 ATTR_UNUSED, void *context2 ATTR_UNUSED)
+{
+	sieve_runtime_error(renv, "duplicate 'reject' action not allowed.");	
+	return -1;
+}
+ 
+int act_reject_check_conflict
+(const struct sieve_runtime_env *renv,
+	const struct sieve_action *action ATTR_UNUSED, 
+	const struct sieve_action *other_action, void *context ATTR_UNUSED)
+{
+	if ( (other_action->flags & SIEVE_ACTFLAG_TRIES_DELIVER) > 0 ) {
+		sieve_runtime_error(renv, "'reject' action conflicts with other action: "
+			"'%s' action tries to deliver the message.",
+			other_action->name);	
+		return -1;
+	}
+
+	if ( (other_action->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0 ) {
+		sieve_runtime_error(renv, "'reject' action conflicts with other action: "
+			"'%s' sends a response to the sender.",
+			other_action->name);	
+		return -1;
+	}
+	
+	return 0;
+}
  
 static void act_reject_print
 (const struct sieve_action *action ATTR_UNUSED, void *context, bool *keep)	
@@ -224,7 +263,7 @@ static bool act_reject_send
 	struct istream *input;
 	void *smtp_handle;
 	struct message_size hdr_size;
-  FILE *f;
+	FILE *f;
 	const char *new_msgid, *boundary;
 	const unsigned char *data;
 	const char *header;
@@ -239,18 +278,18 @@ static bool act_reject_send
 
 	smtp_handle = mailenv->smtp_open(msgdata->return_path, NULL, &f);
 
-  new_msgid = sieve_get_new_message_id(mailenv);
+	new_msgid = sieve_get_new_message_id(mailenv);
 	boundary = t_strdup_printf("%s/%s", my_pid, mailenv->hostname);
 
 	fprintf(f, "Message-ID: %s\r\n", new_msgid);
 	fprintf(f, "Date: %s\r\n", message_date_create(ioloop_time));
 	fprintf(f, "From: Mail Delivery Subsystem <%s>\r\n",
-	  mailenv->postmaster_address);
+		mailenv->postmaster_address);
 	fprintf(f, "To: <%s>\r\n", msgdata->return_path);
 	fprintf(f, "MIME-Version: 1.0\r\n");
 	fprintf(f, "Content-Type: "
-	  "multipart/report; report-type=disposition-notification;\r\n"
-	  "\tboundary=\"%s\"\r\n", boundary);
+		"multipart/report; report-type=disposition-notification;\r\n"
+		"\tboundary=\"%s\"\r\n", boundary);
 	fprintf(f, "Subject: Automatically rejected mail\r\n");
 	fprintf(f, "Auto-Submitted: auto-replied (rejected)\r\n");
 	fprintf(f, "Precedence: bulk\r\n");
@@ -266,7 +305,7 @@ static bool act_reject_send
 	fprintf(f, "Your message to <%s> was automatically rejected:\r\n"	
 		"%s\r\n", msgdata->to_address, ctx->reason);
 
-  /* MDN status report */
+	/* MDN status report */
 	fprintf(f, "--%s\r\n"
 		"Content-Type: message/disposition-notification\r\n\r\n", boundary);
 	fprintf(f, "Reporting-UA: %s; Dovecot Mail Delivery Agent\r\n",
@@ -284,7 +323,7 @@ static bool act_reject_send
 	/* original message's headers */
 	fprintf(f, "--%s\r\nContent-Type: message/rfc822\r\n\r\n", boundary);
 
-  if (mail_get_stream(msgdata->mail, &hdr_size, NULL, &input) == 0) {
+	if (mail_get_stream(msgdata->mail, &hdr_size, NULL, &input) == 0) {
     /* Note: If you add more headers, they need to be sorted.
        We'll drop Content-Type because we're not including the message
        body, and having a multipart Content-Type may confuse some
@@ -321,18 +360,18 @@ static bool act_reject_commit
 	struct act_reject_context *ctx = (struct act_reject_context *) tr_context;
 	
 	if ( msgdata->return_path == NULL || *(msgdata->return_path) == '\0' ) {
-    sieve_result_log(aenv, "discarded reject to <>");
+		sieve_result_log(aenv, "discarded reject to <>");
     
-    *keep = FALSE;
-    return TRUE;
-  }
+		*keep = FALSE;
+		return TRUE;
+	}
 	
 	if ( act_reject_send(aenv, ctx) ) {
 		sieve_result_log(aenv, "rejected");	
 
 		*keep = FALSE;
-  	return TRUE;
-  }
+		return TRUE;
+	}
   
 	return FALSE;
 }
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index b3f749cd23b1719bdfef7b873cdeddb881e58901..f46ff88064663cb41de271072ddb56d2517904b9 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -30,7 +30,6 @@
 
 #include <stdio.h>
 
-
 /* Forward declarations */
 
 static bool ext_vacation_load(int ext_id);
@@ -102,11 +101,17 @@ const struct sieve_opcode vacation_opcode = {
 
 /* Vacation action */
 
+static int act_vacation_check_duplicate
+	(const struct sieve_runtime_env *renv, const struct sieve_action *action1,
+    	void *context1, void *context2);
+int act_vacation_check_conflict
+	(const struct sieve_runtime_env *renv, const struct sieve_action *action,
+		const struct sieve_action *other_action, void *context);
 static void act_vacation_print
 	(const struct sieve_action *action, void *context, bool *keep);	
 static bool act_vacation_commit
-(const struct sieve_action *action ATTR_UNUSED, 
-	const struct sieve_action_exec_env *aenv, void *tr_context, bool *keep);
+	(const struct sieve_action *action,	const struct sieve_action_exec_env *aenv, 
+		void *tr_context, bool *keep);
 		
 struct act_vacation_context {
 	const char *reason;
@@ -121,8 +126,9 @@ struct act_vacation_context {
 
 const struct sieve_action act_vacation = {
 	"vacation",
-	NULL, 
-	NULL,
+	SIEVE_ACTFLAG_SENDS_RESPONSE,
+	act_vacation_check_duplicate, 
+	act_vacation_check_conflict,
 	act_vacation_print,
 	NULL, NULL,
 	act_vacation_commit,
@@ -435,14 +441,36 @@ static bool ext_vacation_opcode_execute
 	
 	/* FIXME: :addresses is ignored */
 	
-	(void) sieve_result_add_action(renv, &act_vacation, slist, (void *) act);
-	
-	return TRUE;
+	return ( sieve_result_add_action(renv, &act_vacation, slist, (void *) act) >= 0 );
 }
 
 /*
  * Action
  */
+
+static int act_vacation_check_duplicate
+(const struct sieve_runtime_env *renv ATTR_UNUSED,
+	const struct sieve_action *action1 ATTR_UNUSED,
+	void *context1 ATTR_UNUSED, void *context2 ATTR_UNUSED)
+{
+	sieve_runtime_error(renv, "duplicate 'vacation' action not allowed.");
+	return -1;
+}
+
+int act_vacation_check_conflict
+(const struct sieve_runtime_env *renv,
+	const struct sieve_action *action ATTR_UNUSED,
+	const struct sieve_action *other_action, void *context ATTR_UNUSED)
+{
+	if ( (other_action->flags & SIEVE_ACTFLAG_SENDS_RESPONSE) > 0 ) {
+		sieve_runtime_error(renv, "'vacation' action conflicts with other action: "
+			"'%s' action sends a response back to the sender.",	
+			other_action->name);
+		return -1;
+	}
+
+	return 0;
+}
  
 static void act_vacation_print
 (const struct sieve_action *action ATTR_UNUSED, void *context, 
@@ -649,8 +677,9 @@ static bool act_vacation_commit
 	}
 	
 	/* Did whe respond to this user before? */
-  if (mailenv->duplicate_check(dupl_hash, sizeof(dupl_hash), mailenv->username)) 
-  {
+	act_vacation_hash(msgdata, ctx, dupl_hash);
+	if (mailenv->duplicate_check(dupl_hash, sizeof(dupl_hash), mailenv->username)) 
+	{
 		sieve_result_log(aenv, "discarded duplicate vacation response to <%s>",
 			str_sanitize(msgdata->return_path, 80));
 		return TRUE;
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 6590abc89b29edbf5de06932e35752ec39a82222..6f485468337f7e817c8fee8f3cabf3d1332a2f14 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -16,6 +16,7 @@
 /*
  * Message transmission (FIXME: place this somewhere more appropriate)
  */
+ 
 const char *sieve_get_new_message_id
 	(const struct sieve_mail_environment *mailenv)
 {
@@ -137,7 +138,7 @@ const struct sieve_side_effect *sieve_opr_side_effect_read
  
 /* Store action */
 
-static bool act_store_check_duplicate
+static int act_store_check_duplicate
 	(const struct sieve_runtime_env *renv ATTR_UNUSED,
 		const struct sieve_action *action1 ATTR_UNUSED, 
 		void *context1, void *context2);
@@ -159,6 +160,7 @@ static void act_store_rollback
 		
 const struct sieve_action act_store = {
 	"store",
+	SIEVE_ACTFLAG_TRIES_DELIVER,
 	act_store_check_duplicate, 
 	NULL, 
 	act_store_print,
@@ -168,7 +170,7 @@ const struct sieve_action act_store = {
 	act_store_rollback,
 };
 
-bool sieve_act_store_add_to_result
+int sieve_act_store_add_to_result
 (const struct sieve_runtime_env *renv, 
 	struct sieve_side_effects_list *seffects, const char *folder)
 {
@@ -185,7 +187,7 @@ bool sieve_act_store_add_to_result
 
 /* Store action implementation */
 
-static bool act_store_check_duplicate
+static int act_store_check_duplicate
 (const struct sieve_runtime_env *renv ATTR_UNUSED,
 	const struct sieve_action *action1 ATTR_UNUSED, 
 	void *context1, void *context2)
@@ -194,9 +196,9 @@ static bool act_store_check_duplicate
 	struct act_store_context *ctx2 = (struct act_store_context *) context2;
 	
 	if ( strcmp(ctx1->folder, ctx2->folder) == 0 ) 
-		return TRUE;
+		return 1;
 		
-	return FALSE;
+	return 0;
 }
 
 static void act_store_print
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index 91548f3ae25da0f4c03d09b24e24272de08cc44b..0717c76af7da253be81ed29820ac98ae342b8f85 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -14,16 +14,23 @@ struct sieve_action_exec_env {
 	const struct sieve_mail_environment *mailenv;
 };
 
+enum sieve_action_flags {
+	SIEVE_ACTFLAG_TRIES_DELIVER = (1 << 0),
+	SIEVE_ACTFLAG_SENDS_RESPONSE = (1 << 1)
+};
+
 struct sieve_action {
 	const char *name;
+	unsigned int flags;
 
-	bool (*check_duplicate)	
+	int (*check_duplicate)	
 		(const struct sieve_runtime_env *renv,
 			const struct sieve_action *action, void *context1, void *context2);	
-	bool (*check_conflict)
+	int (*check_conflict)
 		(const struct sieve_runtime_env *renv,
-			const struct sieve_action *action1, const struct sieve_action *action2,
-			void *context1);
+			const struct sieve_action *action, 
+			const struct sieve_action *other_action,
+			void *context);
 
 	void (*print)
 		(const struct sieve_action *action, void *context, bool *keep);	
@@ -124,7 +131,7 @@ struct act_store_transaction {
 	const char *error;
 };
 
-bool sieve_act_store_add_to_result
+int sieve_act_store_add_to_result
 	(const struct sieve_runtime_env *renv, 
 		struct sieve_side_effects_list *seffects, const char *folder);
 
diff --git a/src/lib-sieve/sieve-commands-private.h b/src/lib-sieve/sieve-commands-private.h
index 423a53f1f5be7852dc18dccdb0f5f04588f47422..085a6501193de5024e67b3ba72523a8b70263e27 100644
--- a/src/lib-sieve/sieve-commands-private.h
+++ b/src/lib-sieve/sieve-commands-private.h
@@ -25,6 +25,11 @@ extern const struct sieve_command tst_not;
 extern const struct sieve_command tst_anyof;
 extern const struct sieve_command tst_allof;
 
+/* Core actions */
+
+extern const struct sieve_action act_redirect;
+extern const struct sieve_action act_store;
+
 /* Lists */
 
 extern const struct sieve_command *sieve_core_commands[];
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 9bf9b733209c702c9c21d3eb6d71cf4b0c76237f..435bbef4baad8671c7018f49779e995c1b7ef14f 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -25,9 +25,12 @@ struct sieve_interpreter {
 		
 	/* Execution status */
 	
-	sieve_size_t pc;  /* Program counter */
-	bool stopped;     /* Explicit successful stop requested */
-	bool test_result; /* Result of previous test command */
+	sieve_size_t pc;          /* Program counter */
+	bool stopped;             /* Explicit successful stop requested */
+	bool test_result;         /* Result of previous test command */
+
+	const struct sieve_opcode *current_op; /* Current opcode */ 
+	sieve_size_t current_op_addr;          /* Start address of current opcode */
 	
 	/* Runtime environment environment */
 	struct sieve_runtime_env runenv; 
@@ -84,6 +87,41 @@ inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp)
 	return interp->pool;
 }
 
+/* Error handling */
+
+/* FIXME: Add support to send errors elsewhere */
+
+void sieve_runtime_log
+	(const struct sieve_runtime_env *runenv, const char *fmt, ...)
+{
+	const char *op = runenv->interp->current_op == NULL ?
+		"<<NOOP>>" : runenv->interp->current_op->mnemonic;
+	va_list args;
+	va_start(args, fmt);
+
+	
+	/* Kludgy, needs explict support from liblib.a (something like i_vinfo) */	
+	i_info("%s at #%08x: %s", op, runenv->interp->current_op_addr, 
+		t_strdup_vprintf(fmt, args)); 
+	
+	va_end(args);
+}
+
+void sieve_runtime_error
+	(const struct sieve_runtime_env *runenv, const char *fmt, ...)
+{
+	const char *op = runenv->interp->current_op == NULL ?
+		"<<NOOP>>" : runenv->interp->current_op->mnemonic;
+	va_list args;
+	va_start(args, fmt);
+	
+	/* Kludgy, needs explict support from liblib.a (something like i_vinfo) */
+	i_error("%s at #%08x: %s", op, runenv->interp->current_op_addr, 
+		t_strdup_vprintf(fmt, args)); 
+	
+	va_end(args);
+}
+
 
 /* Extension support */
 
@@ -253,7 +291,10 @@ void sieve_interpreter_dump_code(struct sieve_interpreter *interp)
 bool sieve_interpreter_execute_operation
 	(struct sieve_interpreter *interp) 
 {
-	const struct sieve_opcode *opcode = 
+	const struct sieve_opcode *opcode;
+
+	interp->current_op_addr = interp->pc;
+	interp->current_op = opcode =
 		sieve_operation_read(interp->runenv.sbin, &(interp->pc));
 
 	if ( opcode != NULL ) {
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index 8f37fb63b88596a0f4b9a7a4b66dcbb9973c4f73..886ac4cfac2ced2f2643931156316f38b29e2c73 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -39,6 +39,13 @@ inline void sieve_interpreter_set_test_result
 inline bool sieve_interpreter_get_test_result
 	(struct sieve_interpreter *interp);
 	
+/* Error handling */
+
+void sieve_runtime_log
+	(const struct sieve_runtime_env *runenv, const char *fmt, ...);
+void sieve_runtime_error
+	(const struct sieve_runtime_env *runenv, const char *fmt, ...);
+
 /* Extension support */
 
 inline void sieve_interpreter_extension_set_context
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index e0afc5fb26e070cb7140c2f4aa58de820b616734..57e2a2025dcb34ebbfff080522cf5ae02d7ba7ea 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -113,11 +113,12 @@ void sieve_result_error
 
 /* Result composition */
 
-bool sieve_result_add_action
+int sieve_result_add_action
 (const struct sieve_runtime_env *renv,
 	const struct sieve_action *action, struct sieve_side_effects_list *seffects,
 	void *context)		
 {
+	int ret = 0;
 	struct sieve_result *result = renv->result;
 	struct sieve_result_action *raction;
 		
@@ -129,20 +130,20 @@ bool sieve_result_add_action
 		if ( raction->action == action ) {
 			/* Possible duplicate */
 			if ( action->check_duplicate != NULL ) {
-				if ( action->check_duplicate
-					(renv, action, raction->context, context) )
-					return FALSE;
+				if ( (ret=action->check_duplicate
+					(renv, action, raction->context, context)) != 0 )
+					return ret;
 			} else 
-				return FALSE; 
+				return 1; 
 		} else {
 			/* Check conflict */
 			if ( action->check_conflict != NULL &&
-				action->check_conflict(renv, action, oact, context) ) 
-				return FALSE;
+				(ret=action->check_conflict(renv, action, oact, context)) != 0 ) 
+				return ret;
 			
 			if ( oact->check_conflict != NULL &&
-				oact->check_conflict(renv, oact, action, raction->context) )
-				return FALSE;
+				(ret=oact->check_conflict(renv, oact, action, raction->context)) != 0 )
+				return ret;
 		}
 		raction = raction->next;
 	}
@@ -169,7 +170,7 @@ bool sieve_result_add_action
 		raction->next = NULL;
 	}	
 	
-	return TRUE;
+	return 0;
 }	
 
 bool sieve_result_print(struct sieve_result *result)
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index f982a1ed97aad1ab4a5f00710e0df7a0259b2135..166a4b8bff309f4487f70d5b41d7b464ba05866d 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -17,7 +17,7 @@ void sieve_result_log
 void sieve_result_error
 	(const struct sieve_action_exec_env *aenv, const char *fmt, ...);
 	
-bool sieve_result_add_action
+int sieve_result_add_action
 (const struct sieve_runtime_env *renv,
 	const struct sieve_action *action, struct sieve_side_effects_list *seffects,
 	void *context);