diff --git a/TODO b/TODO
index e565a06260449c720d154fc22f1d2b7c94f89681..5f835262073ff15d333ef6f4f87da20cba7ea319 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
 Next (in order of descending priority/precedence):
 * Review sieve-address parsing implementation for past-end checks
 * Improve handling of old/corrupt binaries.
-* Move to 1.2 and start using mailbox_keyword_is_valid() and new const str. 
+* Move to 1.2 and start using and new const str. 
 * Resolve problems in variables extension: scope uses hash the wrong way and
   extension ids are emitted directly.
 
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 575d02eeb9e00f7f3eee790ba5920fb4fe144fce..90d6ceddf86f35d8d073964415a865ec7c76c682 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -118,7 +118,7 @@ static bool cmd_redirect_validate
 
 	/* We can only assess the validity of the outgoing address when it is 
 	 * a string literal. For runtime-generated strings this needs to be 
-	 * done at runtime 
+	 * done at runtime (FIXME!)
      */
 	if ( sieve_argument_is_string_literal(arg) ) {
 		string_t *address = sieve_ast_argument_str(arg);
diff --git a/src/lib-sieve/plugins/imapflags/cmd-addflag.c b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
index 17c11aa02e8cbda99e1fd34d6b09662bd67c3168..d65fa1b7e35a46dc42a046f964f854c3c427031b 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-addflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
@@ -75,13 +75,9 @@ static bool cmd_addflag_operation_execute
 	
 	sieve_runtime_trace(renv, "ADDFLAG command");
 	
-	t_push();
-	
 	if ( !ext_imapflags_command_operands_read
-		(renv, address, &flag_list, &storage, &var_index) ) {
-		t_pop();
+		(renv, address, &flag_list, &storage, &var_index) )
 		return FALSE;
-	}
 	
 	/* Iterate through all added flags */	
 	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && 
@@ -89,7 +85,5 @@ static bool cmd_addflag_operation_execute
 		ext_imapflags_add_flags(renv, storage, var_index, flag_item);
 	}
 
-	t_pop();
-	
 	return result;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
index 1ccb4846d594e74393193e38471cd2b08203426e..c2cce08396411a6147f795687e8cfd5ef3dc5b25 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
@@ -76,21 +76,15 @@ static bool cmd_removeflag_operation_execute
 	
 	sieve_runtime_trace(renv, "REMOVEFLAG command");
 	
-	t_push();
-	
 	if ( !ext_imapflags_command_operands_read
-		(renv, address, &flag_list, &storage, &var_index) ) {
-		t_pop();
+		(renv, address, &flag_list, &storage, &var_index) )
 		return FALSE;
-	}
 	
 	/* Iterate through all flags to remove */
 	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && 
 		flag_item != NULL ) {
 		ext_imapflags_remove_flags(renv, storage, var_index, flag_item);
 	}
-
-	t_pop();
 	
 	return result;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-setflag.c b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
index 74e03c6b86ae93d5d9bc9da793b648436d2ea5a6..2d166e974eb581c35d82659efefa3b4984ec6afd 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-setflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
@@ -74,13 +74,9 @@ static bool cmd_setflag_operation_execute
 	
 	sieve_runtime_trace(renv, "SETFLAG command");
 	
-	t_push();
-	
 	if ( !ext_imapflags_command_operands_read
-		(renv, address, &flag_list, &storage, &var_index) ) {
-		t_pop();
+		(renv, address, &flag_list, &storage, &var_index) ) 
 		return FALSE;
-	}
 			
 	/* Iterate through all flags to set */
 	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && 
@@ -88,8 +84,6 @@ static bool cmd_setflag_operation_execute
 		ext_imapflags_set_flags(renv, storage, var_index, flag_item);
 	}
 
-	t_pop();
-	
 	return result;
 }
 
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
index 3ebe325201b5d9978486032a7439a800c533000b..f8454f2ce6f187e3f423b51c5a2a5a9d83f9fa7d 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
@@ -18,6 +18,12 @@
 extern const struct sieve_argument tag_flags;
 extern const struct sieve_argument tag_flags_implicit;
 
+/*
+ * Forward declarations
+ */
+
+static bool flag_is_valid(const char *flag);
+
 /* Common functions */
 
 bool ext_imapflags_command_validate
@@ -77,7 +83,7 @@ bool ext_imapflags_command_validate
 			sieve_ast_argument_type(arg2) != SAAT_STRING_LIST ) 
 		{
 			sieve_command_validate_error(validator, cmd, 
-				"the %s %s command expects a string list (list of flags) as "
+				"the %s %s expects a string list (list of flags) as "
 				"second argument when two arguments are specified, "
 				"but %s was found",
 				cmd->command->identifier, sieve_command_type_name(cmd->command),
@@ -87,7 +93,28 @@ bool ext_imapflags_command_validate
 	} else
 		arg2 = arg;
 
-	return sieve_validator_argument_activate(validator, cmd, arg2, FALSE);	
+	if ( !sieve_validator_argument_activate(validator, cmd, arg2, FALSE) )
+		return FALSE;
+
+	if ( cmd->command != &tst_hasflag && sieve_argument_is_string_literal(arg2) ) {
+		struct ext_imapflags_iter fiter;
+		const char *flag;
+		
+		/* Warn the user about validity of verifiable flags */
+		ext_imapflags_iter_init(&fiter, sieve_ast_argument_str(arg));
+
+		while ( (flag=ext_imapflags_iter_get_flag(&fiter)) != NULL ) {
+			if ( !flag_is_valid(flag) ) {
+				sieve_command_validate_warning(validator, cmd,
+                	"IMAP flag '%s' specified for the %s command is invalid "
+					"and will be ignored (only first invalid is reported)",					
+					flag, cmd->command->identifier);
+				break;
+			}
+		}
+	}
+
+	return TRUE;
 }
 
 bool ext_imapflags_command_operands_dump
@@ -231,7 +258,13 @@ static bool flag_is_valid(const char *flag)
     	return FALSE;
     }
 	} else {
-		/* Custom keyword: currently nothing to validate */					
+		/* Custom keyword:
+		 *
+		 * The validity of the keyword cannot be validated until the 
+		 * target mailbox for the message is known. Meaning that the 
+		 * verfication of keyword can only be performed when the
+		 * action side effect is about to be executed.
+		 */					
 	}
 
 	return TRUE;  
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
index 7be3b498dea2fc0fa1c23c442be41e2e854f49b9..3df0f58c02657363ccceaa278f65a7ff11596601 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
@@ -18,6 +18,14 @@ enum ext_imapflags_opcode {
 	EXT_IMAPFLAGS_OPERATION_HASFLAG
 };
 
+/* Commands */
+
+extern const struct sieve_command cmd_setflag;
+extern const struct sieve_command cmd_addflag;
+extern const struct sieve_command cmd_removeflag;
+
+extern const struct sieve_command tst_hasflag;
+
 bool ext_imapflags_command_validate
 	(struct sieve_validator *validator, struct sieve_command_context *cmd);
 
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags.c b/src/lib-sieve/plugins/imapflags/ext-imapflags.c
index 3a785f4281814e8b65c8ebf60074217afd13250a..c09afcafd5dfdcdb0b2aae4c13541b23bf0015ec 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags.c
@@ -32,14 +32,6 @@ static bool ext_imapflags_validator_load(struct sieve_validator *valdtr);
 static bool ext_imapflags_runtime_load
 	(const struct sieve_runtime_env *renv);
 
-/* Commands */
-
-extern const struct sieve_command cmd_setflag;
-extern const struct sieve_command cmd_addflag;
-extern const struct sieve_command cmd_removeflag;
-
-extern const struct sieve_command tst_hasflag;
-
 /* Operations */
 
 extern const struct sieve_operation setflag_operation;
diff --git a/src/lib-sieve/plugins/imapflags/imapflags-errors.sieve b/src/lib-sieve/plugins/imapflags/imapflags-errors.sieve
index c3fae9ac12ad97443807b47b5355c2b25c47636e..02400c919aee15c72fc19bc68a886b1000bcf472 100644
--- a/src/lib-sieve/plugins/imapflags/imapflags-errors.sieve
+++ b/src/lib-sieve/plugins/imapflags/imapflags-errors.sieve
@@ -1,4 +1,4 @@
-require "imapflags";
+require "imap4flags";
 require "fileinto";
 
 setflag;
@@ -16,3 +16,5 @@ if hasflag 3 {
 if hasflag "flagvar" ["$MDNRequired", "\\Seen"] {
     removeflag "$MDNRequired";
 }
+
+removeflag "\\frop";
diff --git a/src/lib-sieve/plugins/imapflags/imapflags.sieve b/src/lib-sieve/plugins/imapflags/imapflags.sieve
index 53c0fdc18e9a6eefa38e4b7bf70c6fc86a2a4220..2503134b6a41f75358c9d96143166be3921845ad 100644
--- a/src/lib-sieve/plugins/imapflags/imapflags.sieve
+++ b/src/lib-sieve/plugins/imapflags/imapflags.sieve
@@ -25,4 +25,4 @@ if hasflag :count "ge" :comparator "i;ascii-numeric" "2" {
 	fileinto "imap-twoflags";
 }
 
-fileinto :flags "MDNRequired \\Draft" "INBOX";
+fileinto :flags "MDNRequired \\Draft 3[\"]\\4" "INBOX";
diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c
index 2b867fe2e00c494907998e7e2d23c6d76a3f78a4..e05fa43531b28a9e4bfe1157dc0e75c608533667 100644
--- a/src/lib-sieve/plugins/imapflags/tag-flags.c
+++ b/src/lib-sieve/plugins/imapflags/tag-flags.c
@@ -13,6 +13,8 @@
 
 #include "ext-imapflags-common.h"
 
+#include <ctype.h>
+
 static bool tag_flags_validate
 	(struct sieve_validator *validator,	struct sieve_ast_argument **arg, 
 		struct sieve_command_context *cmd);
@@ -274,7 +276,7 @@ static void seff_flags_print
 				str_printfa(flags, " %s", *keyword);
 			}
 
-			sieve_result_seffect_printf(rpenv, "add flags:%s", str_c(flags));
+			sieve_result_seffect_printf(rpenv, "add IMAP flags:%s", str_c(flags));
 		} T_END;
 	}
 }
@@ -296,12 +298,32 @@ static bool seff_flags_pre_execute
 
 	/* Assign mail keywords for subsequent mailbox_copy() */
 	if ( array_count(&ctx->keywords) > 0 ) {
+		unsigned int i;
+
 		if ( !array_is_created(&trans->keywords) ) {
 			pool_t pool = sieve_result_pool(aenv->result); 
 			p_array_init(&trans->keywords, pool, 2);
 		}
 		
-		array_append_array(&trans->keywords, &ctx->keywords);
+		for ( i = 0; i < array_count(&ctx->keywords); i++ ) {		
+			const char *const *keyword = array_idx(&ctx->keywords, i);
+			const char *kw_error;
+
+			if ( trans->box != NULL && 
+				mailbox_keyword_is_valid(trans->box, *keyword, &kw_error) )
+				array_append(&trans->keywords, keyword, 1);
+			else {
+				char *error = "";
+				if ( kw_error != NULL && *kw_error != '\0' ) {
+					error = t_strdup_noconst(kw_error);
+					error[0] = i_tolower(error[0]);
+				}
+				
+				sieve_result_warning(aenv, 
+					"specified IMAP keyword '%s' is invalid (ignored): %s", 
+					*keyword, error);
+			}
+		}
 	}
 
 	/* Assign mail flags for subsequent mailbox_copy() */
diff --git a/src/lib-sieve/plugins/imapflags/tst-hasflag.c b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
index d221bcf4145de050dd5f4afe18e7ab337fddfb66..9f1d55ee1fd41ba7cf3e70f66292e28a3169c760 100644
--- a/src/lib-sieve/plugins/imapflags/tst-hasflag.c
+++ b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
@@ -188,14 +188,9 @@ static bool tst_hasflag_operation_execute
 		}
 	}
 
-	t_push();
-		
 	if ( !ext_imapflags_command_operands_read
-		(renv, address, &flag_list, &storage, &var_index) ) {
-		t_pop();
+		(renv, address, &flag_list, &storage, &var_index) )
 		return FALSE;
-	}
-
 
 	matched = FALSE;
 	mctx = sieve_match_begin(renv->interp, mtch, cmp, flag_list); 	
@@ -209,8 +204,6 @@ static bool tst_hasflag_operation_execute
 
 	matched = sieve_match_end(mctx) || matched; 	
 	
-	t_pop();
-	
 	sieve_interpreter_set_test_result(renv->interp, matched);
 	
 	return TRUE;
diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h
index 7e5b2ab2de138bfc71c5378d560b8fe17802920f..cb27d82c8ad6fdebc0a739ac7aae4a6ad27d8151 100644
--- a/src/lib-sieve/sieve-commands.h
+++ b/src/lib-sieve/sieve-commands.h
@@ -94,6 +94,8 @@ const char *sieve_command_type_name(const struct sieve_command *command);
 		
 #define sieve_command_validate_error(validator, context, ...) \
 	sieve_validator_error(validator, (context)->ast_node, __VA_ARGS__)
+#define sieve_command_validate_warning(validator, context, ...) \
+	sieve_validator_warning(validator, (context)->ast_node, __VA_ARGS__)
 #define sieve_command_validate_critical(validator, context, ...) \
 	sieve_validator_critical(validator, (context)->ast_node, __VA_ARGS__)
 
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 8382c4cdedefe68b03cbc60b31bdc7b6c393f074..c44c31ca5967e16d564ff6b06012071353f95b7e 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -157,6 +157,16 @@ void sieve_result_error
 	va_end(args);
 }
 
+void sieve_result_warning
+	(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
+{
+	va_list args;
+	
+	va_start(args, fmt);	
+	sieve_vwarning(aenv->result->ehandler, _get_location(aenv), fmt, args); 
+	va_end(args);
+}
+
 void sieve_result_log
 	(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
 {
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index 79f016e3e92c1d7fd0ad207cb9ae3085fa835751..e7860ab69d18a701db72c1b3f6c151dc6698f26b 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -40,6 +40,9 @@ bool sieve_result_print(struct sieve_result *result, struct ostream *stream);
 void sieve_result_log
 	(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
 		ATTR_FORMAT(2, 3);
+void sieve_result_warning
+	(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
+		ATTR_FORMAT(2, 3);
 void sieve_result_error
 	(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
 		ATTR_FORMAT(2, 3);