diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 965820750667c6d12c56d0e2f145a06c75ddca66..10ea349c75cab457e0a076c9c1f1f3282471dfc6 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -1627,7 +1627,7 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
 	struct sieve_result_action *ract_keep = &rexec->keep_action;
 	struct sieve_action *act_keep = &ract_keep->action;
 	int commit_status = SIEVE_EXEC_OK;
-	bool success = FALSE;
+	bool success = FALSE, temp_failure = FALSE;
 
 	switch (rexec->status) {
 	case SIEVE_EXEC_OK:
@@ -1637,7 +1637,15 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
 	case SIEVE_EXEC_RESOURCE_LIMIT:
 		if (rexec->committed)
 			break;
-		return rexec->status;
+
+		if (aexec_keep->state !=
+		    SIEVE_ACTION_EXECUTION_STATE_EXECUTED)
+			return rexec->status;
+		/* Roll back for temporary failure when no other action
+		   is committed. */
+		commit_status = rexec->status;
+		temp_failure = TRUE;
+		break;
 	default:
 		break;
 	}
@@ -1662,8 +1670,10 @@ sieve_result_implicit_keep_finalize(struct sieve_result_execution *rexec)
 	rexec->keep_finalizing = TRUE;
 
 	/* Start keep if necessary */
-	if (act_keep->def == NULL ||
-	    aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
+	if (temp_failure) {
+		rexec->keep_status = rexec->status;
+	} else if (act_keep->def == NULL ||
+		   aexec_keep->state != SIEVE_ACTION_EXECUTION_STATE_EXECUTED) {
 		sieve_result_implicit_keep_execute(rexec);
 	/* Switch to failure keep if necessary. */
 	} else if (rexec->keep_success && !success){