diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index ca2b21b2c524772344b0d59dcf1cab307764de00..1faa3c888316abab0e266d331a05070f6c4c116d 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -74,6 +74,8 @@ const struct sieve_operation cmd_redirect_operation = {
  * Redirect action 
  */
 
+static bool act_redirect_equals
+	(const struct sieve_script_env *senv, const void *ctx1, const void *ctx2);
 static int act_redirect_check_duplicate
 	(const struct sieve_runtime_env *renv,
 		const struct sieve_action_data *act, 
@@ -88,6 +90,7 @@ static bool act_redirect_commit
 const struct sieve_action act_redirect = {
 	"redirect",
 	SIEVE_ACTFLAG_TRIES_DELIVER,
+	act_redirect_equals,
 	act_redirect_check_duplicate, 
 	NULL,
 	act_redirect_print,
@@ -237,22 +240,27 @@ static int cmd_redirect_operation_execute
 /*
  * Action implementation
  */
+
+static bool act_redirect_equals
+(const struct sieve_script_env *senv ATTR_UNUSED, 
+	const void *ctx1, const void *ctx2)
+{
+	struct act_redirect_context *rd_ctx1 = 
+		(struct act_redirect_context *) ctx1;
+	struct act_redirect_context *rd_ctx2 = 
+		(struct act_redirect_context *) ctx2;
+
+	/* Address is already normalized, strcmp suffices to assess duplicates */
+	return ( strcmp(rd_ctx1->to_address, rd_ctx2->to_address) == 0 );
+}
  
 static int act_redirect_check_duplicate
 (const struct sieve_runtime_env *renv ATTR_UNUSED,
 	const struct sieve_action_data *act, 
 	const struct sieve_action_data *act_other)
 {
-	struct act_redirect_context *ctx1 = 
-		(struct act_redirect_context *) act->context;
-	struct act_redirect_context *ctx2 = 
-		(struct act_redirect_context *) act_other->context;
-	
-	/* Address is already normalized, strcmp suffices to assess duplicates */
-	if ( strcmp(ctx1->to_address, ctx2->to_address) == 0 ) 
-		return 1;
-		
-	return 0;
+	return ( act_redirect_equals
+		(renv->scriptenv, act->context, act_other->context) ? 1 : 0 );
 }
 
 static void act_redirect_print
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index 26ee60db24fad293c84540e4cd2280c51a0e0a53..62e351a6e1d69ee4155cd9d5adf348a4ace0b113 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -132,6 +132,7 @@ static bool act_reject_commit
 const struct sieve_action act_reject = {
 	"reject",
 	SIEVE_ACTFLAG_SENDS_RESPONSE,
+	NULL,
 	act_reject_check_duplicate, 
 	act_reject_check_conflict,
 	act_reject_print,
diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c
index a25b588baddceacd0ac750186eb6d34d7e396b78..9d4112a6c037b48ce57e82f2c7e587cc136e05fd 100644
--- a/src/lib-sieve/plugins/enotify/cmd-notify.c
+++ b/src/lib-sieve/plugins/enotify/cmd-notify.c
@@ -154,6 +154,7 @@ static bool act_notify_commit
 const struct sieve_action act_notify = {
 	"notify",
 	0,
+	NULL,
 	act_notify_check_duplicate, 
 	NULL,
 	act_notify_print,
diff --git a/src/lib-sieve/plugins/vacation/cmd-vacation.c b/src/lib-sieve/plugins/vacation/cmd-vacation.c
index 9ffdf5d385eca5c25499028b00590df602a56f91..9715e1eb42491547e436f1c5b4afef756c337164 100644
--- a/src/lib-sieve/plugins/vacation/cmd-vacation.c
+++ b/src/lib-sieve/plugins/vacation/cmd-vacation.c
@@ -190,6 +190,7 @@ static bool act_vacation_commit
 const struct sieve_action act_vacation = {
 	"vacation",
 	SIEVE_ACTFLAG_SENDS_RESPONSE,
+	NULL,
 	act_vacation_check_duplicate, 
 	act_vacation_check_conflict,
 	act_vacation_print,
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index c544cb79352a97199f44ab8c22a95694b6343e6f..57662dbeb23eaaff307ec61c1585617097d257c0 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -61,6 +61,9 @@ bool sieve_opr_side_effect_dump
  
 /* Forward declarations */
 
+static bool act_store_equals
+	(const struct sieve_script_env *senv, const void *ctx1, const void *ctx2);
+	
 static int act_store_check_duplicate
 	(const struct sieve_runtime_env *renv, 
 		const struct sieve_action_data *act, 
@@ -87,6 +90,7 @@ static void act_store_rollback
 const struct sieve_action act_store = {
 	"store",
 	SIEVE_ACTFLAG_TRIES_DELIVER,
+	act_store_equals,
 	act_store_check_duplicate, 
 	NULL, 
 	act_store_print,
@@ -115,32 +119,40 @@ int sieve_act_store_add_to_result
 		source_line, (void *) act, 0);
 }
 
-/* Result verification */
+/* Equality */
 
-static int act_store_check_duplicate
-(const struct sieve_runtime_env *renv,
-	const struct sieve_action_data *act, 
-	const struct sieve_action_data *act_other)
+static bool act_store_equals
+(const struct sieve_script_env *senv, const void *ctx1, const void *ctx2)
 {
-	struct act_store_context *ctx1 = 
-		(struct act_store_context *) act->context;
-	struct act_store_context *ctx2 = 
-		(struct act_store_context *) act_other->context;
+	struct act_store_context *st_ctx1 = (struct act_store_context *) ctx1;
+	struct act_store_context *st_ctx2 = (struct act_store_context *) ctx2;
 	const char *folder1, *folder2;
 	
-	if ( ctx1 == NULL && ctx2 == NULL )
-		return 1;
+	if ( st_ctx1 == NULL && st_ctx2 == NULL )
+		return TRUE;
 		
-	folder1 = ctx1 == NULL ? 
-		SIEVE_SCRIPT_DEFAULT_MAILBOX(renv->scriptenv) : ctx1->folder;
-	folder2 = ctx2 == NULL ? 
-		SIEVE_SCRIPT_DEFAULT_MAILBOX(renv->scriptenv) : ctx2->folder;
+	folder1 = ( st_ctx1 == NULL ? 
+		SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) : st_ctx1->folder );
+	folder2 = ( st_ctx2 == NULL ? 
+		SIEVE_SCRIPT_DEFAULT_MAILBOX(senv) : st_ctx2->folder );
 	
 	if ( strcmp(folder1, folder2) == 0 ) 
-		return 1;
+		return TRUE;
 		
 	return 
 		( strcasecmp(folder1, "INBOX") == 0 && strcasecmp(folder2, "INBOX") == 0 ); 
+
+}
+
+/* Result verification */
+
+static int act_store_check_duplicate
+(const struct sieve_runtime_env *renv,
+	const struct sieve_action_data *act, 
+	const struct sieve_action_data *act_other)
+{
+	return ( act_store_equals(renv->scriptenv, act->context, act_other->context)
+		? 1 : 0 );
 }
 
 /* Result printing */
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index 65a3228b5996cdfad8eb75c4049977bcae076b2b..c088ab58c42c846f5f69898ce0b2b18f037275f5 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -51,6 +51,9 @@ struct sieve_action_data {
 struct sieve_action {
 	const char *name;
 	unsigned int flags;
+	
+	bool (*equals)
+		(const struct sieve_script_env *senv, const void *ctx1, const void *ctx2);
 
 	/* Result verification */
 	
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 6a742d844f0f68939488e3dc68e3c109128dea64..55a9f1bd8f9e97e46bf24adf5e75b732ff71422a 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -316,6 +316,26 @@ static int sieve_result_side_effects_merge
 	return 1;
 }
 
+static void sieve_result_action_detach(struct sieve_result_action *raction)
+{
+	struct sieve_result *result = raction->result;
+	
+	if ( result->first_action == raction ) 
+		result->first_action = raction->next;
+		
+	if ( result->last_action == raction ) 
+		result->last_action = raction->prev;
+		
+	if ( raction->next != NULL ) raction->next->prev = raction->prev;
+	if ( raction->prev != NULL ) raction->prev->next = raction->next;
+	
+	raction->next = NULL;
+	raction->prev = NULL;
+	
+	if ( result->action_count > 0 )
+		result->action_count--;
+}
+
 static int _sieve_result_add_action
 (const struct sieve_runtime_env *renv,
 	const struct sieve_action *action, struct sieve_side_effects_list *seffects,
@@ -344,23 +364,16 @@ static int _sieve_result_add_action
 			if ( raction->data.executed ) {
 				/* Keep action from preceeding execution */
 			
-				kaction = raction;
-			
 				/* Detach existing keep action */
-				if ( result->first_action == kaction ) 
-					result->first_action = kaction->next;
-				if ( result->last_action == kaction ) 
-					result->last_action = kaction->prev;
-				if ( kaction->next != NULL ) kaction->next->prev = kaction->prev;
-				if ( kaction->prev != NULL ) kaction->prev->next = kaction->next;
-			
+				sieve_result_action_detach(raction);
+
 				/* Merge existing side-effects with new keep action */
-				if ( raction->data.action == NULL ) {
-					if ( (ret=sieve_result_side_effects_merge
-						(renv, action, seffects, kaction->seffects)) <= 0 )	 
-						return ret;
-				}
-				
+				if ( kaction == NULL )
+					kaction = raction;
+			
+				if ( (ret=sieve_result_side_effects_merge
+					(renv, action, kaction->seffects, seffects)) <= 0 )	 
+					return ret;				
 			} else {
 				/* True duplicate */
 				
@@ -384,19 +397,28 @@ static int _sieve_result_add_action
 						 * action. So, take over the result action object and transform it
 						 * into a keep.
 						 */
+						 
 						if ( (ret=sieve_result_side_effects_merge
 							(renv, action, raction->seffects, seffects)) < 0 ) 
 							return ret;
+						 
+						if ( kaction == NULL ) {								
+							raction->data.context = NULL;
+							raction->data.location = p_strdup(result->pool, act_data.location);
 							
-						raction->keep = TRUE;
-						raction->data.context = NULL;
-						raction->data.location = p_strdup(result->pool, act_data.location);
-						
-						/* Note that existing execution status is retained, making sure that
-						 * keep is not executed multiple times.
-						 */
-						
-						return 1;
+							/* Note that existing execution status is retained, making sure 
+							 * that keep is not executed multiple times.
+							 */
+							
+							kaction = raction;
+												
+						} else {
+							sieve_result_action_detach(raction);
+
+							if ( (ret=sieve_result_side_effects_merge
+								(renv, action, kaction->seffects, raction->seffects)) < 0 ) 
+								return ret;
+						}
 					} else {
 						/* Merge side-effects, but don't add new action */
 						return sieve_result_side_effects_merge
@@ -405,14 +427,16 @@ static int _sieve_result_add_action
 				}
 			}
 		} else {
-			/* Check conflict */
-			if ( action->check_conflict != NULL &&
-				(ret=action->check_conflict(renv, &act_data, &raction->data)) != 0 ) 
-				return ret;
+			if ( action != NULL && oact != NULL ) {
+				/* Check conflict */
+				if ( action->check_conflict != NULL &&
+					(ret=action->check_conflict(renv, &act_data, &raction->data)) != 0 ) 
+					return ret;
 			
-			if ( !raction->data.executed && oact->check_conflict != NULL &&
-				(ret=oact->check_conflict(renv, &raction->data, &act_data)) != 0 )
-				return ret;
+				if ( !raction->data.executed && oact->check_conflict != NULL &&
+					(ret=oact->check_conflict(renv, &raction->data, &act_data)) != 0 )
+					return ret;
+			}
 		}
 		raction = raction->next;
 	}
@@ -438,71 +462,75 @@ static int _sieve_result_add_action
 		/* Create new action object */
 		raction = p_new(result->pool, struct sieve_result_action, 1);
 		raction->data.executed = FALSE;
+		raction->result = result;
+		raction->seffects = seffects;
+		raction->tr_context = NULL;
+		raction->success = FALSE;
 	}
 	
-	raction->result = result;
 	raction->data.context =	context;
 	raction->data.action = action;
 	raction->data.location = p_strdup(result->pool, act_data.location);
-	raction->tr_context = NULL;
-	raction->success = FALSE;
 	raction->keep = keep;
-	raction->seffects = seffects;
 
-	/* Add */
-	if ( result->first_action == NULL ) {
-		result->first_action = raction;
-		result->last_action = raction;
-		raction->prev = NULL;
-		raction->next = NULL;
-	} else {
-		result->last_action->next = raction;
-		raction->prev = result->last_action;
-		result->last_action = raction;
-		raction->next = NULL;
-	}
-	result->action_count++;
+	if ( raction->prev == NULL ) {
+		/* Add */
+		if ( result->first_action == NULL ) {
+			result->first_action = raction;
+			result->last_action = raction;
+			raction->prev = NULL;
+			raction->next = NULL;
+		} else {
+			result->last_action->next = raction;
+			raction->prev = result->last_action;
+			result->last_action = raction;
+			raction->next = NULL;
+		}
+		result->action_count++;
 	
-	/* Apply any implicit side effects */
-	if ( result->action_contexts != NULL ) {
-		struct sieve_result_action_context *actctx;
+		/* Apply any implicit side effects */
+		if ( result->action_contexts != NULL ) {
+			struct sieve_result_action_context *actctx;
 		
-		/* Check for implicit side effects to this particular action */
-		actctx = (struct sieve_result_action_context *) 
-				hash_table_lookup(result->action_contexts, action);
+			/* Check for implicit side effects to this particular action */
+			actctx = (struct sieve_result_action_context *) 
+					hash_table_lookup(result->action_contexts, action);
 		
-		if ( actctx != NULL ) {
-			struct sieve_result_side_effect *iseff;
+			if ( actctx != NULL ) {
+				struct sieve_result_side_effect *iseff;
 			
-			/* Iterate through all implicit side effects and add those that are 
-			 * missing.
-			 */
-			iseff = actctx->seffects->first_effect;
-			while ( iseff != NULL ) {
-				struct sieve_result_side_effect *seff;
-				bool exists = FALSE;
+				/* Iterate through all implicit side effects and add those that are 
+				 * missing.
+				 */
+				iseff = actctx->seffects->first_effect;
+				while ( iseff != NULL ) {
+					struct sieve_result_side_effect *seff;
+					bool exists = FALSE;
 				
-				/* Scan for presence */
-				if ( seffects != NULL ) {
-					seff = seffects->first_effect;
-					while ( seff != NULL ) {
-						if ( seff->seffect == iseff->seffect ) {
-							exists = TRUE;
-							break;
-						}
+					/* Scan for presence */
+					if ( seffects != NULL ) {
+						seff = seffects->first_effect;
+						while ( seff != NULL ) {
+							if ( seff->seffect == iseff->seffect ) {
+								exists = TRUE;
+								break;
+							}
 					
-						seff = seff->next;
+							seff = seff->next;
+						}
+					} else {
+						raction->seffects = seffects = 
+							sieve_side_effects_list_create(result);
 					}
-				} else {
-					raction->seffects = seffects = sieve_side_effects_list_create(result);
-				}
 				
-				/* If not present, add it */
-				if ( !exists ) {
-					sieve_side_effects_list_add(seffects, iseff->seffect, iseff->context);
-				}
+					/* If not present, add it */
+					if ( !exists ) {
+						sieve_side_effects_list_add
+							(seffects, iseff->seffect, iseff->context);
+					}
 				
-				iseff = iseff->next;
+					iseff = iseff->next;
+				}
 			}
 		}
 	}
@@ -527,6 +555,12 @@ int sieve_result_add_keep
 		(renv, renv->result->keep_action, seffects, source_line, NULL, 0, TRUE);
 }
 
+void sieve_result_set_keep_action
+(struct sieve_result *result, const struct sieve_action *action)
+{
+	result->keep_action = action;
+}
+
 /*
  * Result printing
  */
@@ -574,10 +608,28 @@ void sieve_result_seffect_printf
 	o_stream_send(penv->stream, str_data(outbuf), str_len(outbuf));
 }
 
+static void sieve_result_print_side_effect
+(struct sieve_result_print_env *rpenv, const struct sieve_action *action,
+	struct sieve_side_effects_list *slist, bool *implicit_keep)
+{
+	struct sieve_result_side_effect *rsef;
+	const struct sieve_side_effect *sef;
+	
+	/* Print side effects */
+	rsef = slist != NULL ? slist->first_effect : NULL;
+	while ( rsef != NULL ) {
+		sef = rsef->seffect;
+		if ( sef->print != NULL ) 
+			sef->print(sef, action, rpenv, rsef->context, implicit_keep);
+		rsef = rsef->next;
+	}
+}
+
 bool sieve_result_print
 (struct sieve_result *result, const struct sieve_script_env *senv, 
 	struct ostream *stream, bool *keep)
 {
+	const struct sieve_action *act_keep = result->keep_action;
 	struct sieve_result_print_env penv;
 	bool implicit_keep = TRUE;
 	struct sieve_result_action *rac, *first_action;
@@ -601,8 +653,6 @@ bool sieve_result_print
 		rac = first_action;
 		while ( rac != NULL ) {		
 			bool impl_keep = TRUE;
-			struct sieve_result_side_effect *rsef;
-			const struct sieve_side_effect *sef;
 			const struct sieve_action *act = rac->data.action;
 
 			if ( rac->keep && keep != NULL ) *keep = TRUE;
@@ -622,13 +672,8 @@ bool sieve_result_print
 			}
 	
 			/* Print side effects */
-			rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL;
-			while ( rsef != NULL ) {
-				sef = rsef->seffect;
-				if ( sef->print != NULL ) 
-					sef->print(sef, rac->data.action, &penv, rsef->context, &impl_keep);
-				rsef = rsef->next;
-			}
+			sieve_result_print_side_effect
+				(&penv, rac->data.action, rac->seffects, &impl_keep);
 			
 			implicit_keep = implicit_keep && impl_keep;		
 		
@@ -637,9 +682,49 @@ bool sieve_result_print
 	}
 	
 	if ( implicit_keep && keep != NULL ) *keep = TRUE;
-	
-	sieve_result_printf
-		(&penv, "\nImplicit keep: %s\n", implicit_keep ? "yes" : "no");
+		
+	sieve_result_printf(&penv, "\nImplicit keep:\n\n");
+		
+	if ( implicit_keep ) {
+		bool dummy = TRUE;
+			
+		if ( act_keep == NULL ) 
+			sieve_result_action_printf(&penv, "keep");
+		else {
+			/* Scan for execution of keep-equal actions */	
+			rac = result->first_action;
+			while ( act_keep != NULL && rac != NULL ) {
+				if ( rac->data.action == act_keep && act_keep->equals != NULL && 
+					act_keep->equals(senv, NULL, rac->data.context) 
+						&& rac->data.executed ) {
+					act_keep = NULL;
+				}
+	 		
+				rac = rac->next;	
+			}
+			
+			if ( act_keep == NULL ) {
+				sieve_result_printf(&penv, 
+					"  (none; keep or equivalent action executed earlier)\n");
+			} else {
+				act_keep->print(act_keep, &penv, NULL, &dummy);
+			
+				/* Apply any implicit side effects if applicable */
+				if ( result->action_contexts != NULL ) {
+					struct sieve_result_action_context *actctx;
+		
+					/* Check for implicit side effects to keep action */
+					actctx = (struct sieve_result_action_context *) 
+							hash_table_lookup(result->action_contexts, act_keep);
+		
+					if ( actctx != NULL && actctx->seffects != NULL ) 
+						sieve_result_print_side_effect
+							(&penv, act_keep, actctx->seffects, &dummy);
+				}
+			}
+		}
+	} else 
+		sieve_result_printf(&penv, "  (none)\n");
 	
 	return TRUE;
 }
@@ -651,6 +736,7 @@ bool sieve_result_print
 static bool _sieve_result_implicit_keep
 	(struct sieve_result *result, bool rollback)
 {	
+	struct sieve_result_action *rac;
 	bool success = TRUE;
 	bool dummy = TRUE;
 	struct sieve_result_side_effect *rsef, *rsef_first = NULL;
@@ -659,7 +745,18 @@ static bool _sieve_result_implicit_keep
 	
 	/* If keep is a non-action, return right away */
 	if ( act_keep == NULL ) return TRUE; 
-		
+
+	/* Scan for execution of keep-equal actions */	
+	rac = result->first_action;
+	while ( rac != NULL ) {
+		if ( rac->data.action == act_keep && act_keep->equals != NULL && 
+			act_keep->equals(result->action_env.scriptenv, NULL, rac->data.context) &&
+			rac->data.executed )
+			return TRUE;
+ 		
+		rac = rac->next;	
+	}
+	
 	/* Apply any implicit side effects if applicable */
 	if ( !rollback && result->action_contexts != NULL ) {
 		struct sieve_result_action_context *actctx;
@@ -754,7 +851,8 @@ void sieve_result_mark_executed(struct sieve_result *result)
 
 	rac = first_action;
 	while ( rac != NULL ) {
- 		rac->data.executed = TRUE;
+		if ( rac->data.action != NULL )
+			rac->data.executed = TRUE;
  		
 		rac = rac->next;	
 	}
@@ -872,23 +970,17 @@ int sieve_result_execute
 			
 			if ( rac->keep && keep != NULL ) *keep = TRUE;
 
-			/* Skip executed actions */
-			if ( rac->data.executed ) {
+			/* Skip non-actions (inactive keep) and executed ones */
+			if ( act == NULL || rac->data.executed ) {
 				rac = rac->next;	
 				continue;
 			}
 			
-			rac->data.executed = TRUE;
-			
-			/* Skip non-actions (inactive keep) */
-			if ( act == NULL ) {
-				rac = rac->next;	
-				continue;
+			if ( act->commit != NULL ) { 
+				rac->data.executed = act->commit
+					(act, &result->action_env, rac->tr_context, &impl_keep);
+				commit_ok = rac->data.executed && commit_ok;
 			}
-			
-			if ( act->commit != NULL ) 
-				commit_ok = act->commit
-					(act, &result->action_env, rac->tr_context, &impl_keep) && commit_ok;
 	
 			/* Execute post_commit event of side effects */
 			rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL;
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index 41dff38f5bf164ca9a4a9bdb4683577d27e5b5be..6457d1655140a57b04e66f02dda4dc18fb87e14c 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -91,6 +91,9 @@ int sieve_result_add_keep
 	(const struct sieve_runtime_env *renv, 
 		struct sieve_side_effects_list *seffects, unsigned int source_line);
 
+void sieve_result_set_keep_action
+	(struct sieve_result *result, const struct sieve_action *action);
+
 /*
  * Result execution
  */
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index ffdd997365d213ae6efe595b160b3dcd388b9564..13f26ce3109928d2ff341efc913eae1f98f27e89 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -11,6 +11,7 @@
 #include "sieve-script.h"
 #include "sieve-ast.h"
 #include "sieve-binary.h"
+#include "sieve-actions.h"
 #include "sieve-result.h"
 
 #include "sieve-parser.h"
@@ -357,6 +358,8 @@ struct sieve_multiscript *sieve_multiscript_start
 	result = sieve_result_create(ehandler);
 	pool = sieve_result_pool(result);
 	
+	sieve_result_set_keep_action(result, NULL);
+	
 	mscript = p_new(pool, struct sieve_multiscript, 1);
 	mscript->result = result;
 	mscript->msgdata = msgdata;
@@ -370,9 +373,12 @@ struct sieve_multiscript *sieve_multiscript_start
 
 bool sieve_multiscript_test
 (struct sieve_multiscript *mscript, struct sieve_binary *sbin, 
-	struct ostream *stream)
+	bool final, struct ostream *stream)
 {		
 	if ( !mscript->active ) return FALSE;
+	
+	if ( final )
+		sieve_result_set_keep_action(mscript->result, &act_store);
 
 	/* Run the script */
 	mscript->status = sieve_run(sbin, &mscript->result, mscript->msgdata, 
@@ -399,9 +405,13 @@ bool sieve_multiscript_test
 }
 
 bool sieve_multiscript_execute
-(struct sieve_multiscript *mscript, struct sieve_binary *sbin)
+(struct sieve_multiscript *mscript, struct sieve_binary *sbin,
+	bool final)
 {
 	if ( !mscript->active ) return FALSE;
+	
+	if ( final )
+		sieve_result_set_keep_action(mscript->result, &act_store);
 
 	/* Run the script */
 	mscript->status = sieve_run(sbin, &mscript->result, mscript->msgdata, 
diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h
index 3c5a739dd5208b16cffe3da95e5ec2a717b07bb9..8294d2420fdd1078b59f5036859e4a5b44af9d1a 100644
--- a/src/lib-sieve/sieve.h
+++ b/src/lib-sieve/sieve.h
@@ -125,9 +125,10 @@ struct sieve_multiscript *sieve_multiscript_start
 		
 bool sieve_multiscript_test
 	(struct sieve_multiscript *mscript, struct sieve_binary *sbin, 
-		struct ostream *stream);
+		bool final, struct ostream *stream);
 bool sieve_multiscript_execute
-	(struct sieve_multiscript *mscript, struct sieve_binary *sbin);
+	(struct sieve_multiscript *mscript, struct sieve_binary *sbin,
+		bool final);
 	
 int sieve_multiscript_finish(struct sieve_multiscript **mscript);
 
diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index 845c4ffa553903764fbdcff115820eecc52c41f0..b5ec3734c487db06c7d5c2c5515ea1f5dc1f5c6f 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -236,7 +236,8 @@ int main(int argc, char **argv)
 			sieve_tool_dump_binary_to(sbin, dumpfile);
 			
 			/* Test script */
-			result = ( sieve_multiscript_test(mscript, sbin, teststream) ? 1 : 0 );
+			result = ( sieve_multiscript_test(mscript, sbin, FALSE, teststream) ? 
+				1 : 0 );
 			
 			/* Close script */
 			sieve_close(&sbin);
@@ -247,7 +248,7 @@ int main(int argc, char **argv)
 				t_strdup_printf("\n## Executing script: %s\n", scriptfile));
 				
 			sbin = main_sbin;
-			(void)sieve_multiscript_test(mscript, main_sbin, teststream);
+			(void)sieve_multiscript_test(mscript, main_sbin, TRUE, teststream);
 			ret = sieve_multiscript_finish(&mscript);
 		} else {
 			ret = SIEVE_EXEC_FAILURE;