diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 3cf2c02a7aaabb5932971bbe687fbc6c02e6650a..44afeef7bc2acc92fc614fddcebba04652f5275e 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -934,6 +934,7 @@ struct sieve_result_execution {
 	bool keep_success:1;
 	bool keep_explicit:1;
 	bool keep_implicit:1;
+	bool keep_finalizing:1;
 	bool seen_delivery:1;
 	bool executed:1;
 	bool executed_delivery:1;
@@ -1485,7 +1486,24 @@ sieve_result_implicit_keep_execute(struct sieve_result_execution *rexec)
 	struct sieve_action_execution *aexec_keep = &rexec->keep;
 	struct sieve_result_action *ract_keep = &rexec->keep_action;
 	struct sieve_action *act_keep = &ract_keep->action;
-	bool success = (rexec->status == SIEVE_EXEC_OK);
+	bool success = FALSE;
+
+	switch (rexec->status) {
+	case SIEVE_EXEC_OK:
+		success = TRUE;
+		break;
+	case SIEVE_EXEC_TEMP_FAILURE:
+	case SIEVE_EXEC_RESOURCE_LIMIT:
+		if (rexec->executed)
+			break;
+		if (rexec->committed)
+			break;
+		if (rexec->keep_finalizing)
+			break;
+		return;
+	default:
+		break;
+	}
 
 	if (rexec->keep_equiv_action != NULL) {
 		e_debug(rexec->event, "No implicit keep needed "
@@ -1630,6 +1648,8 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
 	e_debug(rexec->event, "Finalize implicit keep (status=%s)",
 		sieve_execution_exitcode_to_str(rexec->status));
 
+	rexec->keep_finalizing = TRUE;
+
 	/* Start keep if necessary */
 	if (act_keep->def == NULL ||
 	    aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
@@ -1923,17 +1943,11 @@ int sieve_result_execute(struct sieve_result_execution *rexec, int status,
 		return rexec->status;
 	}
 
-	/* Execute implicit keep if necessary */
-
-	if (rexec->executed ||
-	    (rexec->status != SIEVE_EXEC_TEMP_FAILURE &&
-	     rexec->status != SIEVE_EXEC_RESOURCE_LIMIT)) {
-		/* Execute implicit keep if the transaction failed or when the
-		   implicit keep was not canceled during transaction.
-		 */
-		if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
-			sieve_result_implicit_keep_execute(rexec);
-	}
+	/* Execute implicit keep if the transaction failed or when the
+	   implicit keep was not canceled during transaction.
+	 */
+	if (rexec->status != SIEVE_EXEC_OK || rexec->keep_implicit)
+		sieve_result_implicit_keep_execute(rexec);
 
 	/* Transaction commit/rollback */