diff --git a/sieve/tests/comparator.sieve b/sieve/tests/comparator.sieve
index 291276ab2a98575175607afffe5151dcec13802d..ae157db47c78db1ee2a1976f947ab115dfc4a8de 100644
--- a/sieve/tests/comparator.sieve
+++ b/sieve/tests/comparator.sieve
@@ -1,7 +1,7 @@
-if header :is :comparator "i;ascii-casemap" "from" "STEPHAN@drunksnipers.com" {
+if header :comparator "i;ascii-casemap" "from" "STEPHAN@drunksnipers.com" {
 	discard;
 
-	if address :is :comparator "i;octet" :domain "from" "drunksnipers.com" {
+	if address :comparator "i;octet" "from" "drunksnipers.com" {
 		keep;
 	}
 	stop;
diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index 9c08e2289d009ca85d72912aa9fad430ea1caaa9..7cac3ae3db0c4e446c99d62a5e271699ac145ab3 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -38,6 +38,7 @@ libsieve_a_SOURCES = \
 	sieve-result.c \
 	sieve-error.c \
 	sieve-comparators.c \
+	sieve-address-parts.c \
 	sieve-commands.c \
 	sieve-code.c \
 	$(tsts) \
@@ -57,6 +58,7 @@ noinst_HEADERS = \
 	sieve-result.h
 	sieve-error.h \
 	sieve-comparators.h \
+	sieve-address-parts.h \
 	sieve-commands.h \
 	sieve-code.h \
 	sieve-extensions.h \
diff --git a/src/lib-sieve/cmd-require.c b/src/lib-sieve/cmd-require.c
index 22388510c416e74f4a89f7ad7109f9858d95649c..67e40f935f63887da08662ee106567fbebd7c967 100644
--- a/src/lib-sieve/cmd-require.c
+++ b/src/lib-sieve/cmd-require.c
@@ -36,18 +36,25 @@ bool cmd_require_validate(struct sieve_validator *validator, struct sieve_comman
 	cmd->data = (void *) arg;
 	
 	/* Check argument and load specified extension(s) */
-	if ( sieve_ast_argument_type(arg) == SAAT_STRING )
+	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
 		/* Single string */
-		arg->context = (void *) sieve_validator_load_extension
+		int ext_id = sieve_validator_extension_load
 			(validator, cmd, sieve_ast_argument_strc(arg));	
-	else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
+
+		if ( ext_id < 0 ) return FALSE;
+		arg->context = (void *) ext_id;
+
+	} 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 ) {
-			stritem->context = (void *) sieve_validator_load_extension
+			int ext_id = sieve_validator_extension_load
 				(validator, cmd, sieve_ast_strlist_strc(stritem));
-			
+
+			if ( ext_id < 0 ) return FALSE;
+			stritem->context = (void *) ext_id;
+	
 			stritem = sieve_ast_strlist_next(stritem);
 		}
 	} else {
@@ -67,17 +74,17 @@ bool cmd_require_generate
 	struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data;
 	
 	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
-		struct sieve_extension *ext = (struct sieve_extension *) arg->context;
+		int ext_id = (int) arg->context;
 		
-		sieve_generator_register_extension(generator, ext);
+		sieve_generator_link_extension(generator, ext_id);
 	} 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 ) {
-			struct sieve_extension *ext = (struct sieve_extension *) stritem->context;
+			int ext_id = (int) stritem->context;
 		
-			sieve_generator_register_extension(generator, ext);
+			sieve_generator_link_extension(generator, ext_id);
 			
 			stritem = sieve_ast_strlist_next(stritem);
 		}
diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index 268ad1154294325b5361bad6ad8fed52634e190a..66fa6e8938d8a48ef8975afca4210a4c2a8b0c4a 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -2,12 +2,16 @@
 
 #include "sieve-extensions.h"
 #include "sieve-commands.h"
+#include "sieve-comparators.h"
+#include "sieve-address-parts.h"
+
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
 
 /* Forward declarations */
 
+static bool ext_envelope_load(int ext_id);
 static bool ext_envelope_validator_load(struct sieve_validator *validator);
 
 static bool ext_envelope_opcode_dump
@@ -22,14 +26,30 @@ static bool tst_envelope_generate
 
 /* Extension definitions */
 
+static int ext_my_id;
+
 const struct sieve_opcode envelope_opcode =
 	{ ext_envelope_opcode_dump, NULL };
-const struct sieve_extension envelope_extension = 
-	{ "envelope", ext_envelope_validator_load, NULL, NULL, &envelope_opcode, NULL };
+
+const struct sieve_extension envelope_extension = { 
+	"envelope", 
+	ext_envelope_load,
+	ext_envelope_validator_load, 
+	NULL, 
+	NULL, 
+	&envelope_opcode, 
+	NULL 
+};
 
 static const struct sieve_command envelope_test = 
 	{ "envelope", SCT_TEST, tst_envelope_registered, tst_envelope_validate, tst_envelope_generate, NULL };
 
+static bool ext_envelope_load(int ext_id) 
+{
+	ext_my_id = ext_id;
+	return TRUE;
+}
+
 /* Optional arguments */
 
 enum tst_envelope_optional {
@@ -43,8 +63,8 @@ enum tst_envelope_optional {
 static bool tst_envelope_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) 
 {
 	/* The order of these is not significant */
-	sieve_validator_link_comparator_tag(validator, cmd_reg, OPT_COMPARATOR);
-	sieve_validator_link_address_part_tags(validator, cmd_reg, OPT_ADDRESS_PART);
+	sieve_comparators_link_tag(validator, cmd_reg, OPT_COMPARATOR);
+	sieve_address_parts_link_tags(validator, cmd_reg, OPT_ADDRESS_PART);
 	sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE);
 	
 	return TRUE;
@@ -103,7 +123,7 @@ static bool ext_envelope_validator_load(struct sieve_validator *validator)
 static bool tst_envelope_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &envelope_extension);
+	(void)sieve_generator_emit_opcode_ext(generator, ext_my_id);
 
 	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index fcb23480e3ed034aadf2d838af21a9da3b839633..42d0cbb53b2e3a71f7581c0d24e70caf5d98bfab 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -7,6 +7,7 @@
 #include "sieve-interpreter.h"
 
 /* Forward declarations */
+static bool ext_fileinto_load(int ext_id);
 static bool ext_fileinto_validator_load(struct sieve_validator *validator);
 
 static bool ext_fileinto_opcode_dump
@@ -18,14 +19,31 @@ static bool cmd_fileinto_validate(struct sieve_validator *validator, struct siev
 static bool cmd_fileinto_generate(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
 /* Extension definitions */
+
+static int ext_my_id;
+
 const struct sieve_opcode fileinto_opcode = 
 	{ ext_fileinto_opcode_dump, ext_fileinto_opcode_execute };
 
-const struct sieve_extension fileinto_extension = 
-	{ "fileinto", ext_fileinto_validator_load, NULL, NULL, &fileinto_opcode, NULL	};
+const struct sieve_extension fileinto_extension = { 
+	"fileinto", 
+	ext_fileinto_load,
+	ext_fileinto_validator_load, 
+	NULL, 
+	NULL, 
+	&fileinto_opcode, 
+	NULL	
+};
+
 static const struct sieve_command fileinto_command = 
 	{ "fileinto", SCT_COMMAND, NULL, cmd_fileinto_validate, cmd_fileinto_generate, NULL };
 
+static bool ext_fileinto_load(int ext_id) 
+{
+	ext_my_id = ext_id;
+	return TRUE;
+}
+
 /* Validation */
 
 static bool cmd_fileinto_validate(struct sieve_validator *validator, struct sieve_command_context *cmd) 
@@ -64,7 +82,7 @@ static bool ext_fileinto_validator_load(struct sieve_validator *validator)
 static bool cmd_fileinto_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &fileinto_extension);
+	sieve_generator_emit_opcode_ext(generator, ext_my_id);
 
 	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index de5dd7c8a2d2a54e406f7d1f88f3cd5fc9b53768..141123a02234980a32451975c6ffb38be4232dec 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -8,24 +8,47 @@
 
 /* Forward declarations */
 
-static bool cmd_reject_validate(struct sieve_validator *validator, struct sieve_command_context *cmd);
-static bool cmd_reject_generate(struct sieve_generator *generator,	struct sieve_command_context *ctx);
- 
+static bool ext_reject_load(int ext_id);
 static bool ext_reject_validator_load(struct sieve_validator *validator);
 static bool ext_reject_generator_load(struct sieve_generator *generator);
 
+static bool cmd_reject_validate(struct sieve_validator *validator, struct sieve_command_context *cmd);
+static bool cmd_reject_generate(struct sieve_generator *generator,	struct sieve_command_context *ctx); 
+
 static bool ext_reject_opcode_dump
 	(struct sieve_interpreter *interp, struct sieve_binary *sbin, sieve_size_t *address);
 
 /* Extension definitions */
+
+static int ext_my_id;
+
 struct sieve_opcode reject_opcode = 
 	{ ext_reject_opcode_dump, NULL };
 	
-struct sieve_extension reject_extension = 
-	{ "reject", ext_reject_validator_load, ext_reject_generator_load, NULL, &reject_opcode, NULL };
-
-static const struct sieve_command reject_command = 
-	{ "reject", SCT_COMMAND, NULL, cmd_reject_validate, cmd_reject_generate, NULL };
+struct sieve_extension reject_extension = { 
+	"reject", 
+	ext_reject_load,
+	ext_reject_validator_load, 
+	ext_reject_generator_load, 
+	NULL, 
+	&reject_opcode, 
+	NULL 
+};
+
+static const struct sieve_command reject_command = { 
+	"reject", 
+	SCT_COMMAND, 
+	NULL, 
+	cmd_reject_validate, 
+	cmd_reject_generate, 
+	NULL 
+};
+
+static bool ext_reject_load(int ext_id) 
+{
+	ext_my_id = ext_id;
+	return TRUE;
+}
 
 /* 
  * Validation 
@@ -66,7 +89,7 @@ static bool ext_reject_validator_load(struct sieve_validator *validator)
 static bool cmd_reject_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &reject_extension);
+	sieve_generator_emit_opcode_ext(generator, ext_my_id);
 
 	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index 7d9d39dd1ff6e3baadbcd8a0db523481f4b633a3..13383a0d16c7a188d79b5e8b6060c03bfc79508b 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -10,6 +10,7 @@
 #include "sieve-interpreter.h"
 
 /* Forward declarations */
+static bool ext_vacation_load(int ext_id);
 static bool ext_vacation_validator_load(struct sieve_validator *validator);
 
 static bool ext_vacation_opcode_dump
@@ -20,12 +21,39 @@ static bool cmd_vacation_validate(struct sieve_validator *validator, struct siev
 static bool cmd_vacation_generate(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
 /* Extension definitions */
-const struct sieve_opcode vacation_opcode = 
-	{ ext_vacation_opcode_dump, NULL };
-const struct sieve_extension vacation_extension = 
-	{ "vacation", ext_vacation_validator_load, NULL, NULL, &vacation_opcode, NULL};
-static const struct sieve_command vacation_command = 
-	{ "vacation", SCT_COMMAND, cmd_vacation_registered, cmd_vacation_validate, cmd_vacation_generate, NULL };
+
+int ext_my_id;
+
+const struct sieve_opcode vacation_opcode = { 
+	ext_vacation_opcode_dump, 
+	NULL 
+};
+
+const struct sieve_extension vacation_extension = { 
+	"vacation", 
+	ext_vacation_load,
+	ext_vacation_validator_load, 
+	NULL, 
+	NULL, 
+	&vacation_opcode, 
+	NULL
+};
+
+static const struct sieve_command vacation_command = { 
+	"vacation", 
+	SCT_COMMAND, 
+	cmd_vacation_registered, 
+	cmd_vacation_validate, 
+	cmd_vacation_generate, 
+	NULL 
+};
+
+static bool ext_vacation_load(int ext_id)
+{
+	ext_my_id = ext_id;
+
+	return TRUE;
+}
 
 /* Tag validation */
 
@@ -243,7 +271,7 @@ static bool ext_vacation_validator_load(struct sieve_validator *validator)
 static bool cmd_vacation_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx) 
 {
-	sieve_generator_emit_opcode_ext(generator, &vacation_extension);
+	sieve_generator_emit_opcode_ext(generator, ext_my_id);
 
 	/* Generate arguments */
     if ( !sieve_generate_arguments(generator, ctx, NULL) )
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
new file mode 100644
index 0000000000000000000000000000000000000000..595961096ae2e034a3fd39e6eb122b4c4e51c83b
--- /dev/null
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -0,0 +1,291 @@
+#include <stdio.h>
+
+#include "lib.h"
+#include "compat.h"
+#include "hash.h"
+#include "array.h"
+
+#include "sieve-extensions.h"
+#include "sieve-code.h"
+#include "sieve-binary.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+
+#include "sieve-address-parts.h"
+
+#include <string.h>
+
+/* 
+ * Predeclarations 
+ */
+ 
+static struct sieve_interpreter_registry *addrp_registry = NULL;
+
+static void opr_address_part_emit
+	(struct sieve_binary *sbin, unsigned int code);
+static void opr_address_part_emit_ext
+	(struct sieve_binary *sbin, const struct sieve_extension *ext);
+
+/* 
+ * Comparator 'extension' 
+ */
+
+static int ext_my_id = -1;
+
+static bool addrp_extension_load(int ext_id);
+static bool addrp_validator_load(struct sieve_validator *validator);
+static bool addrp_interpreter_load(struct sieve_interpreter *interp);
+
+const struct sieve_extension address_part_extension = {
+	"@address-part",
+	addrp_extension_load,
+	addrp_validator_load,
+	NULL,
+	NULL, //addrp_interpreter_load,
+	NULL,
+	NULL
+};
+	
+static bool addrp_extension_load(int ext_id) 
+{
+	ext_my_id = ext_id;
+	return TRUE;
+}
+
+/* 
+ * Validator context:
+ *   name-based comparator registry. 
+ */
+ 
+struct addrp_validator_context {
+	struct hash_table *address_parts;
+};
+
+static inline struct addrp_validator_context *
+	get_validator_context(struct sieve_validator *validator)
+{
+	return (struct addrp_validator_context *) 
+		sieve_validator_extension_get_context(validator, ext_my_id);
+}
+ 
+void sieve_address_part_register
+	(struct sieve_validator *validator, const struct sieve_address_part *addrp) 
+{
+	struct addrp_validator_context *ctx = get_validator_context(validator);
+	
+	hash_insert(ctx->address_parts, (void *) addrp->identifier, (void *) addrp);
+}
+
+const struct sieve_address_part *sieve_address_part_find
+		(struct sieve_validator *validator, const char *addrp_name) 
+{
+	struct addrp_validator_context *ctx = get_validator_context(validator);
+
+  return 	(const struct sieve_address_part *) 
+  	hash_lookup(ctx->address_parts, addrp_name);
+}
+
+static bool addrp_validator_load(struct sieve_validator *validator)
+{
+	unsigned int i;
+	pool_t pool = sieve_validator_pool(validator);
+	
+	struct addrp_validator_context *ctx = 
+		p_new(pool, struct addrp_validator_context, 1);
+	
+	/* Setup comparator registry */
+	ctx->address_parts = hash_create
+		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
+
+	/* Register core comparators */
+	for ( i = 0; i < sieve_core_address_parts_count; i++ ) {
+		const struct sieve_address_part *addrp = sieve_core_address_parts[i];
+		
+		hash_insert(ctx->address_parts, (void *) addrp->identifier, (void *) addrp);
+	}
+
+	sieve_validator_extension_set_context(validator, ext_my_id, ctx);
+
+	return TRUE;
+}
+
+
+/*
+ * Address-part operand
+ */
+ 
+struct sieve_operand_class address_part_class = { "address-part", NULL };
+struct sieve_operand address_part_operand = { "address-part", &address_part_class, FALSE };
+
+/* 
+ * Address-part tag 
+ */
+ 
+static bool tag_address_part_validate
+	(struct sieve_validator *validator ATTR_UNUSED, 
+	struct sieve_ast_argument **arg, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
+{
+	const struct sieve_address_part *addrp;
+
+	/* Syntax:   
+	 *   ":localpart" / ":domain" / ":all"
+   */
+	
+	/* Get address_part from registry */
+	addrp = sieve_address_part_find(validator, sieve_ast_argument_tag(*arg));
+	
+	if ( addrp == NULL ) {
+		sieve_command_validate_error(validator, cmd, 
+			"unknown address-part modifier '%s' "
+			"(this error should not occur and is probably a bug)", 
+			sieve_ast_argument_strc(*arg));
+
+		return FALSE;
+	}
+
+	/* Store comparator in context */
+	(*arg)->context = (void *) addrp;
+	
+	/* Skip tag */
+	*arg = sieve_ast_argument_next(*arg);
+
+	return TRUE;
+}
+
+const struct sieve_argument address_localpart_tag = 
+	{ "localpart", tag_address_part_validate, NULL };
+const struct sieve_argument address_domain_tag = 
+	{ "domain", tag_address_part_validate, NULL };
+const struct sieve_argument address_all_tag = 
+	{ "all", tag_address_part_validate, NULL };
+
+/* Address part validation */
+
+void sieve_address_parts_link_tags
+	(struct sieve_validator *validator, 
+		struct sieve_command_registration *cmd_reg,
+		unsigned int id_code) 
+{
+	sieve_validator_register_tag
+		(validator, cmd_reg, &address_localpart_tag, id_code); 	
+	sieve_validator_register_tag
+		(validator, cmd_reg, &address_domain_tag, id_code); 	
+	sieve_validator_register_tag	
+		(validator, cmd_reg, &address_all_tag, id_code); 	
+}
+
+/* Code generation */
+
+static void opr_address_parts_emit
+	(struct sieve_binary *sbin, unsigned int code)
+{ 
+	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_ADDRESS_PART);
+	(void) sieve_binary_emit_byte(sbin, code);
+}
+
+static void opr_address_parts_emit_ext
+	(struct sieve_binary *sbin, int ext_id)
+{ 
+	unsigned char cmp_code = SIEVE_ADDRESS_PART_CUSTOM + 
+		sieve_binary_extension_get_index(sbin, ext_id);
+	
+	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_ADDRESS_PART);	
+	(void) sieve_binary_emit_byte(sbin, cmp_code);
+}
+
+const struct sieve_address_part *sieve_opr_address_part_read
+  (struct sieve_binary *sbin, sieve_size_t *address)
+{
+	unsigned int addrp_code;
+	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	
+	if ( operand == NULL || operand->class != &address_part_class ) 
+		return NULL;
+	
+	if ( sieve_binary_read_byte(sbin, address, &addrp_code) ) {
+		if ( addrp_code < SIEVE_ADDRESS_PART_CUSTOM ) {
+			if ( addrp_code < sieve_core_address_parts_count )
+				return sieve_core_address_parts[addrp_code];
+			else
+				return NULL;
+		} else {
+		  /*const struct sieve_extension *ext = 
+		  	sieve_binary_get_extension(sbin, cmp_code - SIEVE_ADDRESS_PART_CUSTOM);
+		  
+		  if ( ext != NULL )
+		  	return (const struct sieve_address_part *) 
+		  		sieve_interpreter_registry_get(addrp_registry, ext);	
+		  else*/
+		  	return NULL;
+		}
+	}		
+		
+	return NULL;
+}
+
+bool sieve_opr_address_part_dump(struct sieve_binary *sbin, sieve_size_t *address)
+{
+	sieve_size_t pc = *address;
+	const struct sieve_address_part *addrp = sieve_opr_address_part_read(sbin, address);
+	
+	if ( addrp == NULL )
+		return FALSE;
+		
+	printf("%08x:   ADDRP: %s\n", pc, addrp->identifier);
+	
+	return TRUE;
+}
+
+static bool tag_address_part_generate
+	(struct sieve_generator *generator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
+{
+	struct sieve_binary *sbin = sieve_generator_get_binary(generator);
+	struct sieve_address_part *addrp = (struct sieve_address_part *) (*arg)->context;
+	
+	if ( addrp->extension == NULL ) {
+		if ( addrp->code < SIEVE_ADDRESS_PART_CUSTOM )
+			opr_address_part_emit(sbin, addrp->code);
+		else
+			return FALSE;
+	} else {
+		//opr_comparator_emit_ext(sbin, cmp->extension);
+	} 
+		
+	*arg = sieve_ast_argument_next(*arg);
+	
+	return TRUE;
+}
+
+/* 
+ * Core address-part modifiers
+ */
+
+const struct sieve_address_part all_address_part = {
+	"all",
+	SIEVE_ADDRESS_PART_ALL,
+	NULL
+};
+
+const struct sieve_address_part local_address_part = {
+	"localpart",
+	SIEVE_ADDRESS_PART_LOCAL,
+	NULL
+};
+
+const struct sieve_address_part domain_address_part = {
+	"domain",
+	SIEVE_ADDRESS_PART_LOCAL,
+	NULL
+};
+
+const struct sieve_address_part *sieve_core_address_parts[] = {
+	&all_address_part, &local_address_part, &domain_address_part
+};
+
+const unsigned int sieve_core_address_parts_count =
+	(sizeof(sieve_core_address_parts) / sizeof(sieve_core_address_parts[0]));
+
+
diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h
new file mode 100644
index 0000000000000000000000000000000000000000..a89b67e0dfe601ec42923d882aa172e0f82f450b
--- /dev/null
+++ b/src/lib-sieve/sieve-address-parts.h
@@ -0,0 +1,42 @@
+#ifndef __SIEVE_ADDRESS_PARTS_H
+#define __SIEVE_ADDRESS_PARTS_H
+
+enum sieve_address_part_code {
+	SIEVE_ADDRESS_PART_ALL,
+	SIEVE_ADDRESS_PART_LOCAL,
+	SIEVE_ADDRESS_PART_DOMAIN,
+	SIEVE_ADDRESS_PART_CUSTOM
+};
+
+struct sieve_address_part {
+	const char *identifier;
+	
+	enum sieve_address_part_code code;
+	const struct sieve_extension *extension;
+};
+
+void sieve_address_parts_link_tags
+	(struct sieve_validator *validator, 
+		struct sieve_command_registration *cmd_reg,
+		unsigned int id_code);
+		
+void sieve_address_part_register
+	(struct sieve_validator *validator, const struct sieve_address_part *addrp); 
+const struct sieve_address_part *sieve_address_part_find
+		(struct sieve_validator *validator, const char *addrp_name);
+
+const struct sieve_address_part all_address_part;
+const struct sieve_address_part local_address_part;
+const struct sieve_address_part domain_address_part;
+
+extern const struct sieve_address_part *sieve_core_address_parts[];
+extern const unsigned int sieve_core_address_parts_count;
+
+const struct sieve_address_part *sieve_opr_address_part_read
+  (struct sieve_binary *sbin, sieve_size_t *address);
+bool sieve_opr_address_part_dump
+	(struct sieve_binary *sbin, sieve_size_t *address);
+
+void sieve_address_parts_init_registry(struct sieve_interpreter *interp);
+
+#endif /* __SIEVE_ADDRESS_PARTS_H */
diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c
index 1097e82271cfcaad148fc9b9ee9f45a3134bdd78..4357fddbff302937b294072b15bc7f5a86b8dcc9 100644
--- a/src/lib-sieve/sieve-binary.c
+++ b/src/lib-sieve/sieve-binary.c
@@ -5,19 +5,21 @@
 #include "hash.h"
 #include "array.h"
 
-#include "sieve-binary.h"
+#include "sieve-extensions.h"
 #include "sieve-code.h"
+#include "sieve-binary.h"
 
-struct sieve_extension_registration {
+struct sieve_binary_extension {
 	const struct sieve_extension *extension;
-	unsigned int opcode;
+	int ext_id;
+	int index;
 };
 
 struct sieve_binary {
 	pool_t pool;
 	
-	ARRAY_DEFINE(extensions, const struct sieve_extension *); 
-	struct hash_table *extension_index; 
+	ARRAY_DEFINE(extensions, struct sieve_binary_extension *); 
+	ARRAY_DEFINE(extension_index, struct sieve_binary_extension *); 
 	
 	buffer_t *data;
 	
@@ -36,9 +38,8 @@ struct sieve_binary *sieve_binary_create_new(void)
 	
 	sbin->data = buffer_create_dynamic(pool, 256);
 	
-	p_array_init(&sbin->extensions, pool, 4);
-	sbin->extension_index = hash_create
-		(pool, pool, 0, NULL, NULL);
+	p_array_init(&sbin->extensions, pool, sieve_extensions_get_count());
+	p_array_init(&sbin->extension_index, pool, sieve_extensions_get_count());
 		
 	return sbin;
 }
@@ -68,49 +69,58 @@ void sieve_binary_commit(struct sieve_binary *binary)
 
 /* Extension handling */
 
-static int sieve_binary_link_extension(struct sieve_binary *binary, const struct sieve_extension *extension) 
+int sieve_binary_extension_link
+	(struct sieve_binary *sbin, int ext_id) 
 {
-	array_append(&(binary->extensions), &extension, 1);
+	int index = array_count(&sbin->extensions);
+	const struct sieve_extension *ext = sieve_extension_get_by_id(ext_id); 
+	struct sieve_binary_extension *bext;
+
+	if ( ext != NULL ) {
+		bext = p_new(sbin->pool, struct sieve_binary_extension, 1);
+		bext->index = index;
+		bext->ext_id = ext_id;
+		bext->extension = ext;
 	
-	return array_count(&(binary->extensions)) - 1;
-}
-
-const struct sieve_extension *sieve_binary_get_extension(struct sieve_binary *binary, unsigned int index) 
-{
-	const struct sieve_extension * const *ext;
+		array_idx_set(&sbin->extensions, (unsigned int) index, &bext);
+		array_idx_set(&sbin->extension_index, (unsigned int) ext_id, &bext);
 	
-	if ( array_count(&(binary->extensions)) > index ) {
-		ext = array_idx(&(binary->extensions), index);
-		return *ext;
+		return index;
 	}
 	
-	return NULL;
+	return -1;
 }
 
-int sieve_binary_register_extension
-	(struct sieve_binary *sbin, const struct sieve_extension *extension) 
+const struct sieve_extension *sieve_binary_extension_get_by_index
+	(struct sieve_binary *sbin, int index, int *ext_id) 
 {
-	struct sieve_extension_registration *reg;
+	struct sieve_binary_extension * const *ext;
 	
-	reg = p_new(sbin->pool, struct sieve_extension_registration, 1);
-	reg->extension = extension;
-	reg->opcode = sieve_binary_link_extension(sbin, extension);
+	if ( index < (int) array_count(&sbin->extensions) ) {
+		ext = array_idx(&sbin->extensions, (unsigned int) index);
+		
+		if ( ext_id != NULL ) *ext_id = (*ext)->ext_id;
+		
+		return (*ext)->extension;
+	}
 	
-	hash_insert(sbin->extension_index, (void *) extension, (void *) reg);
+	if ( ext_id != NULL ) *ext_id = -1;
 	
-	return reg->opcode;
+	return NULL;
 }
 
-int sieve_binary_get_extension_index		
-	(struct sieve_binary *sbin, const struct sieve_extension *extension) 
+int sieve_binary_extension_get_index
+	(struct sieve_binary *sbin, int ext_id) 
 {
-  struct sieve_extension_registration *reg = 
-    (struct sieve_extension_registration *) hash_lookup(sbin->extension_index, extension);
-
-	if ( reg == NULL )
-		return -1;
-		    
-  return reg->opcode;
+	struct sieve_binary_extension * const *ext;
+	
+	if ( ext_id < (int) array_count(&sbin->extension_index) ) {
+		ext = array_idx(&sbin->extension_index, (unsigned int) ext_id);
+		
+		return (*ext)->index;
+	}
+	
+	return -1;
 }
 
 /*
diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h
index 7ddbc6c70ce9d61a91a771f6e5ca2d844550d915..fcea7fe2b3edf6dd6fd295f3fbe154361fd203ec 100644
--- a/src/lib-sieve/sieve-binary.h
+++ b/src/lib-sieve/sieve-binary.h
@@ -18,13 +18,13 @@ void sieve_binary_commit(struct sieve_binary *binary);
  * Extension handling 
  */
 
-int sieve_binary_register_extension
-	(struct sieve_binary *sbin, const struct sieve_extension *extension);
-const struct sieve_extension *sieve_binary_get_extension
-	(struct sieve_binary *binary, unsigned int index); 
-int sieve_binary_get_extension_index		
-	(struct sieve_binary *sbin, const struct sieve_extension *extension); 
-
+int sieve_binary_extension_link
+	(struct sieve_binary *sbin, int ext_id);
+const struct sieve_extension *sieve_binary_extension_get_by_index
+	(struct sieve_binary *sbin, int index, int *ext_id);
+int sieve_binary_extension_get_index
+	(struct sieve_binary *sbin, int ext_id);
+	
 /* 
  * Code emission 
  */
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 9e2efba0ee5136a48468ec6f909ad856e7f67d8e..4cc5eecce1a860199c0cc4f4e30f6c0262e18682 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -109,8 +109,10 @@ const struct sieve_operand *sieve_operand_read
 			else
 				return NULL;
 		} else {
+			int ext_id = -1;
 		  const struct sieve_extension *ext = 
-		  	sieve_binary_get_extension(sbin, operand - SIEVE_OPERAND_EXT_OFFSET);
+		  	sieve_binary_extension_get_by_index
+		  		(sbin, operand - SIEVE_OPERAND_EXT_OFFSET, &ext_id);
 		  
 		  if ( ext != NULL )
 		  	return ext->operand;	
@@ -554,10 +556,10 @@ inline sieve_size_t sieve_operation_emit_code
 }
 
 inline sieve_size_t sieve_operation_emit_code_ext
-	(struct sieve_binary *sbin, const struct sieve_extension *extension)
+	(struct sieve_binary *sbin, int ext_id)
 {	
 	unsigned char op = SIEVE_OPCODE_EXT_OFFSET + 
-		sieve_binary_get_extension_index(sbin, extension);
+		sieve_binary_extension_get_index(sbin, ext_id);
 	
 	return sieve_binary_emit_byte(sbin, op);
 }
@@ -574,8 +576,10 @@ const struct sieve_opcode *sieve_operation_read
 			else
 				return NULL;
 		} else {
+			int ext_id = -1;
 		  const struct sieve_extension *ext = 
-		  	sieve_binary_get_extension(sbin, opcode - SIEVE_OPCODE_EXT_OFFSET);
+		  	sieve_binary_extension_get_by_index
+		  		(sbin, opcode - SIEVE_OPCODE_EXT_OFFSET, &ext_id);
 		  
 		  if ( ext != NULL )
 		  	return ext->opcode;	
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index e8a50bea40dcc4673d9ea80c55008befc9f17dd3..624aec2878ec7fdeab5476d610c4fb6130d1943c 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -57,12 +57,12 @@ struct sieve_opr_stringlist_interface {
 
 enum sieve_core_operand {
 	SIEVE_OPERAND_OPTIONAL,
-  SIEVE_OPERAND_NUMBER,
-  SIEVE_OPERAND_STRING,
-  SIEVE_OPERAND_STRING_LIST,
-  SIEVE_OPERAND_COMPARATOR,
-  SIEVE_OPERAND_MATCH_TYPE,
-  SIEVE_OPERAND_ADDR_PART  
+	SIEVE_OPERAND_NUMBER,
+	SIEVE_OPERAND_STRING,
+	SIEVE_OPERAND_STRING_LIST,
+	SIEVE_OPERAND_COMPARATOR,
+	SIEVE_OPERAND_MATCH_TYPE,
+	SIEVE_OPERAND_ADDRESS_PART  
 };
 
 extern const struct sieve_operand *sieve_operands[];
@@ -125,7 +125,7 @@ extern const unsigned int sieve_opcode_count;
 inline sieve_size_t sieve_operation_emit_code
 	(struct sieve_binary *sbin, int opcode);
 inline sieve_size_t sieve_operation_emit_code_ext
-	(struct sieve_binary *sbin, const struct sieve_extension *extension);
+	(struct sieve_binary *sbin, int ext_id);
 const struct sieve_opcode *sieve_operation_read
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index fd93cb72e20ccee037e4fd80eca6dbbd0b7ef591..3847df7f2fcac40699af2083860922e0ae271495 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -2,7 +2,10 @@
 
 #include "lib.h"
 #include "compat.h"
+#include "hash.h"
+#include "array.h"
 
+#include "sieve-extensions.h"
 #include "sieve-code.h"
 #include "sieve-binary.h"
 #include "sieve-validator.h"
@@ -17,16 +20,143 @@
  * Predeclarations 
  */
  
-static struct sieve_interpreter_registry *cmp_registry = NULL;
+extern const struct sieve_comparator *sieve_core_comparators[];
+extern const unsigned int sieve_core_comparators_count;
 
 static void opr_comparator_emit
 	(struct sieve_binary *sbin, unsigned int code);
 static void opr_comparator_emit_ext
-	(struct sieve_binary *sbin, const struct sieve_extension *ext);
+	(struct sieve_binary *sbin, int ext_id);
 
+static int cmp_i_octet_compare
+	(const void *val1, size_t val1_size, const void *val2, size_t val2_size);
+static int cmp_i_ascii_casemap_compare
+	(const void *val1, size_t val1_size, const void *val2, size_t val2_size);
 
-static int cmp_i_octet_compare(const void *val1, size_t val1_size, const void *val2, size_t val2_size);
-static int cmp_i_ascii_casemap_compare(const void *val1, size_t val1_size, const void *val2, size_t val2_size);
+/* 
+ * Comparator 'extension' 
+ */
+
+static int ext_my_id = -1;
+
+static bool cmp_extension_load(int ext_id);
+static bool cmp_validator_load(struct sieve_validator *validator);
+static bool cmp_interpreter_load(struct sieve_interpreter *interp);
+
+const struct sieve_extension comparator_extension = {
+	"@comparator",
+	cmp_extension_load,
+	cmp_validator_load,
+	NULL,
+	cmp_interpreter_load,
+	NULL,
+	NULL
+};
+	
+static bool cmp_extension_load(int ext_id) 
+{
+	ext_my_id = ext_id;
+	return TRUE;
+}
+
+/* 
+ * Validator context:
+ *   name-based comparator registry. 
+ */
+ 
+struct cmp_validator_context {
+	struct hash_table *comparators;
+};
+
+static inline struct cmp_validator_context *
+	get_validator_context(struct sieve_validator *validator)
+{
+	return (struct cmp_validator_context *) 
+		sieve_validator_extension_get_context(validator, ext_my_id);
+}
+ 
+void sieve_comparator_register
+	(struct sieve_validator *validator, const struct sieve_comparator *cmp) 
+{
+	struct cmp_validator_context *ctx = get_validator_context(validator);
+	
+	hash_insert(ctx->comparators, (void *) cmp->identifier, (void *) cmp);
+}
+
+const struct sieve_comparator *sieve_comparator_find
+		(struct sieve_validator *validator, const char *cmp_name) 
+{
+	struct cmp_validator_context *ctx = get_validator_context(validator);
+
+  return 	(const struct sieve_comparator *) 
+  	hash_lookup(ctx->comparators, cmp_name);
+}
+
+static bool cmp_validator_load(struct sieve_validator *validator)
+{
+	unsigned int i;
+	pool_t pool = sieve_validator_pool(validator);
+	
+	struct cmp_validator_context *ctx = p_new(pool, struct cmp_validator_context, 1);
+	
+	/* Setup comparator registry */
+	ctx->comparators = hash_create(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
+
+	/* Register core comparators */
+	for ( i = 0; i < sieve_core_comparators_count; i++ ) {
+		const struct sieve_comparator *cmp = sieve_core_comparators[i];
+		
+		hash_insert(ctx->comparators, (void *) cmp->identifier, (void *) cmp);
+	}
+
+	sieve_validator_extension_set_context(validator, ext_my_id, ctx);
+
+	return TRUE;
+}
+
+/*
+ * Interpreter context:
+ */
+
+struct cmp_interpreter_context {
+	ARRAY_DEFINE(cmp_extensions, 
+		const struct sieve_comparator_extension *); 
+};
+
+static inline struct cmp_interpreter_context *
+	get_interpreter_context(struct sieve_interpreter *interpreter)
+{
+	return (struct cmp_interpreter_context *) 
+		sieve_interpreter_extension_get_context(interpreter, ext_my_id);
+}
+
+static const struct sieve_comparator_extension *sieve_comparator_extension_get
+	(struct sieve_interpreter *interpreter, int ext_id)
+{
+	struct cmp_interpreter_context *ctx = get_interpreter_context(interpreter);
+	
+	if ( ext_id > 0 && ext_id < (int) array_count(&ctx->cmp_extensions) ) {
+		return (const struct sieve_comparator_extension *)
+			array_idx(&ctx->cmp_extensions, (unsigned int) ext_id);
+	}
+	
+	return NULL;
+}
+
+static bool cmp_interpreter_load(struct sieve_interpreter *interpreter)
+{
+	pool_t pool = sieve_interpreter_pool(interpreter);
+	
+	struct cmp_interpreter_context *ctx = 
+		p_new(pool, struct cmp_interpreter_context, 1);
+	
+	/* Setup comparator registry */
+	p_array_init(&ctx->cmp_extensions, default_pool, 4);
+
+	sieve_interpreter_extension_set_context(interpreter, ext_my_id, ctx);
+	
+	return TRUE;
+}
 
 /*
  * Comparator operand
@@ -69,7 +199,7 @@ static bool tag_comparator_validate
 	}
 	
 	/* Get comparator from registry */
-	cmp = sieve_validator_find_comparator(validator, sieve_ast_argument_strc(*arg));
+	cmp = sieve_comparator_find(validator, sieve_ast_argument_strc(*arg));
 	
 	if ( cmp == NULL ) {
 		sieve_command_validate_error(validator, cmd, 
@@ -78,15 +208,22 @@ static bool tag_comparator_validate
 		return FALSE;
 	}
 	
-	/* String argument not needed during code generation, so delete it */
+	/* String argument not needed during code generation, so delete it from argument list */
 	*arg = sieve_ast_arguments_delete(*arg, 1);
-	
+
 	/* Store comparator in context */
 	tag->context = (void *) cmp;
 	
 	return TRUE;
 }
 
+void sieve_comparators_link_tag
+	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg,	
+		unsigned int id_code) 
+{
+	sieve_validator_register_tag(validator, cmd_reg, &comparator_tag, id_code); 	
+}
+
 /* Code generation */
 
 static void opr_comparator_emit
@@ -97,10 +234,10 @@ static void opr_comparator_emit
 }
 
 static void opr_comparator_emit_ext
-	(struct sieve_binary *sbin, const struct sieve_extension *ext)
+	(struct sieve_binary *sbin, int ext_id)
 { 
 	unsigned char cmp_code = SIEVE_COMPARATOR_CUSTOM + 
-		sieve_binary_get_extension_index(sbin, ext);
+		sieve_binary_extension_get_index(sbin, ext_id);
 	
 	(void) sieve_operand_emit_code(sbin, SIEVE_OPERAND_COMPARATOR);	
 	(void) sieve_binary_emit_byte(sbin, cmp_code);
@@ -122,13 +259,15 @@ const struct sieve_comparator *sieve_opr_comparator_read
 			else
 				return NULL;
 		} else {
+		  /*int ext_id = -1;
 		  const struct sieve_extension *ext = 
-		  	sieve_binary_get_extension(sbin, cmp_code - SIEVE_COMPARATOR_CUSTOM);
+		  	sieve_binary_extension_get_by_index
+		  		(sbin, cmp_code - SIEVE_COMPARATOR_CUSTOM, &ext_id);
 		  
 		  if ( ext != NULL )
-		  	return (const struct sieve_comparator *) 
-		  		sieve_interpreter_registry_get(cmp_registry, ext);	
-		  else
+		  	struct sieve_comparator_extension *cext = 
+		  		sieve_comparator_extension_get(cmp_registry, ext);	
+		  else*/
 		  	return NULL;
 		}
 	}		
@@ -162,7 +301,7 @@ static bool tag_comparator_generate
 		else
 			return FALSE;
 	} else {
-		opr_comparator_emit_ext(sbin, cmp->extension);
+		//opr_comparator_emit_ext(sbin, cmp->ext);
 	} 
 		
 	*arg = sieve_ast_argument_next(*arg);
@@ -195,8 +334,8 @@ const struct sieve_comparator *sieve_core_comparators[] = {
 const unsigned int sieve_core_comparators_count =
 	(sizeof(sieve_core_comparators) / sizeof(sieve_core_comparators[0]));
 
-
-static int cmp_i_octet_compare(const void *val1, size_t val1_size, const void *val2, size_t val2_size)
+static int cmp_i_octet_compare(const void *val1, size_t val1_size, 
+	const void *val2, size_t val2_size)
 {
 	int result;
 
@@ -242,13 +381,3 @@ static int cmp_i_ascii_casemap_compare(const void *val1, size_t val1_size, const
 	return result;
 }
 
-/* 
- * Registry 
- */
- 
-void sieve_comparators_init_registry(struct sieve_interpreter *interp) 
-{
-	cmp_registry = sieve_interpreter_registry_init(interp, "comparators");
-}
-
-
diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h
index 77da4c23cb344b5f3ea21d5ca1afe654f4851a6e..e2d8026dd67b9a87d3cabdfdde1c7fdfeabba2c1 100644
--- a/src/lib-sieve/sieve-comparators.h
+++ b/src/lib-sieve/sieve-comparators.h
@@ -16,25 +16,32 @@ struct sieve_comparator {
 	/* Equality, ordering, prefix and substring match */
 	
 	/* ( output similar to strncmp ) */
-	int (*compare)(const void *val1, size_t val1_size, const void *val2, size_t val2_size);
+	int (*compare)(const void *val1, size_t val1_size, 
+		const void *val2, size_t val2_size);
 };
 
-extern const struct sieve_argument comparator_tag;
+struct sieve_comparator_extension {
+	const struct sieve_comparator *comparator;
+	const struct sieve_comparator *(*read)
+		(struct sieve_binary *sbin, sieve_size_t *address);
+};
 
+void sieve_comparators_link_tag
+	(struct sieve_validator *validator, 
+		struct sieve_command_registration *cmd_reg,	
+		unsigned int id_code);
 
 const struct sieve_comparator i_octet_comparator;
 const struct sieve_comparator i_ascii_casemap_comparator;
 
-extern const struct sieve_comparator *sieve_core_comparators[];
-extern const unsigned int sieve_core_comparators_count;
+void sieve_comparator_register
+	(struct sieve_validator *validator, const struct sieve_comparator *cmp);
+const struct sieve_comparator *sieve_comparator_find
+		(struct sieve_validator *validator, const char *cmp_name);
 
 const struct sieve_comparator *sieve_opr_comparator_read
   (struct sieve_binary *sbin, sieve_size_t *address);
 bool sieve_opr_comparator_dump
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
-void sieve_comparators_init_registry(struct sieve_interpreter *interp);
-
-
-
 #endif /* __SIEVE_COMPARATORS_H */
diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index 68d53d1bd4c189d13afed53d8acd77b902c0faad..7b7580c4ff4d0f31c7165778d3b73214caaec2ae 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -1,35 +1,162 @@
 #include "lib.h"
+#include "mempool.h"
 #include "hash.h"
+#include "array.h"
 
 #include "sieve-extensions.h"
 
+/* Static pre-declarations */
+
+static void sieve_extensions_init_registry(void);
+static void sieve_extensions_deinit_registry(void);
+
+/* Core extensions */
+
+extern const struct sieve_extension comparator_extension;
+extern const struct sieve_extension address_part_extension;
+
+/* Base extensions */
+
 extern const struct sieve_extension fileinto_extension;
 extern const struct sieve_extension reject_extension;
 extern const struct sieve_extension envelope_extension;
 
 /* Plugins (FIXME: make this dynamic) */
+
 extern const struct sieve_extension vacation_extension;
 
 const struct sieve_extension *sieve_core_extensions[] = {
+	&comparator_extension, &address_part_extension, 
 	&fileinto_extension, &reject_extension, &envelope_extension, &vacation_extension
 };
 
 const unsigned int sieve_core_extensions_count =
 	(sizeof(sieve_core_extensions) / sizeof(sieve_core_extensions[0]));
 
-const struct sieve_extension *sieve_extension_acquire(const char *extension) {
+/* Extension state */
+
+bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED) 
+{
 	unsigned int i;
 	
-	/* First try to acquire one of the compiled-in extensions */
+	sieve_extensions_init_registry();
+	
+	/* Pre-load core extensions */
 	for ( i = 0; i < sieve_core_extensions_count; i++ ) {
-		if ( strcasecmp(extension, sieve_core_extensions[i]->name) == 0 ) 
-			return sieve_core_extensions[i];
+		int ext_id = 
+			sieve_extension_register(sieve_core_extensions[i]);
+			
+		if ( sieve_core_extensions[i]->load != NULL && 
+			!sieve_core_extensions[i]->load(ext_id) ) {
+			i_error("sieve: failed to load '%s' extension support.", 
+				sieve_core_extensions[i]->name);
+			return FALSE;
+		}
 	}
 	
-	/* Try to load a plugin */
+	/* More extensions can be added through plugins */
+	/* FIXME */
+	
+	return TRUE;
+}
+
+void sieve_extensions_deinit(void)
+{
+	sieve_extensions_deinit_registry();
+}
+
+/* Extension registry */
+
+struct sieve_extension_registration {
+	const struct sieve_extension *extension;
+	int id;
+};
+
+static ARRAY_DEFINE(extensions, const struct sieve_extension *); 
+static struct hash_table *extension_index; 
+
+static void sieve_extensions_init_registry(void)
+{	
+	p_array_init(&extensions, default_pool, 4);
+	extension_index = hash_create(default_pool, default_pool, 0, NULL, NULL);
+}
+
+int sieve_extension_register(const struct sieve_extension *extension) 
+{
+	int ext_id = array_count(&extensions); 
+	struct sieve_extension_registration *ereg;
+	
+	array_append(&extensions, &extension, 1);
 	
-	// FIXME
+	ereg = p_new(default_pool, struct sieve_extension_registration, 1);
+	ereg->extension = extension;
+	ereg->id = ext_id;
+	
+	hash_insert(extension_index, (void *) extension->name, (void *) ereg);
+	
+	return ext_id;
+}
+
+int sieve_extensions_get_count(void)
+{
+	return array_count(&extensions);
+}
+
+const struct sieve_extension *sieve_extension_get_by_id(unsigned int ext_id) 
+{
+	const struct sieve_extension * const *ext;
+	
+	if ( ext_id < array_count(&extensions) ) {
+		ext = array_idx(&extensions, ext_id);
+		return *ext;
+	}
 	
-	/* Not found */
 	return NULL;
 }
+
+int sieve_extension_get_by_name(const char *name, const struct sieve_extension **ext) 
+{
+  struct sieve_extension_registration *ereg = 
+    (struct sieve_extension_registration *) hash_lookup(extension_index, name);
+	
+	*ext = NULL;
+
+	if ( ereg == NULL )
+		return -1;
+	
+	if ( *(ereg->extension->name) == '@' )
+		return -1;
+		    
+	*ext = ereg->extension;
+	
+  return ereg->id;
+}
+
+int sieve_extension_get_id(const struct sieve_extension *extension) 
+{
+  struct sieve_extension_registration *ereg = 
+    (struct sieve_extension_registration *) 
+    	hash_lookup(extension_index, extension->name);
+
+	if ( ereg == NULL )
+		return -1;
+		    
+  return ereg->id;
+}
+
+static void sieve_extensions_deinit_registry() 
+{
+	struct hash_iterate_context *itx = 
+		hash_iterate_init(extension_index);
+	void *key; 
+	void *ereg;
+	
+	while ( hash_iterate(itx, &key, &ereg) ) {
+		p_free(default_pool, ereg);
+	}
+
+	hash_iterate_deinit(&itx); 	
+
+	array_free(&extensions);
+	hash_destroy(&extension_index);
+}
diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h
index 343b2efc78f1b93caae723eae9fd46581fef1956..0f1d27fe2a786607905927e1ac7057f51ca64279 100644
--- a/src/lib-sieve/sieve-extensions.h
+++ b/src/lib-sieve/sieve-extensions.h
@@ -7,6 +7,8 @@
 struct sieve_extension {
 	const char *name;
 	
+	bool (*load)(int ext_id);
+	
 	bool (*validator_load)(struct sieve_validator *validator);
 	bool (*generator_load)(struct sieve_generator *generator);
 	bool (*interpreter_load)(struct sieve_interpreter *interpreter);
@@ -17,4 +19,17 @@ struct sieve_extension {
 
 const struct sieve_extension *sieve_extension_acquire(const char *extension);
 
+/* Extensions state */
+
+bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED); 
+void sieve_extensions_deinit(void);
+
+/* Extension registry */
+
+int sieve_extension_register(const struct sieve_extension *extension);
+int sieve_extensions_get_count(void);
+const struct sieve_extension *sieve_extension_get_by_id(unsigned int ext_id); 
+int sieve_extension_get_by_name(const char *name, const struct sieve_extension **ext); 
+int sieve_extension_get_id(const struct sieve_extension *extension); 
+
 #endif /* __SIEVE_EXTENSIONS_H */
diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c
index e23f5606cddee6cca71979e51a00d1863bda4518..5594e425dadcbe2d1e0971274439938cbfd42496 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -71,10 +71,10 @@ void sieve_generator_free(struct sieve_generator *generator)
 	pool_unref(&(generator->pool));
 }
 
-inline void sieve_generator_register_extension
-	(struct sieve_generator *gentr, const struct sieve_extension *ext) 
+inline void sieve_generator_link_extension
+	(struct sieve_generator *generator, int ext_id) 
 {
-	(void)sieve_binary_register_extension(gentr->binary, ext);
+	(void)sieve_binary_extension_link(generator->binary, ext_id);
 }
 
 /* Binary access */
@@ -92,12 +92,11 @@ inline sieve_size_t sieve_generator_emit_opcode
 }
 
 inline sieve_size_t sieve_generator_emit_opcode_ext
-	(struct sieve_generator *gentr, const struct sieve_extension *ext)
+	(struct sieve_generator *gentr, int ext_id)
 {	
-	return sieve_operation_emit_code_ext(gentr->binary, ext);
+	return sieve_operation_emit_code_ext(gentr->binary, ext_id);
 }
 
-
 /* Generator functions */
 
 bool sieve_generate_arguments(struct sieve_generator *generator, 
diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h
index 1fe0e0d39e51d2f486d59ca17bfb3c3b2ec4bd04..8aaa894bbc89be7ddd1cbb3e3a32c8b91ed86446 100644
--- a/src/lib-sieve/sieve-generator.h
+++ b/src/lib-sieve/sieve-generator.h
@@ -9,8 +9,8 @@ struct sieve_generator;
 struct sieve_generator *sieve_generator_create(struct sieve_ast *ast);
 void sieve_generator_free(struct sieve_generator *generator);
 
-inline void sieve_generator_register_extension
-    (struct sieve_generator *gentr, const struct sieve_extension *ext);
+inline void sieve_generator_link_extension
+    (struct sieve_generator *generator, int ext_id);
     		
 /* Jump list */
 
@@ -35,7 +35,7 @@ inline struct sieve_binary *sieve_generator_get_binary
 inline sieve_size_t sieve_generator_emit_opcode
 	(struct sieve_generator *gentr, int opcode);
 inline sieve_size_t sieve_generator_emit_opcode_ext
-	(struct sieve_generator *gentr, const struct sieve_extension *extension);
+	(struct sieve_generator *gentr, int ext_id);
 
 /* Offset emission */
 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 21596e8f44056745bad72a3e4de95a3cb1c5f30c..a23d67f84099b74afab4f3b8530eeb572c8d4409 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -7,10 +7,12 @@
 #include "hash.h"
 #include "mail-storage.h"
 
+#include "sieve-extensions.h"
 #include "sieve-commands-private.h"
 #include "sieve-generator.h"
 #include "sieve-binary.h"
 #include "sieve-result.h"
+#include "sieve-comparators.h"
 
 #include "sieve-interpreter.h"
 
@@ -20,7 +22,7 @@ struct sieve_interpreter {
 	struct sieve_binary *binary;
 		
 	/* Object registries */
-	struct hash_table *registries; 
+	ARRAY_DEFINE(ext_contexts, void); 
 		
 	/* Execution status */
 	sieve_size_t pc; 
@@ -46,10 +48,8 @@ struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary)
 	
 	interp->pc = 0;
 
-	interp->registries = hash_create(pool, pool, 0, NULL, NULL);
-	
-	/* Init core functionalities */
-	sieve_comparators_init_registry(interp);
+	array_create(&interp->ext_contexts, pool, sizeof(void *), 
+		sieve_extensions_get_count());
 	
 	return interp;
 }
@@ -60,55 +60,27 @@ void sieve_interpreter_free(struct sieve_interpreter *interpreter)
 	pool_unref(&(interpreter->pool));
 }
 
-/* Object registry */
-
-struct sieve_interpreter_registry {
-	struct sieve_interpreter *interpreter;
-	const char *name;
-	ARRAY_DEFINE(registered, void);
-};
-
-struct sieve_interpreter_registry *
-	sieve_interpreter_registry_init(struct sieve_interpreter *interp, const char *name)
+inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp)
 {
-	struct sieve_interpreter_registry *reg = (struct sieve_interpreter_registry *) 
-		hash_lookup(interp->registries, name);
-	
-	if ( reg == NULL ) {
-		reg = p_new(interp->pool, struct sieve_interpreter_registry, 1);
-		reg->interpreter = interp;
-		reg->name = name;
-		array_create(&reg->registered, interp->pool, sizeof(void *), 5);
-		
-		hash_insert(interp->registries, (void *) name, (void *) reg);
-	}
-
-	return reg;
+	return interp->pool;
 }
 
-const void *sieve_interpreter_registry_get
-	(struct sieve_interpreter_registry *reg, const struct sieve_extension *ext)
+
+/* Extension support */
+
+inline void sieve_interpreter_extension_set_context
+	(struct sieve_interpreter *interpreter, int ext_id, void *context)
 {
-	const void *result;
-	int index = sieve_binary_get_extension_index(reg->interpreter->binary, ext);
-	
-	if  ( index < 0 || index > (int) array_count(&reg->registered) )
-		return NULL;
-	
-	result = array_idx(&reg->registered, (unsigned int) index);		
-	
-	return result;
+	array_idx_set(&interpreter->ext_contexts, (unsigned int) ext_id, context);	
 }
 
-void  sieve_interpreter_registry_set
-	(struct sieve_interpreter_registry *reg, const struct sieve_extension *ext, const void *obj)
+inline const void *sieve_interpreter_extension_get_context
+	(struct sieve_interpreter *interpreter, int ext_id) 
 {
-	int index = sieve_binary_get_extension_index(reg->interpreter->binary, ext);
-	
-	if  ( index < 0 || index > (int) array_count(&reg->registered) )
-		return;
+	if  ( ext_id < 0 || ext_id > (int) array_count(&interpreter->ext_contexts) )
+		return NULL;
 	
-	array_idx_set(&reg->registered, (unsigned int) index, obj);		
+	return array_idx(&interpreter->ext_contexts, (unsigned int) ext_id);		
 }
 
 
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index d89e85f5e319d1f7cdadf5658813dab43ae7b3ef..0898a708766fc6585f443fd9dcfc6059f867fdae 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -12,6 +12,7 @@ struct sieve_interpreter;
 
 struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary);
 void sieve_interpreter_free(struct sieve_interpreter *interpreter);
+inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp);
 
 inline void sieve_interpreter_reset
 	(struct sieve_interpreter *interpreter);
@@ -28,16 +29,12 @@ inline bool sieve_interpreter_get_test_result
 inline struct sieve_binary *sieve_interpreter_get_binary
 	(struct sieve_interpreter *interp);
 
-/* Object registry */
+/* Extension support */
 
-struct sieve_interpreter_registry;
-
-struct sieve_interpreter_registry *
-	sieve_interpreter_registry_init(struct sieve_interpreter *interp, const char *name);
-const void *sieve_interpreter_registry_get
-	(struct sieve_interpreter_registry *reg, const struct sieve_extension *ext);
-void  sieve_interpreter_registry_set
-	(struct sieve_interpreter_registry *reg, const struct sieve_extension *ext, const void *obj);
+inline void sieve_interpreter_extension_set_context
+	(struct sieve_interpreter *interpreter, int ext_id, void *context);
+inline const void *sieve_interpreter_extension_get_context
+	(struct sieve_interpreter *interpreter, int ext_id);
 	
 /* Opcodes and operands */
 
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index 26f6ac5240a6a5be293c6d9ee31e513700245985..4599de460588f1b967bcbce5f48f5febd02255e9 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -7,7 +7,9 @@
 #include "sieve-commands-private.h"
 #include "sieve-validator.h"
 #include "sieve-extensions.h"
+
 #include "sieve-comparators.h"
+#include "sieve-address-parts.h"
 
 /* Context/Semantics checker implementation */
 
@@ -19,7 +21,8 @@ struct sieve_validator {
 	
 	/* Registries */
 	struct hash_table *commands;
-	struct hash_table *comparators; 
+	
+	ARRAY_DEFINE(ext_contexts, void);
 };
 
 /* Predeclared statics */
@@ -50,6 +53,9 @@ void sieve_validator_error(struct sieve_validator *validator, struct sieve_ast_n
 	va_end(args);
 }
 
+extern struct sieve_extension comparator_extension;
+extern struct sieve_extension address_part_extension;
+
 struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sieve_error_handler *ehandler) 
 {
 	pool_t pool;
@@ -68,24 +74,29 @@ struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sie
 		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
 	sieve_validator_register_core_commands(validator);
 	sieve_validator_register_core_tests(validator);
-	
-	/* Setup comparator registry */
-	validator->comparators = hash_create
-		(pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
-	sieve_validator_register_core_comparators(validator);
-	
+
+	array_create(&validator->ext_contexts, pool, sizeof(void *), 
+		sieve_extensions_get_count());
+		
+	(void)comparator_extension.validator_load(validator);	
+	(void)address_part_extension.validator_load(validator);	
+		
 	return validator;
 }
 
 void sieve_validator_free(struct sieve_validator *validator) 
 {
 	hash_destroy(&validator->commands);
-	hash_destroy(&validator->comparators);
 	
 	sieve_ast_unref(&validator->ast);
 	pool_unref(&(validator->pool));
 }
 
+inline pool_t sieve_validator_pool(struct sieve_validator *validator)
+{
+	return validator->pool;
+}
+
 /* Command registry */
 
 struct sieve_command_registration {
@@ -234,57 +245,40 @@ static const struct sieve_argument *sieve_validator_find_tag
 
 /* Extension support */
 
-const struct sieve_extension *sieve_validator_load_extension
-	(struct sieve_validator *validator, struct sieve_command_context *cmd, const char *extension) 
+int sieve_validator_extension_load
+	(struct sieve_validator *validator, struct sieve_command_context *cmd, 
+		const char *ext_name) 
 {
-	const struct sieve_extension *ext = sieve_extension_acquire(extension); 
+	const struct sieve_extension *ext;
+	int ext_id = sieve_extension_get_by_name(ext_name, &ext); 
 	
-	if ( ext == NULL ) {
+	if ( ext_id < 0 ) {
 		sieve_command_validate_error(validator, cmd, 
-			"unsupported sieve capability '%s'", extension);
-		return NULL;
+			"unsupported sieve capability '%s'", ext_name);
+		return -1;
 	}
 
 	if ( ext->validator_load != NULL && !ext->validator_load(validator) ) {
 		sieve_command_validate_error(validator, cmd, 
-			"failed to load sieve capability '%s'", extension);
-		return NULL;
+			"failed to load sieve capability '%s'", ext->name);
+		return -1;
 	}
 	
-	i_info("loaded extension '%s'", extension);
-	return ext;
+	i_info("loaded extension '%s'", ext->name);
+	return ext_id;
 }
 
-/* Comparator registry */
-
-void sieve_validator_register_comparator
-	(struct sieve_validator *validator, const struct sieve_comparator *cmp) 
+inline void sieve_validator_extension_set_context(struct sieve_validator *validator, int ext_id, void *context)
 {
-	hash_insert(validator->comparators, (void *) cmp->identifier, (void *) cmp);
+	array_idx_set(&validator->ext_contexts, (unsigned int) ext_id, context);	
 }
 
-const struct sieve_comparator *sieve_validator_find_comparator
-		(struct sieve_validator *validator, const char *comparator) 
+inline const void *sieve_validator_extension_get_context(struct sieve_validator *validator, int ext_id) 
 {
-  return 	(const struct sieve_comparator *) hash_lookup(validator->comparators, comparator);
-}
-
-static void sieve_validator_register_core_comparators(struct sieve_validator *validator) 
-{
-	unsigned int i;
+	if  ( ext_id < 0 || ext_id > (int) array_count(&validator->ext_contexts) )
+		return NULL;
 	
-	for ( i = 0; i < sieve_core_comparators_count; i++ ) {
-		sieve_validator_register_comparator(validator, sieve_core_comparators[i]); 
-	}
-}
-
-/* Comparator validation */
-
-void sieve_validator_link_comparator_tag
-	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg,	
-		unsigned int id_code) 
-{
-	sieve_validator_register_tag(validator, cmd_reg, &comparator_tag, id_code); 	
+	return array_idx(&validator->ext_contexts, (unsigned int) ext_id);		
 }
 
 /* Match type validation */
@@ -320,39 +314,6 @@ void sieve_validator_link_match_type_tags
 	sieve_validator_register_tag(validator, cmd_reg, &match_matches_tag, id_code); 	
 }
 
-/* Address part validation */
-
-static bool sieve_validate_address_part_tag
-	(struct sieve_validator *validator ATTR_UNUSED, 
-	struct sieve_ast_argument **arg, 
-	struct sieve_command_context *cmd ATTR_UNUSED)
-{
-	/* Syntax:   
-	 *   ":localpart" / ":domain" / ":all"
-   */
-
-	/* Not implemented, so delete it */
-	*arg = sieve_ast_arguments_delete(*arg, 1);		
-
-	return TRUE;
-}
-
-static const struct sieve_argument address_localpart_tag = 
-	{ "localpart", sieve_validate_address_part_tag, NULL };
-static const struct sieve_argument address_domain_tag = 
-	{ "domain", sieve_validate_address_part_tag, NULL };
-static const struct sieve_argument address_all_tag = 
-	{ "all", sieve_validate_address_part_tag, NULL };
-
-void sieve_validator_link_address_part_tags
-	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg,
-		unsigned int id_code) 
-{
-	sieve_validator_register_tag(validator, cmd_reg, &address_localpart_tag, id_code); 	
-	sieve_validator_register_tag(validator, cmd_reg, &address_domain_tag, id_code); 	
-	sieve_validator_register_tag(validator, cmd_reg, &address_all_tag, id_code); 	
-}
-
 /* Tag Validation API */
 
 /* Test validation API */
diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h
index 8103faaf3bc930bf49fcf8db13ebe90241d383a2..dab6892d53cea5ff865a71fc3c77618f4d11772f 100644
--- a/src/lib-sieve/sieve-validator.h
+++ b/src/lib-sieve/sieve-validator.h
@@ -3,7 +3,6 @@
 
 #include "lib.h"
 
-#include "sieve-comparators.h"
 #include "sieve-common.h"
 #include "sieve-error.h"
 
@@ -12,6 +11,7 @@ struct sieve_command_registration;
 
 struct sieve_validator *sieve_validator_create(struct sieve_ast *ast, struct sieve_error_handler *ehandler);
 void sieve_validator_free(struct sieve_validator *validator);
+inline pool_t sieve_validator_pool(struct sieve_validator *validator);
 
 bool sieve_validator_run(struct sieve_validator *validator);
 
@@ -30,23 +30,11 @@ void sieve_validator_register_command
 void sieve_validator_register_tag
 	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg, 
 	const struct sieve_argument *argument, unsigned int id_code);
-	
-/* Comparator registration */
-void sieve_validator_register_comparator
-	(struct sieve_validator *validator, const struct sieve_comparator *cmp);
-const struct sieve_comparator *sieve_validator_find_comparator
-		(struct sieve_validator *validator, const char *comparator); 
 
 /* Special test arguments */
-void sieve_validator_link_comparator_tag
-	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg,
-		unsigned int id_code); 
 void sieve_validator_link_match_type_tags
 	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg,
 		unsigned int id_code); 
-void sieve_validator_link_address_part_tags
-	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg,
-		unsigned int id_code); 
 
 /* Argument validation */
 bool sieve_validate_command_arguments
@@ -62,7 +50,10 @@ bool sieve_validate_command_block(struct sieve_validator *validator, struct siev
 	bool block_allowed, bool block_required);
 
 /* Extensions */
-const struct sieve_extension *sieve_validator_load_extension
-	(struct sieve_validator *validator, struct sieve_command_context *cmd, const char *extension);
+int sieve_validator_extension_load
+	(struct sieve_validator *validator, struct sieve_command_context *cmd, 
+		const char *ext_name); 
+inline void sieve_validator_extension_set_context(struct sieve_validator *validator, int ext_id, void *context);
+inline const void *sieve_validator_extension_get_context(struct sieve_validator *validator, int ext_id);
 
 #endif /* __SIEVE_VALIDATOR_H__ */
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 76473cda093dab8f67665d4c957930b1a542c0cd..11fd336c1ed99aa60bb4300c01ddad5e0181d214 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -3,6 +3,7 @@
 #include "istream.h"
 #include "buffer.h"
 
+#include "sieve-extensions.h"
 #include "sieve-parser.h"
 #include "sieve-ast.h"
 #include "sieve-validator.h"
@@ -18,6 +19,16 @@
 #include <unistd.h>
 #include <stdio.h>
 
+bool sieve_init(const char *plugins)
+{
+	return sieve_extensions_init(plugins);
+}
+
+void sieve_deinit(void)
+{
+	sieve_extensions_deinit();
+}
+
 static struct sieve_ast *sieve_parse(int fd, struct sieve_error_handler *ehandler)
 {
 	struct sieve_parser *parser;
diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h
index 42fab8b1dd7b373d55817b3bee306138644e9c74..049b8675d33f10e0841b1bd6924a55259b1a77b8 100644
--- a/src/lib-sieve/sieve.h
+++ b/src/lib-sieve/sieve.h
@@ -1,7 +1,12 @@
 #ifndef __SIEVE_H
 #define __SIEVE_H
 
-#include "sieve-binary.h"
+#include "mail-storage.h"
+
+struct sieve_binary;
+
+bool sieve_init(const char *plugins);
+void sieve_deinit(void);
 
 struct sieve_binary *sieve_compile(int fd);
 void sieve_dump(struct sieve_binary *binary);
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index c13ca9c6659307c5caece9adde2763cb523ad992..a767e73653733450440ed86f206ad8f0298c6d1b 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -2,6 +2,9 @@
 
 #include "sieve-commands.h"
 #include "sieve-commands-private.h"
+
+#include "sieve-comparators.h"
+#include "sieve-address-parts.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
@@ -30,8 +33,8 @@ enum tst_address_optional {
 bool tst_address_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) 
 {
 	/* The order of these is not significant */
-	sieve_validator_link_comparator_tag(validator, cmd_reg, OPT_COMPARATOR );
-	sieve_validator_link_address_part_tags(validator, cmd_reg, OPT_ADDRESS_PART);
+	sieve_comparators_link_tag(validator, cmd_reg, OPT_COMPARATOR );
+	sieve_address_parts_link_tags(validator, cmd_reg, OPT_ADDRESS_PART);
 	sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE);
 
 	return TRUE;
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index 78718568a16e309278ef56b2ee8f302051929a42..2146ae651a0f3b80f2f7c127fc1aa45117fd0c20 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -30,7 +30,7 @@ enum tst_header_optional {
 bool tst_header_registered(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg) 
 {
 	/* The order of these is not significant */
-	sieve_validator_link_comparator_tag(validator, cmd_reg, OPT_COMPARATOR);
+	sieve_comparators_link_tag(validator, cmd_reg, OPT_COMPARATOR);
 	sieve_validator_link_match_type_tags(validator, cmd_reg, OPT_MATCH_TYPE);
 
 	return TRUE;
diff --git a/src/sieve-bin/sieve_test.c b/src/sieve-bin/sieve_test.c
index e841bf319157c3e2558350c6711fc2e7d1a8a8f0..c8c57d3a8222d8c2494ae14824077a335cd500f8 100644
--- a/src/sieve-bin/sieve_test.c
+++ b/src/sieve-bin/sieve_test.c
@@ -164,7 +164,7 @@ int main(int argc, char **argv)
  		exit(1);
  	}
   
-  /* Compile sieve script */
+  	/* Compile sieve script */
   
 	if ( (fd = open(argv[1], O_RDONLY)) < 0 ) {
 		perror("open()");
@@ -173,9 +173,16 @@ int main(int argc, char **argv)
 
 	printf("Parsing sieve script '%s'...\n", argv[1]);
 
-	if ( (sbin = sieve_compile(fd)) == NULL ) 
+	if ( !sieve_init("") ) {
+		printf("Failed to initialize sieve implementation\n");
 		exit(1);
-	
+	}
+
+	if ( (sbin = sieve_compile(fd)) == NULL ) {
+		printf("Failed to compile sieve script\n");
+		exit(1);
+	}		 
+		
 	(void) sieve_dump(sbin);
 
  	close(fd);
@@ -225,7 +232,10 @@ int main(int argc, char **argv)
 
 	/* */
 	i_stream_seek(input, 0);
+
 	sieve_test(sbin, mail);
+
+	sieve_deinit();
 	//ret = deliver_save(ns, &storage, mailbox, mail, 0, NULL);
 
 	i_stream_unref(&input);
diff --git a/src/sieve-bin/sievec.c b/src/sieve-bin/sievec.c
index 583ea07af253f6ebc27331c28d9b192511b17b4c..0292a34b8b8c3aab624e97c853877225ff56e948 100644
--- a/src/sieve-bin/sievec.c
+++ b/src/sieve-bin/sievec.c
@@ -34,10 +34,16 @@ int main(int argc, char **argv) {
 
 	printf("Parsing sieve script '%s'...\n", argv[1]);
 
-	sbin = sieve_compile(fd);
+	if ( sieve_init("") ) {
+		sbin = sieve_compile(fd);
 	
-	if ( sbin != NULL ) 
-		(void) sieve_dump(sbin);
+		if ( sbin != NULL ) 
+			(void) sieve_dump(sbin);
+
+		sieve_deinit();
+	} else {
+		printf("Failed to initialize sieve implementation.");
+	}
 
  	close(fd);
 }