diff --git a/src/lib-sieve/plugins/regex/mcht-regex.c b/src/lib-sieve/plugins/regex/mcht-regex.c
index c3156f36ce1945f9fb27644ce7fb088b2170fc91..1c631e174f4f9e385369112af91cc98814f09228 100644
--- a/src/lib-sieve/plugins/regex/mcht-regex.c
+++ b/src/lib-sieve/plugins/regex/mcht-regex.c
@@ -20,6 +20,11 @@
 #include <ctype.h>
 #include <regex.h>
 
+/*
+ * Configuration
+ */
+
+#define MCHT_REGEX_MAX_SUBSTITUTIONS 64
 /* 
  * Forward declarations 
  */
@@ -108,7 +113,7 @@ bool mcht_regex_validate_context
 			if ( sieve_comparator_tag_is(carg, &i_ascii_casemap_comparator) )
 				cflags =  REG_EXTENDED | REG_NOSUB | REG_ICASE;
 			else if ( sieve_comparator_tag_is(carg, &i_octet_comparator) )
-				cflags =  REG_EXTENDED | REG_NOSUB ;
+				cflags =  REG_EXTENDED | REG_NOSUB;
 			else {
 				sieve_command_validate_error(validator, ctx->command_ctx, 
 					"regex match type only supports "
@@ -121,7 +126,7 @@ bool mcht_regex_validate_context
 	
 		carg = sieve_ast_argument_next(carg);
 	}
-
+		
 	/* Validate regular expression(s) */
 	if ( sieve_ast_argument_type(key_arg) == SAAT_STRING ) {
 		/* Single string */	
@@ -156,6 +161,9 @@ bool mcht_regex_validate_context
 struct mcht_regex_context {
 	ARRAY_DEFINE(reg_expressions, regex_t *);
 	int value_index;
+	struct sieve_match_values *mvalues;
+	regmatch_t *pmatch;
+	size_t nmatch;
 };
 
 void mcht_regex_match_init
@@ -167,7 +175,15 @@ void mcht_regex_match_init
 	t_array_init(&ctx->reg_expressions, 4);
 
 	ctx->value_index = -1;
-
+	ctx->mvalues = sieve_match_values_start(mctx->interp);
+	if ( ctx->mvalues != NULL ) {
+		ctx->pmatch = t_new(regmatch_t, MCHT_REGEX_MAX_SUBSTITUTIONS);
+		ctx->nmatch = MCHT_REGEX_MAX_SUBSTITUTIONS;
+	} else {
+		ctx->pmatch = NULL;
+		ctx->nmatch = 0;
+	}
+	
 	mctx->data = (void *) ctx;
 }
 
@@ -182,17 +198,19 @@ static regex_t *mcht_regex_get
 	int cflags;
 	
 	if ( ctx->value_index <= 0 ) {
-		regexp = p_new(pool_datastack_create(), regex_t, 1);
+		regexp = t_new(regex_t, 1);
 
 		if ( cmp == &i_octet_comparator ) 
-			cflags =  REG_EXTENDED | REG_NOSUB;
+			cflags =  REG_EXTENDED;
 		else if ( cmp ==  &i_ascii_casemap_comparator )
-			cflags =  REG_EXTENDED | REG_NOSUB | REG_ICASE;
+			cflags =  REG_EXTENDED | REG_ICASE;
 		else
 			return NULL;
+			
+		if ( ctx->mvalues == NULL ) cflags |= REG_NOSUB;
 
 		if ( (ret=regcomp(regexp, key, cflags)) != 0 ) {
-    		/* FIXME: Do something useful, i.e. report error somewhere */
+			/* FIXME: Do something useful, i.e. report error somewhere */
 			return NULL;
 		}
 
@@ -219,7 +237,28 @@ static bool mcht_regex_match
 
 	regexp = mcht_regex_get(ctx, mctx->comparator, key, key_index);
 	 
-	return ( regexec(regexp, val, 0, NULL, 0) == 0 );
+	if ( regexec(regexp, val, ctx->nmatch, ctx->pmatch, 0) == 0 ) {
+		size_t i;
+		int skipped = 0;
+		string_t *subst = t_str_new(32);
+		
+		for ( i = 0; i < ctx->nmatch; i++ ) {
+			str_truncate(subst, 0);
+			
+			if ( ctx->pmatch[i].rm_so != -1 ) {
+				if ( skipped > 0 )
+					sieve_match_values_skip(ctx->mvalues, skipped);
+					
+				str_append_n(subst, val + ctx->pmatch[i].rm_so, 
+					ctx->pmatch[i].rm_eo - ctx->pmatch[i].rm_so);
+				sieve_match_values_add(ctx->mvalues, subst);
+			} else 
+				skipped++;
+		}
+		return TRUE;
+	}
+	
+	return FALSE;
 }
 
 bool mcht_regex_match_deinit
diff --git a/src/lib-sieve/plugins/variables/Makefile.am b/src/lib-sieve/plugins/variables/Makefile.am
index 413a0b17080f3147b963604a2eae709ccfb51418..afcc3401ac20bd4d37681c22cada3d01f53b8a5d 100644
--- a/src/lib-sieve/plugins/variables/Makefile.am
+++ b/src/lib-sieve/plugins/variables/Makefile.am
@@ -22,6 +22,6 @@ libsieve_ext_variables_la_SOURCES = \
 
 noinst_HEADERS = \
 	ext-variables-common.h \
-	ext-variables-name.h
-
+	ext-variables-name.h \
+	sieve-ext-variables.h
 
diff --git a/src/lib-sieve/plugins/variables/variables-regex.sieve b/src/lib-sieve/plugins/variables/variables-regex.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..263be5ea78761710ab47c6cf6110af557545e1d7
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/variables-regex.sieve
@@ -0,0 +1,18 @@
+require "variables";
+require "regex";
+require "fileinto";
+
+set "match1" "Hutseflutsfropfrml";
+
+if string :regex "${match1}" "Hutse(.+)fropfrml" {
+	fileinto "${0}:${1}:${2}";
+}
+
+if string :regex "${match1}" "(.+)f((.+)f(.+))f(.+)" {
+	fileinto "${0}:${1}:${2}:${3}:${4}:${5}";
+}
+
+if string :regex "${match1}" "(.+)((g(.+)friep)|(f(.+)frop))(.+)" {
+	fileinto "${0}:${1}:${2}:${3}:${4}:${5}:${6}:${7}";
+}
+
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index 5c901e12e00a37f97b1e1b70cbdb31d023c1b966..079b2fe75f1a70f5c857445dbdd64c7d07802c33 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -303,6 +303,15 @@ void sieve_match_values_add_char
 		str_append_c(entry, c);
 }
 
+void sieve_match_values_skip
+	(struct sieve_match_values *mvalues, int num) 
+{
+	int i;
+	
+	for ( i = 0; i < num; i++ )
+		(void) sieve_match_values_add_entry(mvalues); 
+}
+
 void sieve_match_values_get
 	(struct sieve_interpreter *interp, unsigned int index, string_t **value_r) 
 {
diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h
index 96263f63d4066da876c6088cb812d6dd43c1e8d7..f4d358c4f9877f8d1a5c9aa29070799a1e19c9e1 100644
--- a/src/lib-sieve/sieve-match-types.h
+++ b/src/lib-sieve/sieve-match-types.h
@@ -83,6 +83,8 @@ void sieve_match_values_add
 	(struct sieve_match_values *mvalues, string_t *value);
 void sieve_match_values_add_char
 	(struct sieve_match_values *mvalues, char c);	
+void sieve_match_values_skip
+	(struct sieve_match_values *mvalues, int num);
 void sieve_match_values_get
 	(struct sieve_interpreter *interp, unsigned int index, string_t **value_r);