diff --git a/src/lib-sieve/plugins/relational/ext-relational.c b/src/lib-sieve/plugins/relational/ext-relational.c
index 5b46af083f8b2a1c552e8ddcae5f4412f9524d91..333320d06aab9065ee59cfd03253952a8eed7526 100644
--- a/src/lib-sieve/plugins/relational/ext-relational.c
+++ b/src/lib-sieve/plugins/relational/ext-relational.c
@@ -36,6 +36,11 @@ static bool ext_relational_interpreter_load
 
 /* Types */
 
+enum ext_relational_match_type {
+  RELATIONAL_VALUE,
+  RELATIONAL_COUNT
+};
+
 enum relational_match {
 	REL_MATCH_GREATER,
 	REL_MATCH_GREATER_EQUAL,
@@ -46,6 +51,9 @@ enum relational_match {
 	REL_MATCH_INVALID
 };
 
+#define REL_MATCH_INDEX(type, match) \
+	(type * REL_MATCH_INVALID + match)
+
 /* Extension definitions */
 
 static int ext_my_id;
@@ -69,6 +77,8 @@ static bool ext_relational_load(int ext_id)
 
 /* Validation */
 
+static const struct sieve_match_type rel_match_types[];
+
 static bool ext_relational_parameter_validate
 	(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
 		struct sieve_match_type_context *ctx)
@@ -86,7 +96,7 @@ static bool ext_relational_parameter_validate
 	/* Did we get a string in the first place ? */ 
 	if ( (*arg)->type != SAAT_STRING ) {
 		sieve_command_validate_error(validator, ctx->command_ctx, 
-			"the :%s match-type requires a constant string argument containing "
+			"the :%s match-type requires a constant string argument being "
 			"one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", "
 			"but %s was found", 
 			ctx->match_type->identifier, sieve_ast_argument_name(*arg));
@@ -145,7 +155,7 @@ static bool ext_relational_parameter_validate
 	
 	if ( rel_match >= REL_MATCH_INVALID ) {
 		sieve_command_validate_error(validator, ctx->command_ctx, 
-			"the :%s match-type requires a constant string argument containing "
+			"the :%s match-type requires a constant string argument being "
 			"one of \"gt\", \"ge\", \"lt\", \"le\", \"eq\" or \"ne\", "
 			"but \"%s\" was found", 
 			ctx->match_type->identifier, rel_match_id);
@@ -155,6 +165,13 @@ static bool ext_relational_parameter_validate
 	/* Delete argument */
 	*arg = sieve_ast_arguments_delete(*arg, 1);
 
+	/* Not used just yet */
+	ctx->ctx_data = (void *) rel_match;
+
+	/* Override the actual match type with a parameter-specific one */
+	ctx->match_type = &rel_match_types
+		[REL_MATCH_INDEX(ctx->match_type->ext_code, rel_match)];
+
 	return TRUE;
 }
 
@@ -163,13 +180,10 @@ static bool ext_relational_parameter_validate
 
 /* Extension access structures */
 
-enum ext_relational_match_type {
-  RELATIONAL_VALUE,
-  RELATIONAL_COUNT
-};
-
 extern const struct sieve_match_type_extension relational_match_extension;
 
+/* Parameter-independent match type objects, only used during validation */
+
 const struct sieve_match_type value_match_type = {
 	"value",
 	SIEVE_MATCH_TYPE_CUSTOM,
@@ -186,18 +200,50 @@ const struct sieve_match_type count_match_type = {
 	ext_relational_parameter_validate
 };
 
+/* Per-parameter match type objects, used for generation/interpretation 
+ * FIXME: This is fast, but kinda hideous.. however, otherwise context data 
+ * would have to be passed along with the match type objects everywhere.. also
+ * not such a great idea. This needs more thought
+ */
+
+#define VALUE_MATCH_TYPE(name, rel_match, func) {     \
+		"value-" name,                                    \
+		SIEVE_MATCH_TYPE_CUSTOM,                          \
+		&relational_match_extension,                      \
+		REL_MATCH_INDEX(RELATIONAL_VALUE, rel_match),     \
+		NULL,	                                            \
+	}
+
+#define COUNT_MATCH_TYPE(name, rel_match, func) {     \
+		"count-" name,                                    \
+		SIEVE_MATCH_TYPE_CUSTOM,                          \
+		&relational_match_extension,                      \
+		REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match),     \
+		NULL,	                                            \
+	}
+	
+static const struct sieve_match_type rel_match_types[] = { 
+	VALUE_MATCH_TYPE("gt", REL_MATCH_GREATER, NULL), 
+	VALUE_MATCH_TYPE("ge", REL_MATCH_GREATER_EQUAL, NULL), 
+	VALUE_MATCH_TYPE("lt", REL_MATCH_LESS, NULL), 
+	VALUE_MATCH_TYPE("le", REL_MATCH_LESS_EQUAL, NULL), 
+	VALUE_MATCH_TYPE("eq", REL_MATCH_EQUAL, NULL), 
+	VALUE_MATCH_TYPE("ne", REL_MATCH_NOT_EQUAL, NULL),
+
+	COUNT_MATCH_TYPE("gt", REL_MATCH_GREATER, NULL), 
+	COUNT_MATCH_TYPE("ge", REL_MATCH_GREATER_EQUAL, NULL), 
+	COUNT_MATCH_TYPE("lt", REL_MATCH_LESS, NULL), 
+	COUNT_MATCH_TYPE("le", REL_MATCH_LESS_EQUAL, NULL), 
+	COUNT_MATCH_TYPE("eq", REL_MATCH_EQUAL, NULL), 
+	COUNT_MATCH_TYPE("ne", REL_MATCH_NOT_EQUAL, NULL)
+};
+ 
 static const struct sieve_match_type *ext_relational_get_match 
 	(unsigned int code)
 {
-	switch ( code ) {
-	case RELATIONAL_VALUE:
-		return &value_match_type;
-	case RELATIONAL_COUNT:
-		return &count_match_type;
-	default:
-		break;
-	}
-	
+	if ( code < N_ELEMENTS(rel_match_types) ) 
+		return &rel_match_types[code];
+			
 	return NULL;
 }
 
diff --git a/src/lib-sieve/plugins/relational/relational.sieve b/src/lib-sieve/plugins/relational/relational.sieve
index 51179a38c90201608385d76949a264478d6f299c..1acc32f8f70123ef1ba066cc2e2b6f2c4b9fbbf2 100644
--- a/src/lib-sieve/plugins/relational/relational.sieve
+++ b/src/lib-sieve/plugins/relational/relational.sieve
@@ -5,4 +5,19 @@ if header :value "gt" :comparator "i;ascii-numeric" "x-spam-score" "2" {
 	stop;
 }
 
+if header :value "ne" :comparator "i;ascii-numeric" "x-spam-score" "2" {
+	discard;
+	stop;
+}
+
+if header :count "lt" :comparator "i;ascii-numeric" "x-spam-score" "2" {
+	discard;
+	stop;
+}
+
+if header :count "eq" :comparator "i;ascii-numeric" "x-spam-score" "2" {
+	discard;
+	stop;
+}
+
 keep;
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index 2ef62a893b78c3e0caab1b564f29ecbf91b2a681..f4f2ce3f8b650657c11f15ee89de947ee9f6a0af 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -265,6 +265,10 @@ static bool tag_match_type_validate
 	/* Skip tag */
 	*arg = sieve_ast_argument_next(*arg);
 	
+	/* Check whether this match type requires additional validation. 
+	 * Additional validation can override the match type recorded in the context 
+	 * for later code generation. 
+	 */
 	if ( mtch->validate != NULL ) {
 		return mtch->validate(validator, arg, mtctx);
 	}
@@ -311,22 +315,22 @@ const struct sieve_match_type *sieve_opr_match_type_read
 				return NULL;
 		} else {
 			int ext_id = -1;
-			const struct sieve_match_type_extension *ap_ext;
+			const struct sieve_match_type_extension *mtch_ext;
 
 			if ( sieve_binary_extension_get_by_index(sbin,
 				mtch_code - SIEVE_MATCH_TYPE_CUSTOM, &ext_id) == NULL )
 				return NULL; 
 
-			ap_ext = sieve_match_type_extension_get(interpreter, ext_id); 
+			mtch_ext = sieve_match_type_extension_get(interpreter, ext_id); 
  
-			if ( ap_ext != NULL ) {  	
+			if ( mtch_ext != NULL ) {  	
 				unsigned int code;
-				if ( ap_ext->match_type != NULL )
-					return ap_ext->match_type;
+				if ( mtch_ext->match_type != NULL )
+					return mtch_ext->match_type;
 		  	
 				if ( sieve_binary_read_byte(sbin, address, &code) &&
-					ap_ext->get_part != NULL )
-				return ap_ext->get_part(code);
+					mtch_ext->get_match != NULL )
+					return mtch_ext->get_match(code);
 			} else {
 				i_info("Unknown match-type modifier %d.", mtch_code); 
 			}
diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h
index 08814f1bd7028f5da1f230898060bec75b4716c4..9e8e6e112c2e92cef7548fdbd2659584871506ae 100644
--- a/src/lib-sieve/sieve-match-types.h
+++ b/src/lib-sieve/sieve-match-types.h
@@ -33,13 +33,18 @@ struct sieve_match_type_extension {
 	const struct sieve_match_type *match_type;
 	
 	/* ... or multiple: then the extension must handle emit/read */
-	const struct sieve_match_type *(*get_part)
+	const struct sieve_match_type *(*get_match)
 		(unsigned int code);
 };
 
 struct sieve_match_type_context {
 	struct sieve_command_context *command_ctx;
 	const struct sieve_match_type *match_type;
+	
+	/* Context data could be used in the future to pass data between validator and
+	 * generator in match types that use extra parameters. Currently not 
+	 * necessary, not even for the relational extension.
+	 */
 	void *ctx_data;
 };