diff --git a/TODO b/TODO
index 721b96a585e8ddf2ae505764fadd141e3fb4de28..59b845084b84698df1a2f553073bf53d3a3c8ed9 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
 Current activities:
 
-* Build a sieve tool to filter an entire existing mailbox through a Sieve 
-  script.
+* Update include extension to latest draft (v13 currently):
+	- Implement :optional tag.
 
 Parallel plugin-based efforts:
 
@@ -15,9 +15,6 @@ Parallel plugin-based efforts:
 Next (mostly in order of descending priority/precedence):
 
 * Implement index extension
-* Update include extension to latest draft (v10 currently):
-	- Implement :optional tag.
-	- Implement required ManageSieve behavior
 * Add normalize() method to comparators to normalize the string before matching
   (for efficiency).
 * Improve error handling. 
diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c
index 1ad1d16213598df24d1e65de52ad4959b16e8f6b..8c6a8ae6141755a81f94ed965ebb266b858d8424 100644
--- a/src/lib-sieve/plugins/include/cmd-include.c
+++ b/src/lib-sieve/plugins/include/cmd-include.c
@@ -203,7 +203,8 @@ static bool cmd_include_validate
 		(struct cmd_include_context_data *) cmd->data;
 	struct sieve_script *script;
 	const char *script_path, *script_name;
-	enum sieve_error error = TRUE;
+	enum sieve_error error = SIEVE_ERROR_NONE;
+	bool include = TRUE;
 	
 	/* Check argument */
 	if ( !sieve_validate_positional_argument
@@ -251,18 +252,33 @@ static bool cmd_include_validate
 			sieve_validator_error_handler(valdtr), &error);
 
 	if ( script == NULL ) {
-		if ( error == SIEVE_ERROR_NOT_FOUND ) {
-			sieve_argument_validate_error(valdtr, arg, 
-				"included %s script '%s' does not exist", 
-				ext_include_script_location_name(ctx_data->location),
-				str_sanitize(script_name, 80));
+		if ( error != SIEVE_ERROR_NOT_FOUND ) {
+			return FALSE;
+		} else {
+			enum sieve_compile_flags cpflags =
+				sieve_validator_compile_flags(valdtr);
+
+			if ( (cpflags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 ) {
+				sieve_argument_validate_warning(valdtr, arg, 
+					"included %s script '%s' does not exist (ignored during upload)", 
+					ext_include_script_location_name(ctx_data->location),
+					str_sanitize(script_name, 80));
+				include = FALSE;
+			} else {
+				sieve_argument_validate_error(valdtr, arg, 
+					"included %s script '%s' does not exist", 
+					ext_include_script_location_name(ctx_data->location),
+					str_sanitize(script_name, 80));
+				return FALSE;
+			}
 		}
-		return FALSE;
 	}
 
-	ext_include_ast_link_included_script(cmd->ext, cmd->ast_node->ast, script);		
-	ctx_data->script = script;
-		
+	if ( include ) {
+		ext_include_ast_link_included_script(cmd->ext, cmd->ast_node->ast, script);		
+		ctx_data->script = script;
+	}
+	
 	arg = sieve_ast_arguments_detach(arg, 1);
 	
 	return TRUE;
@@ -279,18 +295,26 @@ static bool cmd_include_generate
 		(struct cmd_include_context_data *) cmd->data;
 	const struct ext_include_script_info *included;
 	unsigned int flags = ctx_data->include_once;
+	int ret;
 
-	/* Compile (if necessary) and include the script into the binary.
-	 * This yields the id of the binary block containing the compiled byte code.  
+	/* Upon upload ctx_data->script may be NULL if the script was not found. We
+	 * don't emit any code for this include command in that case.
 	 */
-	if ( !ext_include_generate_include
-		(cgenv, cmd, ctx_data->location, ctx_data->script, &included,
-			ctx_data->include_once) )
- 		return FALSE;
- 		
- 	(void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation);
-	(void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); 
-	(void)sieve_binary_emit_byte(cgenv->sblock, flags); 
+	if ( ctx_data->script != NULL ) {
+		/* Compile (if necessary) and include the script into the binary.
+		 * This yields the id of the binary block containing the compiled byte code.  
+		 */
+		if ( (ret=ext_include_generate_include
+			(cgenv, cmd, ctx_data->location, ctx_data->script, &included,
+				ctx_data->include_once)) < 0 )
+	 		return FALSE;
+	 		
+		if ( ret > 0 ) {
+		 	(void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation);
+			(void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); 
+			(void)sieve_binary_emit_byte(cgenv->sblock, flags);
+		}
+	}
  	 		
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index c47dcc21b210f550cf3162fe3464502fffe6388c..a5f4c983e2b41408790535c020b2ee9902248e43 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -462,7 +462,7 @@ struct sieve_variable_storage *ext_include_interpreter_get_global_variables
  * Including a script during code generation 
  */
 
-bool ext_include_generate_include
+int ext_include_generate_include
 (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd,
 	enum ext_include_script_location location, struct sieve_script *script, 
 	const struct ext_include_script_info **included_r, bool once)
@@ -470,7 +470,7 @@ bool ext_include_generate_include
 	const struct sieve_extension *this_ext = cmd->ext;
 	struct ext_include_context *ext_ctx =
 		(struct ext_include_context *)this_ext->context;
-	bool result = TRUE;
+	int result = 1;
 	struct sieve_ast *ast;
 	struct sieve_binary *sbin = cgenv->sbin;
 	struct sieve_generator *gentr = cgenv->gentr;
@@ -488,14 +488,14 @@ bool ext_include_generate_include
 	 * already. 
 	 */
 	if ( sieve_get_errors(ehandler) > 0 )
-		return FALSE;
+		return -1;
 		
 	/* Limit nesting level */
 	if ( ctx->nesting_depth >= ext_ctx->max_nesting_depth ) {
 		sieve_command_generate_error
 			(gentr, cmd, "cannot nest includes deeper than %d levels",
 				ext_ctx->max_nesting_depth);
-		return FALSE;
+		return -1;
 	}
 	
 	/* Check for circular include */
@@ -503,9 +503,18 @@ bool ext_include_generate_include
 		pctx = ctx;
 		while ( pctx != NULL ) {
 			if ( sieve_script_equals(pctx->script, script) ) {
+				/* Just drop circular include when uploading inactive script;
+				 * not an error
+				 */
+				if ( (cgenv->flags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 && 
+					(cgenv->flags & SIEVE_COMPILE_FLAG_ACTIVATED) == 0 ) {
+					sieve_command_generate_warning
+						(gentr, cmd, "circular include (ignored during upload)");
+					return 0;
+				}
+
 				sieve_command_generate_error(gentr, cmd, "circular include");
-				
-				return FALSE;
+				return -1;
 			}
 		
 			pctx = pctx->parent;
@@ -520,7 +529,7 @@ bool ext_include_generate_include
 	{	
 		struct sieve_binary_block *inc_block;
 		const char *script_name = sieve_script_name(script);
-		enum sieve_compile_flags cpflags = 0;
+		enum sieve_compile_flags cpflags = cgenv->flags;
 
 		/* Check whether include limit is exceeded */
 		if ( ext_include_binary_script_get_count(binctx) >= 
@@ -528,7 +537,7 @@ bool ext_include_generate_include
 	 		sieve_command_generate_error(gentr, cmd, 
 	 			"failed to include script '%s': no more than %u includes allowed", 
 				str_sanitize(script_name, 80), ext_ctx->max_includes);
-	 		return FALSE;			
+	 		return -1;
 		}
 		
 		/* No, allocate a new block in the binary and mark the script as included.
@@ -541,13 +550,15 @@ bool ext_include_generate_include
 		if ( (ast = sieve_parse(script, ehandler, NULL)) == NULL ) {
 	 		sieve_command_generate_error(gentr, cmd, 
 	 			"failed to parse included script '%s'", str_sanitize(script_name, 80));
-	 		return FALSE;
+	 		return -1;
 		}
 		
 		/* Included scripts inherit global variable scope */
 		(void)ext_include_create_ast_context(this_ext, ast, cmd->ast_node->ast);
 
-		if ( location != EXT_INCLUDE_LOCATION_GLOBAL )
+		if ( location == EXT_INCLUDE_LOCATION_GLOBAL )
+				cpflags &= ~SIEVE_RUNTIME_FLAG_NOGLOBAL;
+		else
 				cpflags |= SIEVE_RUNTIME_FLAG_NOGLOBAL;
 
 		/* Validate */
@@ -556,7 +567,7 @@ bool ext_include_generate_include
 				"failed to validate included script '%s'", 
 				str_sanitize(script_name, 80));
 	 		sieve_ast_unref(&ast);
-	 		return FALSE;
+	 		return -1;
 	 	}
 
 		/* Generate 
@@ -564,14 +575,14 @@ bool ext_include_generate_include
 		 * FIXME: It might not be a good idea to recurse code generation for 
 		 * included scripts.
 		 */
-	 	subgentr = sieve_generator_create(ast, ehandler);			
+	 	subgentr = sieve_generator_create(ast, ehandler, cpflags);			
 		ext_include_initialize_generator_context(cmd->ext, subgentr, ctx, script);
 			
 		if ( sieve_generator_run(subgentr, &inc_block) == NULL ) {
 			sieve_command_generate_error(gentr, cmd, 
 				"failed to generate code for included script '%s'", 
 				str_sanitize(script_name, 80));
-	 		result = FALSE;
+	 		result = -1;
 		}
 		
 		sieve_generator_free(&subgentr);
@@ -580,7 +591,7 @@ bool ext_include_generate_include
 		sieve_ast_unref(&ast);		
 	} 
 
-	if ( result ) *included_r = included;
+	if ( result > 0 ) *included_r = included;
 	
 	return result;
 }
diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h
index 4d27e80f0731b1b5b09a292ba5b3e5f229d681ef..c55617ecf6c3ed0ae29447753cc61d4b7a888cd3 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.h
+++ b/src/lib-sieve/plugins/include/ext-include-common.h
@@ -142,7 +142,7 @@ void ext_include_register_generator_context
 	(const struct sieve_extension *this_ext, 
 		const struct sieve_codegen_env *cgenv);
 
-bool ext_include_generate_include
+int ext_include_generate_include
 	(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd,
 		enum ext_include_script_location location, struct sieve_script *script, 
 		const struct ext_include_script_info **included_r, bool once);
diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h
index feaf9899c2d1492e543d93d5bbb3cad90d3439f0..49d872f3c6fd25e127f8c215bc9d837e6cff1509 100644
--- a/src/lib-sieve/sieve-commands.h
+++ b/src/lib-sieve/sieve-commands.h
@@ -200,6 +200,8 @@ bool sieve_command_block_exits_unconditionally
 
 #define sieve_command_generate_error(gentr, context, ...) \
 	sieve_generator_error(gentr, (context)->ast_node->source_line, __VA_ARGS__)
+#define sieve_command_generate_warning(gentr, context, ...) \
+	sieve_generator_warning(gentr, (context)->ast_node->source_line, __VA_ARGS__)
 
 /* Utility macros */
 
diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c
index 637a75c843564a0c42def5a817b779a05f4e7eba..d3224507378f44ce89be348660691caa396ada0c 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -76,7 +76,8 @@ struct sieve_generator {
 };
 
 struct sieve_generator *sieve_generator_create
-(struct sieve_ast *ast, struct sieve_error_handler *ehandler) 
+(struct sieve_ast *ast, struct sieve_error_handler *ehandler,
+	enum sieve_compile_flags flags) 
 {
 	pool_t pool;
 	struct sieve_generator *gentr;
@@ -91,6 +92,7 @@ struct sieve_generator *sieve_generator_create
 	sieve_error_handler_ref(ehandler);
 	
 	gentr->genenv.gentr = gentr;
+	gentr->genenv.flags = flags;
 	gentr->genenv.ast = ast;	
 	sieve_ast_ref(ast);
 
diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h
index 34a2c2aa3b9c3dce1c33f4701a16a5616801bace..654fdd43c1ce069d1fce010fb6d4fc5326d012e3 100644
--- a/src/lib-sieve/sieve-generator.h
+++ b/src/lib-sieve/sieve-generator.h
@@ -16,6 +16,8 @@ struct sieve_codegen_env {
 	struct sieve_generator *gentr;
 
 	struct sieve_instance *svinst;
+	enum sieve_compile_flags flags;
+
 	struct sieve_script *script;
 	struct sieve_ast *ast;
 
@@ -24,7 +26,8 @@ struct sieve_codegen_env {
 };
 
 struct sieve_generator *sieve_generator_create
-	(struct sieve_ast *ast, struct sieve_error_handler *ehandler);
+	(struct sieve_ast *ast, struct sieve_error_handler *ehandler,\
+		enum sieve_compile_flags flags);
 void sieve_generator_free(struct sieve_generator **generator);
 
 /* 
diff --git a/src/lib-sieve/sieve-types.h b/src/lib-sieve/sieve-types.h
index 5a3223bd0a9a125b2a655284ee6ccef3dbd038e2..3da2192ce8e01d032dc9c59a0c86804f53c2bd41 100644
--- a/src/lib-sieve/sieve-types.h
+++ b/src/lib-sieve/sieve-types.h
@@ -65,7 +65,14 @@ enum sieve_error {
  */
 
 enum sieve_compile_flags {
-	SIEVE_COMPILE_FLAG_NOGLOBAL = (1<<0)
+	/* No global extensions are allowed
+	 *  (as marked by sieve_global_extensions setting)
+	 */
+	SIEVE_COMPILE_FLAG_NOGLOBAL = (1<<0),
+	/* Script is being uploaded (usually through ManageSieve) */
+	SIEVE_COMPILE_FLAG_UPLOADED = (1<<1),
+	/* Script is being activated (usually through ManageSieve) */
+	SIEVE_COMPILE_FLAG_ACTIVATED = (1<<2),	
 };
 
 /* 
@@ -88,6 +95,9 @@ struct sieve_message_data {
  */
 
 enum sieve_runtime_flags {
+	/* No global extensions are allowed
+	 *  (as marked by sieve_global_extensions setting)
+	 */
 	SIEVE_RUNTIME_FLAG_NOGLOBAL = (1<<0)
 };
 
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 5e2a8526338ef510e4d4fe8fa440b05a1f2c5da7..bdd1dba0424633bd193e36acb974041ca81cfa11 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -177,9 +177,10 @@ bool sieve_validate
 
 static struct sieve_binary *sieve_generate
 (struct sieve_ast *ast, struct sieve_error_handler *ehandler, 
-	enum sieve_error *error_r)
+	enum sieve_compile_flags flags, enum sieve_error *error_r)
 {
-	struct sieve_generator *generator = sieve_generator_create(ast, ehandler);
+	struct sieve_generator *generator =
+		sieve_generator_create(ast, ehandler, flags);
 	struct sieve_binary *sbin = NULL;
 		
 	sbin = sieve_generator_run(generator, NULL);
@@ -222,7 +223,7 @@ struct sieve_binary *sieve_compile_script
  	}
  	
 	/* Generate */
-	if ( (sbin=sieve_generate(ast, ehandler, error_r)) == NULL ) {
+	if ( (sbin=sieve_generate(ast, ehandler, flags, error_r)) == NULL ) {
 		sieve_error(ehandler, sieve_script_name(script), "code generation failed");
 		
 		sieve_ast_unref(&ast);
diff --git a/src/lib-sievestorage/sieve-storage-save.c b/src/lib-sievestorage/sieve-storage-save.c
index 60ed394fb4ed5aace44f384ba9c3e9bba669c642..9fa2ee5070faefe86c1033045d80582e7445902a 100644
--- a/src/lib-sievestorage/sieve-storage-save.c
+++ b/src/lib-sievestorage/sieve-storage-save.c
@@ -316,6 +316,24 @@ struct sieve_script *sieve_storage_save_get_tempscript
 	return ctx->scriptobject;
 }
 
+bool sieve_storage_save_will_activate
+(struct sieve_save_context *ctx)
+{
+	const char *scriptname;
+	int ret = 0;
+
+	T_BEGIN {
+		ret = sieve_storage_get_active_scriptfile(ctx->storage, &scriptname);
+	
+		if ( ret > 0 ) {
+		 	/* Is the requested script active? */
+			ret = ( strcmp(ctx->scriptname, scriptname) == 0 ? 1 : 0 );
+		}
+	} T_END;
+
+	return ret;
+}
+
 int sieve_storage_save_commit(struct sieve_save_context **ctx)
 {
 	const char *dest_path;
diff --git a/src/lib-sievestorage/sieve-storage-save.h b/src/lib-sievestorage/sieve-storage-save.h
index 819b4cb1670d496fb00a6ba023f3747416ddfdfd..3e861d580ca447a11c07b78fc3a32d15d306c21b 100644
--- a/src/lib-sievestorage/sieve-storage-save.h
+++ b/src/lib-sievestorage/sieve-storage-save.h
@@ -19,6 +19,9 @@ int sieve_storage_save_finish(struct sieve_save_context *ctx);
 struct sieve_script *sieve_storage_save_get_tempscript
   (struct sieve_save_context *ctx);
 
+bool sieve_storage_save_will_activate
+	(struct sieve_save_context *ctx);
+
 void sieve_storage_save_cancel(struct sieve_save_context **ctx);
 
 int sieve_storage_save_commit(struct sieve_save_context **ctx);
diff --git a/src/lib-sievestorage/sieve-storage-script.c b/src/lib-sievestorage/sieve-storage-script.c
index 58567d6b30c0f40747eceea1b130570a8a9b48e3..a57784c93870983e47767e18a31d46cd918417b0 100644
--- a/src/lib-sievestorage/sieve-storage-script.c
+++ b/src/lib-sievestorage/sieve-storage-script.c
@@ -164,7 +164,7 @@ static int sieve_storage_read_active_link
 }
 
 static const char *sieve_storage_parse_link
-(struct sieve_storage *storage, const char *link)
+(struct sieve_storage *storage, const char *link, const char **scriptname_r)
 {
 	const char *fname, *scriptname, *scriptpath;
 
@@ -200,6 +200,9 @@ static const char *sieve_storage_parse_link
 		return NULL; 
 	}
 
+	if ( scriptname_r != NULL )
+		*scriptname_r = scriptname;
+
 	return fname;
 }
 
@@ -216,7 +219,7 @@ int sieve_storage_get_active_scriptfile
 		return ret;
 
 	/* Parse the link */
-	scriptfile = sieve_storage_parse_link(storage, link);
+	scriptfile = sieve_storage_parse_link(storage, link, NULL);
 
 	if (scriptfile == NULL) {
 		/* Obviously someone has been playing with our symlink,
@@ -230,6 +233,29 @@ int sieve_storage_get_active_scriptfile
 	return 1;
 }
 
+int sieve_storage_get_active_scriptname
+(struct sieve_storage *storage, const char **name_r)
+{
+	const char *link;
+	int ret;
+
+	*name_r = NULL;
+
+	/* Read the active link */
+	if ( (ret=sieve_storage_read_active_link(storage, &link)) <= 0 )
+		return ret;
+
+	if ( sieve_storage_parse_link(storage, link, name_r) == NULL ) {
+		/* Obviously someone has been playing with our symlink,
+		 * ignore this situation and report 'no active script'.
+		 * Activation should fix this situation.
+		 */
+		return 0;
+	}
+
+	return 1;
+}
+
 struct sieve_script *sieve_storage_get_active_script
 (struct sieve_storage *storage)
 {
@@ -251,7 +277,7 @@ struct sieve_script *sieve_storage_get_active_script
 	}
 
 	/* Parse the link */
-	scriptfile = sieve_storage_parse_link(storage, link);
+	scriptfile = sieve_storage_parse_link(storage, link, NULL);
 
 	if (scriptfile == NULL) {
 		/* Obviously someone has been playing with our symlink,
diff --git a/src/lib-sievestorage/sieve-storage-script.h b/src/lib-sievestorage/sieve-storage-script.h
index c440086ace6775f9ceab8090bcce4606251979e8..d446b0ecf47248e90ff0152977ee64920fc5d2d5 100644
--- a/src/lib-sievestorage/sieve-storage-script.h
+++ b/src/lib-sievestorage/sieve-storage-script.h
@@ -16,6 +16,8 @@ const char *sieve_storage_file_get_scriptname
 
 int sieve_storage_get_active_scriptfile
 	(struct sieve_storage *storage, const char **file_r);
+int sieve_storage_get_active_scriptname
+	(struct sieve_storage *storage, const char **name_r);
 
 struct sieve_script *sieve_storage_get_active_script
 	(struct sieve_storage *storage);
diff --git a/src/managesieve/cmd-putscript.c b/src/managesieve/cmd-putscript.c
index 1165e6fa5bc2616c3f3b3ca60a98be02bedac901..1fe8c07922863e48553e24f844a6f63d6a17f1f9 100644
--- a/src/managesieve/cmd-putscript.c
+++ b/src/managesieve/cmd-putscript.c
@@ -174,8 +174,6 @@ static bool cmd_putscript_finish_parsing(struct client_command_context *cmd)
 
 	if (args[0].type == MANAGESIEVE_ARG_EOL) {
 		struct sieve_script *script;
-
-		/* Last (and only) script */
 		bool success = TRUE;
 
 		/* Eat away the trailing CRLF */
@@ -194,9 +192,16 @@ static bool cmd_putscript_finish_parsing(struct client_command_context *cmd)
 		/* Try to compile script */
 		T_BEGIN {
 			struct sieve_error_handler *ehandler;
+			enum sieve_compile_flags cpflags = 
+				SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_UPLOADED;
 			struct sieve_binary *sbin;
 			string_t *errors;
 
+			/* Mark this as an activation when we are replacing the active script */
+			if ( sieve_storage_save_will_activate(ctx->save_ctx) ) {
+				cpflags |= SIEVE_COMPILE_FLAG_ACTIVATED;
+			}
+
 			/* Prepare error handler */
 			errors = str_new(default_pool, 1024);
 			ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE, 
@@ -204,7 +209,7 @@ static bool cmd_putscript_finish_parsing(struct client_command_context *cmd)
 
 			/* Compile */
 			if ( (sbin=sieve_compile_script
-				(script, ehandler, SIEVE_COMPILE_FLAG_NOGLOBAL, NULL)) == NULL ) {
+				(script, ehandler, cpflags, NULL)) == NULL ) {
 				client_send_no(client, str_c(errors));
 				success = FALSE;
 			} else {
diff --git a/src/managesieve/cmd-setactive.c b/src/managesieve/cmd-setactive.c
index 3e566cd79c23b8e04e5d525a4b1451bfd1d719dd..0cf518f6004f0a365a456b370b7e366007ee8435 100644
--- a/src/managesieve/cmd-setactive.c
+++ b/src/managesieve/cmd-setactive.c
@@ -2,7 +2,9 @@
  */
 
 #include "lib.h"
+#include "str.h"
 
+#include "sieve.h"
 #include "sieve-storage.h"
 #include "sieve-storage-script.h"
 
@@ -14,39 +16,88 @@ bool cmd_setactive(struct client_command_context *cmd)
 	struct client *client = cmd->client;
 	struct sieve_storage *storage = client->storage;
 	const char *scriptname;
-	struct sieve_script *script;;
+	struct sieve_script *script;
 	int ret;
 
 	/* <scriptname> */
 	if ( !client_read_string_args(cmd, 1, TRUE, &scriptname) )
 		return FALSE;
 
+	/* Activate, or .. */
 	if ( *scriptname != '\0' ) {
-		script = sieve_storage_script_init(storage, scriptname);
+		string_t *errors = NULL;
+		bool warnings = FALSE;
+		bool success = TRUE;
 
+		script = sieve_storage_script_init(storage, scriptname);
 		if ( script == NULL ) {
 			client_send_storage_error(client, storage);
 			return TRUE;
 		}
+
+		if ( sieve_storage_script_is_active(script) <= 0 ) {
+			/* Script is first being activated; compile it again without the UPLOAD
+			 * flag.
+			 */
+			T_BEGIN {
+				struct sieve_error_handler *ehandler;
+				enum sieve_compile_flags cpflags = 
+					SIEVE_COMPILE_FLAG_NOGLOBAL | SIEVE_COMPILE_FLAG_ACTIVATED;
+				struct sieve_binary *sbin;
+
+				/* Prepare error handler */
+				errors = str_new(default_pool, 1024);
+				ehandler = sieve_strbuf_ehandler_create(client->svinst, errors, TRUE, 
+					client->set->managesieve_max_compile_errors);
+
+				/* Compile */
+				if ( (sbin=sieve_compile_script
+					(script, ehandler, cpflags, NULL)) == NULL ) {
+					success = FALSE;
+				} else {
+					sieve_close(&sbin);
+				}
+
+				warnings = ( sieve_get_warnings(ehandler) > 0 );
+				sieve_error_handler_unref(&ehandler);
+			} T_END;
+		}
 	
-		ret = sieve_storage_script_activate(script);
-		if ( ret < 0 )
-			client_send_storage_error(client, storage);
-		else
-			client_send_ok(client, ret ? 
-				"Setactive completed." :
-				"Script is already active.");
+		/* Activate only when script is valid (or already active) */
+		if ( success ) {
+			/* Refresh activation no matter what; this can also resolve some erroneous
+			 * situations.
+			 */
+			ret = sieve_storage_script_activate(script);
+			if ( ret < 0 ) {
+				client_send_storage_error(client, storage);
+			} else {
+				if ( warnings ) {
+					client_send_okresp(client, "WARNINGS", str_c(errors));
+				} else {
+					client_send_ok(client, ( ret > 0 ? 
+						"Setactive completed." :
+						"Script is already active." ));
+				}
+			}
+		} else {
+			client_send_no(client, str_c(errors));
+		}
 
+		if ( errors != NULL )
+			str_free(&errors);
 		sieve_script_unref(&script);
+
+	/* ... deactivate */
 	} else {
 		ret = sieve_storage_deactivate(storage);
 		
 		if ( ret < 0 )
 			client_send_storage_error(client, storage);
 		else
-			client_send_ok(client, ret ?
+			client_send_ok(client, ( ret > 0 ?
  				"Active script is now deactivated." :
-				"No scripts currently active.");	
+				"No scripts currently active." ));	
 	}
 
 	return TRUE;