diff --git a/src/lib-sieve/plugins/include/cmd-export.c b/src/lib-sieve/plugins/include/cmd-export.c
index 713db816595aca5d202f472f600b591b277d5523..049717abf639a66495895ccd01d3bf6906959e29 100644
--- a/src/lib-sieve/plugins/include/cmd-export.c
+++ b/src/lib-sieve/plugins/include/cmd-export.c
@@ -14,13 +14,6 @@
 
 static bool cmd_export_validate
   (struct sieve_validator *validator, struct sieve_command_context *cmd);
-static bool cmd_export_generate
-	(struct sieve_generator *generator, 
-		struct sieve_command_context *ctx ATTR_UNUSED);
-
-static bool opc_export_execute
-	(const struct sieve_operation *op, 
-		const struct sieve_runtime_env *renv, sieve_size_t *address);
 		
 /* Export command 
  * 
@@ -31,20 +24,9 @@ const struct sieve_command cmd_export = {
 	"export", 
 	SCT_COMMAND, 
 	1, 0, FALSE, FALSE,
-	NULL, NULL,
+	NULL, NULL, 
 	cmd_export_validate, 
-	cmd_export_generate, 
-	NULL
-};
-
-/* Export operation */
-
-const struct sieve_operation export_operation = { 
-	"export",
-	&include_extension,
-	EXT_INCLUDE_OPERATION_EXPORT,
-	NULL, 
-	opc_export_execute 
+	NULL, NULL
 };
 
 /*
@@ -77,38 +59,41 @@ static bool cmd_export_validate
 		return FALSE;
 	}
 	
-	if ( !sieve_validate_positional_argument
-		(validator, cmd, arg, "value", 1, SAAT_STRING_LIST) ) {
+	/* Register imported variable */
+	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
+		/* Single string */
+		const char *variable = sieve_ast_argument_strc(arg);
+		
+		if ( !ext_include_export_variable(arg->ast, variable) ) {
+			sieve_command_validate_error(validator, cmd, 
+				"cannot export imported variable '%s'", variable);
+			return FALSE;
+		}
+
+	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
+		/* String list */
+		struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg);
+		
+		while ( stritem != NULL ) {
+			const char *variable = sieve_ast_argument_strc(stritem);
+			
+			if ( !ext_include_export_variable(arg->ast, variable) ) {
+				sieve_command_validate_error(validator, cmd, 
+					"cannot export imported variable '%s'", variable);
+				return FALSE;
+			}
+	
+			stritem = sieve_ast_strlist_next(stritem);
+		}
+	} else {
+		/* Something else */
+		sieve_command_validate_error(validator, cmd, 
+			"the export command accepts a single string or string list argument, "
+			"but %s was found", 
+			sieve_ast_argument_name(arg));
 		return FALSE;
 	}
 	
-	//return sieve_validator_argument_activate(validator, cmd, arg, FALSE);
-	return TRUE;
-}
-
-/*
- * Generation
- */
-
-static bool cmd_export_generate
-(struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) 
-{
-	sieve_generator_emit_operation_ext	
-		(gentr, &export_operation, ext_include_my_id);
-
-	return TRUE;
-}
-
-/*
- * Interpretation
- */
-
-static bool opc_export_execute
-(const struct sieve_operation *op ATTR_UNUSED,
-	const struct sieve_runtime_env *renv, 
-	sieve_size_t *address ATTR_UNUSED)
-{	
+	(void)sieve_ast_arguments_detach(arg, 1);
 	return TRUE;
 }
-
-
diff --git a/src/lib-sieve/plugins/include/cmd-import.c b/src/lib-sieve/plugins/include/cmd-import.c
index 997cea655df1fca232820d7e8989146ecac306be..ad0102dd966c6e3adeb0b09d9f1d00c0f885ce94 100644
--- a/src/lib-sieve/plugins/include/cmd-import.c
+++ b/src/lib-sieve/plugins/include/cmd-import.c
@@ -14,13 +14,6 @@
 
 static bool cmd_import_validate
   (struct sieve_validator *validator, struct sieve_command_context *cmd); 
-static bool cmd_import_generate
-	(struct sieve_generator *generator, 
-		struct sieve_command_context *ctx ATTR_UNUSED);
-		
-static bool opc_import_execute
-	(const struct sieve_operation *op, 
-		const struct sieve_runtime_env *renv, sieve_size_t *address);
 		
 /* Import command 
  * 
@@ -33,18 +26,7 @@ const struct sieve_command cmd_import = {
 	1, 0, FALSE, FALSE,
 	NULL, NULL,
 	cmd_import_validate, 
-	cmd_import_generate, 
-	NULL
-};
-
-/* Import operation */
-
-const struct sieve_operation import_operation = { 
-	"import",
-	&include_extension,
-	EXT_INCLUDE_OPERATION_IMPORT,
-	NULL, 
-	opc_import_execute 
+	NULL, NULL
 };
 
 /*
@@ -75,39 +57,34 @@ static bool cmd_import_validate
 			"import command requires that variables extension is active");
 		return FALSE;
 	}
+		
+	/* Register imported variable */
+	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
+		/* Single string */
+		const char *variable = sieve_ast_argument_strc(arg);
+		
+		ext_include_import_variable(arg->ast, variable);
+
+	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
+		/* String list */
+		struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg);
+		
+		while ( stritem != NULL ) {
+			const char *variable = sieve_ast_argument_strc(stritem);
+			ext_include_import_variable(arg->ast, variable);
 	
-	if ( !sieve_validate_positional_argument
-		(validator, cmd, arg, "value", 1, SAAT_STRING_LIST) ) {
+			stritem = sieve_ast_strlist_next(stritem);
+		}
+	} else {
+		/* Something else */
+		sieve_command_validate_error(validator, cmd, 
+			"the import command accepts a single string or string list argument, "
+			"but %s was found", 
+			sieve_ast_argument_name(arg));
 		return FALSE;
 	}
 	
-	//return sieve_validator_argument_activate(validator, cmd, arg, FALSE);
-	return TRUE;
-}
-
-/*
- * Generation
- */
-
-static bool cmd_import_generate
-(struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) 
-{
-	sieve_generator_emit_operation_ext	
-		(gentr, &import_operation, ext_include_my_id);
-
-	return TRUE;
-}
-
-/*
- * Interpretation
- */
-
-static bool opc_import_execute
-(const struct sieve_operation *op ATTR_UNUSED,
-	const struct sieve_runtime_env *renv, 
-	sieve_size_t *address ATTR_UNUSED)
-{	
+	(void)sieve_ast_arguments_detach(arg, 1);
 	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 67aedc331c87141770a06731ee73022e16233d7d..4aacb8405ce7975852e411899d1e49b9fe2b6951 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -6,12 +6,20 @@
 #include "sieve-commands.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-ext-variables.h"
 
 #include "ext-include-common.h"
 
 /*
  * Forward declarations
  */
+ 
+/* AST context */
+
+struct ext_include_ast_context {
+	struct sieve_variable_scope *import_vars;
+	struct sieve_variable_scope *export_vars;
+};
 
 /* Generator context */
 
@@ -59,10 +67,14 @@ const char *ext_include_get_script_path
 (enum ext_include_script_location location, const char *script_name)
 {
 	/* FIXME: Hardcoded */	
-	if ( location == EXT_INCLUDE_LOCATION_PERSONAL )
+	switch ( location ) {
+	case EXT_INCLUDE_LOCATION_PERSONAL:
 		return t_strconcat(HARDCODED_PERSONAL_DIR, script_name, ".sieve", NULL);
-	else if ( location == EXT_INCLUDE_LOCATION_GLOBAL )
+	case EXT_INCLUDE_LOCATION_GLOBAL:
 		return t_strconcat(HARDCODED_GLOBAL_DIR, script_name, ".sieve", NULL);
+	default:
+		break;
+	}
 	
 	return NULL;
 }
@@ -84,6 +96,60 @@ static struct ext_include_main_context *ext_include_create_main_context
 	return ctx;
 }
 
+/* 
+ * AST context management
+ */
+
+static struct ext_include_ast_context *ext_include_create_ast_context
+(struct sieve_ast *ast)
+{	
+	struct ext_include_ast_context *ctx;
+
+	pool_t pool = sieve_ast_pool(ast);
+	ctx = p_new(pool, struct ext_include_ast_context, 1);
+	ctx->import_vars = sieve_variable_scope_create(pool);
+	ctx->export_vars = sieve_variable_scope_create(pool);
+	
+	return ctx;
+}
+
+static inline struct ext_include_ast_context *
+	ext_include_get_ast_context(struct sieve_ast *ast)
+{
+	struct ext_include_ast_context *ctx = (struct ext_include_ast_context *)
+		sieve_ast_extension_get_context(ast, ext_include_my_id);
+		
+	if ( ctx == NULL ) {
+		ctx = ext_include_create_ast_context(ast);
+		sieve_ast_extension_set_context(ast, ext_include_my_id, ctx);
+	}
+	
+	return ctx;
+}
+
+/* 
+ * Variable import-export
+ */
+ 
+void ext_include_import_variable(struct sieve_ast *ast, const char *variable)
+{
+	struct ext_include_ast_context *ctx = ext_include_get_ast_context(ast);
+	
+	(void)sieve_variable_scope_declare(ctx->import_vars, variable);
+}
+
+bool ext_include_export_variable(struct sieve_ast *ast, const char *variable)
+{
+	struct ext_include_ast_context *ctx = ext_include_get_ast_context(ast);
+	
+	if ( sieve_variable_scope_get_variable(ctx->import_vars, variable, FALSE) 
+		!= NULL )
+		return FALSE;
+		
+	(void)sieve_variable_scope_declare(ctx->export_vars, variable);
+	return TRUE;	
+}
+
 /* 
  * Generator context management 
  */
diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h
index 3440e209a0e5b7e5a8a8661bb633f7ebe78af96f..cb389e53e2d02b98aed87a2536cf7a4ae04113f3 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.h
+++ b/src/lib-sieve/plugins/include/ext-include-common.h
@@ -73,4 +73,9 @@ bool ext_include_execute_include
 	(const struct sieve_runtime_env *renv, unsigned int block_id);
 void ext_include_execute_return(const struct sieve_runtime_env *renv);
 
+/* Variables import-export */
+
+void ext_include_import_variable(struct sieve_ast *ast, const char *variable);
+bool ext_include_export_variable(struct sieve_ast *ast, const char *variable);
+
 #endif /* __EXT_INCLUDE_COMMON_H */
diff --git a/src/lib-sieve/plugins/include/ext-include.c b/src/lib-sieve/plugins/include/ext-include.c
index 999aaa3e83f416c3d88e5b179f8444124e16fe29..2d12ebb6e18da33a3011f9e83da59d4f1af83358 100644
--- a/src/lib-sieve/plugins/include/ext-include.c
+++ b/src/lib-sieve/plugins/include/ext-include.c
@@ -41,14 +41,10 @@ static bool ext_include_interpreter_load(struct sieve_interpreter *interp);
 
 extern const struct sieve_operation include_operation;
 extern const struct sieve_operation return_operation;
-extern const struct sieve_operation import_operation;
-extern const struct sieve_operation export_operation;
 
 static const struct sieve_operation *ext_include_operations[] = { 
 	&include_operation, 
-	&return_operation, 
-	&import_operation, 
-	&export_operation 
+	&return_operation
 };
 
 /* Extension definitions */
diff --git a/src/lib-sieve/plugins/include/include-variables-error2.sieve b/src/lib-sieve/plugins/include/include-variables-error2.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..f06a7df1ac23a021d7969fb49d22eeab6db0011b
--- /dev/null
+++ b/src/lib-sieve/plugins/include/include-variables-error2.sieve
@@ -0,0 +1,6 @@
+require "include";
+require "variables";
+import "frop";
+import ["friep", "frml"];
+export ["friep"];
+
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index 26691a0dd6fe219fe35de8da37a4a5a66dd2ef56..8c3a723558e0b17ce59b313e5271a0a6fce55ff2 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -79,19 +79,26 @@ struct sieve_variable_scope *sieve_variable_scope_create(pool_t pool)
 	return scope;
 }
 
-struct sieve_variable *sieve_variable_scope_get_variable
+struct sieve_variable *sieve_variable_scope_declare
 (struct sieve_variable_scope *scope, const char *identifier)
+{
+	struct sieve_variable *var = p_new(scope->pool, struct sieve_variable, 1);
+	var->identifier = identifier;
+	var->index = scope->next_index++;
+		
+	hash_insert(scope->variables, (void *) identifier, (void *) var);
+	
+	return var;
+}
+
+struct sieve_variable *sieve_variable_scope_get_variable
+(struct sieve_variable_scope *scope, const char *identifier, bool declare)
 {
 	struct sieve_variable *var = 
 		(struct sieve_variable *) hash_lookup(scope->variables, identifier);
 	
-	if ( var == NULL ) {
-		var = p_new(scope->pool, struct sieve_variable, 1);
-		var->identifier = identifier;
-		var->index = scope->next_index++;
-		
-		hash_insert(scope->variables, (void *) identifier, (void *) var);
-	} 
+	if ( var == NULL && declare )
+		var = sieve_variable_scope_declare(scope, identifier);
 	
 	return var;
 }
@@ -196,12 +203,12 @@ ext_variables_validator_context_get(struct sieve_validator *validator)
 }
 
 struct sieve_variable *ext_variables_validator_get_variable
-(struct sieve_validator *validator, const char *variable)
+(struct sieve_validator *validator, const char *variable, bool declare)
 {
 	struct ext_variables_validator_context *ctx = 
 		ext_variables_validator_context_get(validator);
 		
-	return sieve_variable_scope_get_variable(ctx->main_scope, variable);
+	return sieve_variable_scope_get_variable(ctx->main_scope, variable, declare);
 }
 
 bool sieve_ext_variables_is_active(struct sieve_validator *valdtr)
@@ -279,7 +286,7 @@ static struct sieve_ast_argument *ext_variables_variable_argument_create
 	struct sieve_ast_argument *arg;
 	
 	ctx = ext_variables_validator_context_get(validator);
-	var = sieve_variable_scope_get_variable(ctx->main_scope, variable);
+	var = sieve_variable_scope_get_variable(ctx->main_scope, variable, TRUE);
 
 	if ( var == NULL ) 
 		return NULL;
@@ -323,7 +330,7 @@ bool ext_variables_variable_assignment_activate
 		if ( cur_element->num_variable == -1 ) {
 			ctx = ext_variables_validator_context_get(validator);
 			var = sieve_variable_scope_get_variable
-				(ctx->main_scope, str_c(cur_element->identifier));
+				(ctx->main_scope, str_c(cur_element->identifier), TRUE);
 
 			arg->argument = &variable_argument;
 			arg->context = (void *) var;
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index 83eb4c99f66df10d0fdc0503d745c1b5dfef8964..b016f4acf102a21ebfe244fa7ee72c5e6293955c 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -72,7 +72,7 @@ bool ext_variables_variable_assignment_activate
 	struct sieve_command_context *cmd);
 
 struct sieve_variable *ext_variables_validator_get_variable
-(struct sieve_validator *validator, const char *variable);
+(struct sieve_validator *validator, const char *variable, bool declare);
 
 struct sieve_variable_storage *ext_variables_interpreter_get_storage
 	(struct sieve_interpreter *interp);
diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
index 120df375306a8f5ed26557cae1d986748231bec0..d2f025d5a2190aeac1bf2f3636efdbe7530762d2 100644
--- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h
+++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
@@ -22,8 +22,10 @@ struct sieve_variable {
 struct sieve_variable_scope;
 
 struct sieve_variable_scope *sieve_variable_scope_create(pool_t pool);
-struct sieve_variable *sieve_variable_scope_get_variable
+struct sieve_variable *sieve_variable_scope_declare
 	(struct sieve_variable_scope *scope, const char *identifier);
+struct sieve_variable *sieve_variable_scope_get_variable
+	(struct sieve_variable_scope *scope, const char *identifier, bool create);
 	
 /* 
  * Variable storage
diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c
index 5ab6edde176abd6f185c709d60d8a8f74fdefbdc..21fbc79064016da718938e8fbca0f7f7e4ae749d 100644
--- a/src/lib-sieve/sieve-ast.c
+++ b/src/lib-sieve/sieve-ast.c
@@ -6,6 +6,7 @@
 #include "array.h"
 
 #include "sieve-script.h"
+#include "sieve-extensions.h"
 
 #include "sieve-ast.h"
 
@@ -32,6 +33,8 @@ struct sieve_ast {
 		
 	struct sieve_ast_node *root;
 	
+	ARRAY_DEFINE(ext_contexts, void *);
+
 	ARRAY_DEFINE(node_links, struct sieve_ast_node_link);
 };
 
@@ -52,6 +55,7 @@ struct sieve_ast *sieve_ast_create(struct sieve_script *script)
 	ast->root->identifier = "ROOT";
 	
 	p_array_init(&ast->node_links, pool, 4);
+	p_array_init(&ast->ext_contexts, pool, sieve_extensions_get_count());
 	
 	return ast;
 }
@@ -123,6 +127,27 @@ const char *sieve_ast_type_name(enum sieve_ast_type ast_type) {
 	}
 }
 
+/* Extension support */
+
+inline void sieve_ast_extension_set_context
+	(struct sieve_ast *ast, int ext_id, void *context)
+{
+	array_idx_set(&ast->ext_contexts, (unsigned int) ext_id, &context);	
+}
+
+inline const void *sieve_ast_extension_get_context
+	(struct sieve_ast *ast, int ext_id) 
+{
+	void * const *ctx;
+
+	if  ( ext_id < 0 || ext_id >= (int) array_count(&ast->ext_contexts) )
+		return NULL;
+	
+	ctx = array_idx(&ast->ext_contexts, (unsigned int) ext_id);		
+
+	return *ctx;
+}
+
 /* AST-based error reporting */
 
 void sieve_ast_error
diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h
index cfd638b2fa6299d055f49446e991213f5f1e3437..cb962e8026f00d29cb2895f561776f93ed020c51 100644
--- a/src/lib-sieve/sieve-ast.h
+++ b/src/lib-sieve/sieve-ast.h
@@ -167,6 +167,12 @@ inline struct sieve_script *sieve_ast_script(struct sieve_ast *ast);
 
 const char *sieve_ast_type_name(enum sieve_ast_type ast_type);
 
+/* extension support */
+inline void sieve_ast_extension_set_context
+	(struct sieve_ast *ast, int ext_id, void *context);
+inline const void *sieve_ast_extension_get_context
+	(struct sieve_ast *ast, int ext_id);
+
 /* error reporting */
 void sieve_ast_error
 (struct sieve_error_handler *ehandler, sieve_error_vfunc_t vfunc,