diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c
index 8dbc976e10c2e11a42d1cbcbe93ca7d36190f9fb..157cd69a09ef452855186f162094e4b752f0cb2a 100644
--- a/src/lib-sieve/plugins/variables/cmd-set.c
+++ b/src/lib-sieve/plugins/variables/cmd-set.c
@@ -3,6 +3,7 @@
 #include "sieve-common.h"
 
 #include "sieve-code.h"
+#include "sieve-ast.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
@@ -62,7 +63,9 @@ const struct sieve_operation cmd_set_operation = {
  */
  
 static bool tag_modifier_is_instance_of
-	(struct sieve_validator *validator, struct sieve_ast_argument *arg)
+(struct sieve_validator *validator, 
+	struct sieve_command_context *cmdctx ATTR_UNUSED,	
+	struct sieve_ast_argument *arg)
 {
 	return ext_variables_set_modifier_find
 		(validator, sieve_ast_argument_tag(arg)) != NULL;
@@ -149,13 +152,13 @@ static bool cmd_set_validate(struct sieve_validator *validator,
 	struct sieve_command_context *cmd) 
 { 	
 	struct sieve_ast_argument *arg = cmd->first_positional;
-
+	
 	if ( !sieve_validate_positional_argument
 		(validator, cmd, arg, "name", 1, SAAT_STRING) ) {
 		return FALSE;
 	}
-	sieve_validator_argument_activate(validator, cmd, arg, TRUE);	
-	
+	ext_variables_variable_argument_activate(validator, arg);
+
 	arg = sieve_ast_argument_next(arg);
 	
 	if ( !sieve_validate_positional_argument
@@ -196,7 +199,6 @@ static bool cmd_set_operation_dump
 	sieve_code_descend(denv);
 
 	return 
-		sieve_opr_string_dump(denv, address) &&
 		sieve_opr_string_dump(denv, address);
 }
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index 932e7631905c0112ac17acdcadca7d68cf2bf448..c21c7d1a02c1431f698c4febfa97524745dba180 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -2,6 +2,8 @@
 #include "hash.h"
 
 #include "sieve-common.h"
+#include "sieve-ast.h"
+#include "sieve-commands.h"
 #include "sieve-validator.h"
 
 #include "ext-variables-common.h"
@@ -23,10 +25,51 @@ const struct ext_variables_set_modifier *default_set_modifiers[] = {
 const unsigned int default_set_modifiers_count = 
 	N_ELEMENTS(default_set_modifiers);
 
+/* Variable scope */
+
+struct sieve_variable_scope {
+	pool_t pool;
+  const char *identifier;
+
+	unsigned int next_index;
+	struct hash_table *variables;
+};
+
+struct sieve_variable_scope *sieve_variable_scope_create(pool_t pool) 
+{
+	struct sieve_variable_scope *scope;
+	
+	scope = p_new(pool, struct sieve_variable_scope, 1);
+	scope->pool = pool;
+	scope->variables = hash_create
+		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
+		
+	return scope;
+}
+
+struct sieve_variable *sieve_variable_scope_get_variable
+(struct sieve_variable_scope *scope, const char *identifier)
+{
+	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);
+	} 
+	
+	return var;
+}
+
 /* Validator context */
 
 struct ext_variables_validator_context {
 	struct hash_table *set_modifiers;
+	
+	struct sieve_variable_scope *main_scope;
 };
 
 static struct ext_variables_validator_context *
@@ -34,10 +77,12 @@ ext_variables_validator_context_create(struct sieve_validator *validator)
 {		
 	pool_t pool = sieve_validator_pool(validator);
 	struct ext_variables_validator_context *ctx;
+	struct sieve_ast *ast = sieve_validator_ast(validator);
 	
 	ctx = p_new(pool, struct ext_variables_validator_context, 1);
 	ctx->set_modifiers = hash_create
 		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
+	ctx->main_scope = sieve_variable_scope_create(sieve_ast_pool(ast));
 
 	sieve_validator_extension_set_context
 		(validator, ext_variables_my_id, (void *) ctx);
@@ -67,6 +112,45 @@ ext_variables_validator_context_get(struct sieve_validator *validator)
 		sieve_validator_extension_get_context(validator, ext_variables_my_id);
 }
 
+struct sieve_variable *ext_variables_validator_get_variable
+(struct sieve_validator *validator, const char *variable)
+{
+	struct ext_variables_validator_context *ctx = 
+		ext_variables_validator_context_get(validator);
+		
+	return sieve_variable_scope_get_variable(ctx->main_scope, variable);
+}
+
+/* Variable arguments */
+
+static bool arg_variable_generate
+	(struct sieve_generator *generator, struct sieve_ast_argument *arg, 
+		struct sieve_command_context *context);
+
+const struct sieve_argument variable_argument =
+	{ "@variable", NULL, NULL, NULL, arg_variable_generate };
+
+void ext_variables_variable_argument_activate
+(struct sieve_validator *validator, struct sieve_ast_argument *arg)
+{
+	struct ext_variables_validator_context *ctx;
+	struct sieve_variable *var;
+	
+	ctx = ext_variables_validator_context_get(validator);
+	var = sieve_variable_scope_get_variable(ctx->main_scope, 
+		sieve_ast_argument_strc(arg));
+
+	arg->argument = &variable_argument;
+	arg->context = (void *) var;
+}
+
+static bool arg_variable_generate
+(struct sieve_generator *generator, struct sieve_ast_argument *arg, 
+	struct sieve_command_context *context)
+{
+	return TRUE;
+}
+
 /* Set modifier registration */
 
 const struct ext_variables_set_modifier *ext_variables_set_modifier_find
@@ -79,3 +163,6 @@ const struct ext_variables_set_modifier *ext_variables_set_modifier_find
 		hash_lookup(ctx->set_modifiers, identifier);
 }
 
+/* Interpreter context */
+
+
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index 738b2a71305b523b763b6f791c7b23b5eaabe6fe..e8420cc18f0c3481f418f9df00de4d697f45fbd1 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -3,6 +3,8 @@
 
 #include "sieve-common.h"
 
+#include "sieve-ext-variables.h"
+
 extern int ext_variables_my_id;
 
 extern struct sieve_extension variables_extension;
@@ -36,5 +38,13 @@ struct ext_variables_set_modifier {
 
 const struct ext_variables_set_modifier *ext_variables_set_modifier_find
 	(struct sieve_validator *validator, const char *identifier);
+	
+/* Variables */
+
+void ext_variables_variable_argument_activate
+	(struct sieve_validator *validator, struct sieve_ast_argument *arg);
+
+struct sieve_variable *ext_variables_validator_get_variable
+(struct sieve_validator *validator, const char *variable);
 
 #endif /* __EXT_VARIABLES_COMMON_H */
diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
new file mode 100644
index 0000000000000000000000000000000000000000..42f8c9c63746c320c6f5c52c2583837790421686
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
@@ -0,0 +1,18 @@
+#ifndef __SIEVE_EXT_VARIABLES_H
+#define __SIEVE_EXT_VARIABLES_H
+
+/* Public interface for other extensions to use */
+
+struct sieve_variable {
+	const char *identifier;
+	unsigned int index;
+};
+
+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_scope *scope, const char *identifier);
+
+
+#endif /* __SIEVE_EXT_VARIABLES_H */