diff --git a/configure.ac b/configure.ac
index 30e0c534777f444d0c555fe88c5a3c7519f94edd..2e925f35c15ad55e7c6bbc47786d6499da337fdc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -120,6 +120,7 @@ src/lib-sieve/plugins/date/Makefile
 src/lib-sieve/plugins/spamvirustest/Makefile
 src/lib-sieve/plugins/ihave/Makefile
 src/lib-sieve/plugins/editheader/Makefile
+src/lib-sieve/plugins/metadata/Makefile
 src/lib-sieve/plugins/vnd.dovecot/Makefile
 src/lib-sieve/plugins/vnd.dovecot/debug/Makefile
 src/lib-sieve/plugins/vnd.dovecot/duplicate/Makefile
diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index 7cd4acfaf2bc32ad6e7334761583869b9b5b7d9e..eea61baacea632194f0ab1742bb52e7f6d9c769e 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -42,7 +42,8 @@ comparators = \
 	cmp-i-ascii-casemap.c
 
 if BUILD_UNFINISHED
-unfinished_plugins =
+unfinished_plugins = \
+	$(extdir)/metadata/libsieve_ext_metadata.la
 endif
 
 # These are not actual plugins just yet...
diff --git a/src/lib-sieve/plugins/Makefile.am b/src/lib-sieve/plugins/Makefile.am
index 21fedfcee80a44d5cb27e2a28924d2f1702491ac..a26c4a820d4a9fb857f0419bbf44e1cc65e5ef63 100644
--- a/src/lib-sieve/plugins/Makefile.am
+++ b/src/lib-sieve/plugins/Makefile.am
@@ -1,5 +1,5 @@
 if BUILD_UNFINISHED
-UNFINISHED =
+UNFINISHED = metadata
 endif
 
 SUBDIRS = \
diff --git a/src/lib-sieve/plugins/metadata/Makefile.am b/src/lib-sieve/plugins/metadata/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..bac6f5d75fa6862946c9a76d301c49563a92b3f2
--- /dev/null
+++ b/src/lib-sieve/plugins/metadata/Makefile.am
@@ -0,0 +1,24 @@
+
+noinst_LTLIBRARIES = libsieve_ext_metadata.la
+
+libsieve_ext_metadata_la_LDFLAGS = -module -avoid-version
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib-sieve \
+	-I$(top_srcdir)/src/lib-sieve/plugins/variables \
+	$(LIBDOVECOT_INCLUDE)
+
+tests = \
+	tst-metadata.c \
+	tst-metadataexists.c
+
+extensions = \
+	ext-metadata.c
+
+libsieve_ext_metadata_la_SOURCES = \
+	$(tests) \
+	$(extensions)
+
+noinst_HEADERS = \
+	ext-metadata-common.h
+
diff --git a/src/lib-sieve/plugins/metadata/ext-metadata-common.h b/src/lib-sieve/plugins/metadata/ext-metadata-common.h
new file mode 100644
index 0000000000000000000000000000000000000000..a974436559a5a7b4cca2129c56a4df2e3e2800f5
--- /dev/null
+++ b/src/lib-sieve/plugins/metadata/ext-metadata-common.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
+ */
+
+#ifndef __EXT_METADATA_COMMON_H
+#define __EXT_METADATA_COMMON_H
+
+#include "sieve-common.h"
+
+/*
+ * Extension
+ */
+
+extern const struct sieve_extension_def mboxmetadata_extension;
+extern const struct sieve_extension_def servermetadata_extension;
+
+/*
+ * Commands
+ */
+
+extern const struct sieve_command_def metadata_test;
+extern const struct sieve_command_def servermetadata_test;
+extern const struct sieve_command_def metadataexists_test;
+extern const struct sieve_command_def servermetadataexists_test;
+
+/*
+ * Operations
+ */
+
+enum ext_metadata_opcode {
+	EXT_METADATA_OPERATION_METADATA,
+	EXT_METADATA_OPERATION_METADATAEXISTS
+};
+
+extern const struct sieve_operation_def metadata_operation;
+extern const struct sieve_operation_def servermetadata_operation;
+extern const struct sieve_operation_def metadataexists_operation;
+extern const struct sieve_operation_def servermetadataexists_operation;
+
+#endif /* __EXT_METADATA_COMMON_H */
diff --git a/src/lib-sieve/plugins/metadata/ext-metadata.c b/src/lib-sieve/plugins/metadata/ext-metadata.c
new file mode 100644
index 0000000000000000000000000000000000000000..0beb6307997b65cdadd55b96921eeeed6219706d
--- /dev/null
+++ b/src/lib-sieve/plugins/metadata/ext-metadata.c
@@ -0,0 +1,83 @@
+/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+
+#include "sieve-extensions.h"
+#include "sieve-commands.h"
+#include "sieve-binary.h"
+
+#include "sieve-validator.h"
+#include "sieve-interpreter.h"
+
+#include "ext-metadata-common.h"
+
+/*
+ * Extension mboxmetadata
+ * -----------------------------
+ *
+ * Authors: Stephan Bosch
+ * Specification: RFC 5490; Section 3
+ * Implementation: skeleton
+ * Status: development
+ *
+ */
+
+const struct sieve_operation_def *mboxmetadata_operations[] = {
+	&metadata_operation,
+	&metadataexists_operation,
+};
+
+static bool ext_mboxmetadata_validator_load
+	(const struct sieve_extension *ext, struct sieve_validator *valdtr);
+
+const struct sieve_extension_def mboxmetadata_extension = {
+	.name = "mboxmetadata",
+	.validator_load = ext_mboxmetadata_validator_load,
+	SIEVE_EXT_DEFINE_OPERATIONS(mboxmetadata_operations)
+};
+
+static bool ext_mboxmetadata_validator_load
+(const struct sieve_extension *ext, struct sieve_validator *valdtr)
+{
+	sieve_validator_register_command(valdtr, ext, &metadata_test);
+	sieve_validator_register_command(valdtr, ext, &metadataexists_test);
+
+	return TRUE;
+}
+
+/*
+ * Extension servermetadata
+ * -----------------------------
+ *
+ * Authors: Stephan Bosch
+ * Specification: RFC 5490; Section 4
+ * Implementation: skeleton
+ * Status: development
+ *
+ */
+
+const struct sieve_operation_def *servermetadata_operations[] = {
+	&servermetadata_operation,
+	&servermetadataexists_operation,
+};
+
+static bool ext_servermetadata_validator_load
+	(const struct sieve_extension *ext, struct sieve_validator *valdtr);
+
+const struct sieve_extension_def servermetadata_extension = {
+	.name = "servermetadata",
+	.validator_load = ext_servermetadata_validator_load,
+	SIEVE_EXT_DEFINE_OPERATIONS(servermetadata_operations)
+};
+
+static bool ext_servermetadata_validator_load
+(const struct sieve_extension *ext, struct sieve_validator *valdtr)
+{
+	sieve_validator_register_command(valdtr, ext, &servermetadata_test);
+	sieve_validator_register_command(valdtr, ext, &servermetadataexists_test);
+
+	return TRUE;
+}
+
+
diff --git a/src/lib-sieve/plugins/metadata/tst-metadata.c b/src/lib-sieve/plugins/metadata/tst-metadata.c
new file mode 100644
index 0000000000000000000000000000000000000000..fb85212cf88a352203565f63d981ac5ac50b3204
--- /dev/null
+++ b/src/lib-sieve/plugins/metadata/tst-metadata.c
@@ -0,0 +1,286 @@
+/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "sieve-common.h"
+#include "sieve-commands.h"
+#include "sieve-stringlist.h"
+#include "sieve-code.h"
+#include "sieve-comparators.h"
+#include "sieve-match-types.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-dump.h"
+#include "sieve-match.h"
+
+#include "ext-metadata-common.h"
+
+/*
+ * Test definitions
+ */
+
+/* Forward declarations */
+
+static bool tst_metadata_registered
+	(struct sieve_validator *valdtr, const struct sieve_extension *ext,
+		struct sieve_command_registration *cmd_reg);
+static bool tst_metadata_validate
+	(struct sieve_validator *valdtr, struct sieve_command *tst);
+static bool tst_metadata_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd);
+
+/* Metadata test
+ *
+ * Syntax:
+ *   metadata [MATCH-TYPE] [COMPARATOR]
+ *            <mailbox: string>
+ *            <annotation-name: string> <key-list: string-list>
+ */
+
+const struct sieve_command_def metadata_test = {
+	"metadata",
+	SCT_TEST,
+	3, 0, FALSE, FALSE,
+	tst_metadata_registered,
+	NULL,
+	tst_metadata_validate,
+	NULL,
+	tst_metadata_generate,
+	NULL
+};
+
+/* Servermetadata test
+ *
+ * Syntax:
+ *   servermetadata [MATCH-TYPE] [COMPARATOR]
+ *            <annotation-name: string> <key-list: string-list>
+ */
+
+const struct sieve_command_def servermetadata_test = {
+	"servermetadata",
+	SCT_TEST,
+	2, 0, FALSE, FALSE,
+	tst_metadata_registered,
+	NULL,
+	tst_metadata_validate,
+	NULL,
+	tst_metadata_generate,
+	NULL
+};
+
+/*
+ * Opcode definitions
+ */
+
+static bool tst_metadata_operation_dump
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
+static int tst_metadata_operation_execute
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
+
+/* Metadata operation */
+
+const struct sieve_operation_def metadata_operation = {
+	"METADATA",
+	&mboxmetadata_extension,
+	EXT_METADATA_OPERATION_METADATA,
+	tst_metadata_operation_dump,
+	tst_metadata_operation_execute
+};
+
+/* Servermetadata operation */
+
+const struct sieve_operation_def servermetadata_operation = {
+	"SERVERMETADATA",
+	&servermetadata_extension,
+	EXT_METADATA_OPERATION_METADATA,
+	tst_metadata_operation_dump,
+	tst_metadata_operation_execute
+};
+
+/*
+ * Test registration
+ */
+
+static bool tst_metadata_registered
+(struct sieve_validator *valdtr, const struct sieve_extension *ext ATTR_UNUSED,
+	struct sieve_command_registration *cmd_reg)
+{
+	/* The order of these is not significant */
+	sieve_comparators_link_tag(valdtr, cmd_reg, SIEVE_MATCH_OPT_COMPARATOR);
+	sieve_match_types_link_tags(valdtr, cmd_reg, SIEVE_MATCH_OPT_MATCH_TYPE);
+
+	return TRUE;
+}
+
+/*
+ * Test validation
+ */
+
+static bool tst_metadata_validate
+(struct sieve_validator *valdtr, struct sieve_command *tst)
+{
+	struct sieve_ast_argument *arg = tst->first_positional;
+	const struct sieve_match_type mcht_default =
+		SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
+	const struct sieve_comparator cmp_default =
+		SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator);
+	unsigned int arg_index = 1;
+
+	if ( sieve_command_is(tst, metadata_test) ) {
+		if ( !sieve_validate_positional_argument
+			(valdtr, tst, arg, "mailbox", arg_index++, SAAT_STRING) ) {
+			return FALSE;
+		}
+
+		if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
+			return FALSE;
+
+		arg = sieve_ast_argument_next(arg);
+	}
+
+	if ( !sieve_validate_positional_argument
+		(valdtr, tst, arg, "annotation-name", arg_index++, SAAT_STRING) ) {
+		return FALSE;
+	}
+
+	if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
+		return FALSE;
+
+	arg = sieve_ast_argument_next(arg);
+
+	if ( !sieve_validate_positional_argument
+		(valdtr, tst, arg, "key list", arg_index++, SAAT_STRING_LIST) ) {
+		return FALSE;
+	}
+
+	if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
+		return FALSE;
+
+	/* Validate the key argument to a specified match type */
+	return sieve_match_type_validate
+		(valdtr, tst, arg, &mcht_default, &cmp_default);
+}
+
+/*
+ * Test generation
+ */
+
+static bool tst_metadata_generate
+(const struct sieve_codegen_env *cgenv, struct sieve_command *tst)
+{
+	if ( sieve_command_is(tst, metadata_test) ) {
+		sieve_operation_emit
+			(cgenv->sblock, tst->ext, &metadata_operation);
+	} else if ( sieve_command_is(tst, servermetadata_test) ) {
+		sieve_operation_emit
+			(cgenv->sblock, tst->ext, &servermetadata_operation);
+	} else {
+		i_unreached();
+	}
+
+ 	/* Generate arguments */
+	if ( !sieve_generate_arguments(cgenv, tst, NULL) )
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+ * Code dump
+ */
+
+static bool tst_metadata_operation_dump
+(const struct sieve_dumptime_env *denv, sieve_size_t *address)
+{
+	bool metadata = sieve_operation_is(denv->oprtn, metadata_operation);
+
+	if ( metadata )
+		sieve_code_dumpf(denv, "METADATA");
+	else
+		sieve_code_dumpf(denv, "SERVERMETADATA");
+
+	sieve_code_descend(denv);
+
+	/* Handle any optional arguments */
+	if ( sieve_match_opr_optional_dump(denv, address, NULL) != 0 )
+ 		return FALSE;
+
+	if ( metadata && !sieve_opr_string_dump(denv, address, "mailbox") )
+		return FALSE;
+
+	return
+		sieve_opr_string_dump(denv, address, "annotation-name") &&
+		sieve_opr_stringlist_dump(denv, address, "key list");
+}
+
+/*
+ * Code execution
+ */
+
+static int tst_metadata_operation_execute
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	bool metadata = sieve_operation_is(renv->oprtn, metadata_operation);
+	struct sieve_match_type mcht =
+		SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
+	struct sieve_comparator cmp =
+		SIEVE_COMPARATOR_DEFAULT(i_ascii_casemap_comparator);
+	string_t *mailbox, *annotation_name;
+	struct sieve_stringlist *value_list, *key_list;
+	const char *annotation = NULL;
+	int match, ret;
+
+	/*
+	 * Read operands
+	 */
+
+	/* Handle match-type and comparator operands */
+	if ( sieve_match_opr_optional_read
+		(renv, address, NULL, &ret, &cmp, &mcht) < 0 )
+		return ret;
+
+	/* Read mailbox */
+	if ( metadata ) {
+		if ( (ret=sieve_opr_string_read(renv, address, "mailbox", &mailbox)) <= 0 )
+			return ret;
+	}
+
+	/* Read annotation-name */
+	if ( (ret=sieve_opr_string_read
+		(renv, address, "annotation-name", &annotation_name)) <= 0 )
+		return ret;
+
+	/* Read key-list */
+	if ( (ret=sieve_opr_stringlist_read
+		(renv, address, "key-list", &key_list)) <= 0 )
+		return ret;
+
+	/*
+	 * Perform operation
+	 */
+
+	if ( metadata )
+		sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "metadata test");
+	else
+		sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "servermetadata test");
+
+	/* Get annotation */
+	annotation = "FIXME";
+
+	/* Perform match */
+	if ( annotation != NULL ) {
+		/* Create value stringlist */
+		value_list = sieve_single_stringlist_create_cstr(renv, annotation, FALSE);
+
+		/* Perform match */
+		if ( (match=sieve_match(renv, &mcht, &cmp, value_list, key_list, &ret))
+			< 0 )
+			return ret;
+	} else {
+		match = 0;
+	}
+
+	/* Set test result for subsequent conditional jump */
+	sieve_interpreter_set_test_result(renv->interp, match > 0);
+	return SIEVE_EXEC_OK;
+}
diff --git a/src/lib-sieve/plugins/metadata/tst-metadataexists.c b/src/lib-sieve/plugins/metadata/tst-metadataexists.c
new file mode 100644
index 0000000000000000000000000000000000000000..b234201d6631bcc1ed9e8a87ea6a97edd1143d9a
--- /dev/null
+++ b/src/lib-sieve/plugins/metadata/tst-metadataexists.c
@@ -0,0 +1,246 @@
+/* Copyright (c) 2002-2013 Pigeonhole authors, see the included COPYING file
+ */
+
+#include "lib.h"
+#include "str-sanitize.h"
+#include "mail-storage.h"
+#include "mail-namespace.h"
+
+#include "sieve-common.h"
+#include "sieve-commands.h"
+#include "sieve-stringlist.h"
+#include "sieve-code.h"
+#include "sieve-validator.h"
+#include "sieve-generator.h"
+#include "sieve-interpreter.h"
+#include "sieve-dump.h"
+
+#include "ext-metadata-common.h"
+
+/*
+ * Command definitions
+ */
+
+/* Forward declarations */
+
+static bool tst_metadataexists_validate
+	(struct sieve_validator *valdtr, struct sieve_command *tst);
+static bool tst_metadataexists_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command *ctx);
+
+/* Metadataexists command
+ *
+ * Syntax:
+ *    metadataexists <mailbox: string> <annotation-names: string-list>
+ */
+
+static bool tst_metadataexists_validate
+	(struct sieve_validator *valdtr, struct sieve_command *tst);
+static bool tst_metadataexists_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_command *ctx);
+
+const struct sieve_command_def metadataexists_test = {
+	"metadataexists",
+	SCT_TEST,
+	2, 0, FALSE, FALSE,
+	NULL, NULL,
+	tst_metadataexists_validate,
+	NULL,
+	tst_metadataexists_generate,
+	NULL
+};
+
+/* Servermetadataexists command
+ *
+ * Syntax:
+ *    servermetadataexists <annotation-names: string-list>
+ */
+
+const struct sieve_command_def servermetadataexists_test = {
+	"servermetadataexists",
+	SCT_TEST,
+	1, 0, FALSE, FALSE,
+	NULL, NULL,
+	tst_metadataexists_validate,
+	NULL,
+	tst_metadataexists_generate,
+	NULL
+};
+
+
+/*
+ * Opcode definitions
+ */
+
+static bool tst_metadataexists_operation_dump
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
+static int tst_metadataexists_operation_execute
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
+
+/* Metadata operation */
+
+const struct sieve_operation_def metadataexists_operation = {
+	"METADATAEXISTS",
+	&mboxmetadata_extension,
+	EXT_METADATA_OPERATION_METADATAEXISTS,
+	tst_metadataexists_operation_dump,
+	tst_metadataexists_operation_execute
+};
+
+/* Mailboxexists operation */
+
+const struct sieve_operation_def servermetadataexists_operation = {
+	"SERVERMETADATAEXISTS",
+	&servermetadata_extension,
+	EXT_METADATA_OPERATION_METADATAEXISTS,
+	tst_metadataexists_operation_dump,
+	tst_metadataexists_operation_execute
+};
+
+/*
+ * Test validation
+ */
+
+static bool tst_metadataexists_validate
+(struct sieve_validator *valdtr, struct sieve_command *tst)
+{
+	struct sieve_ast_argument *arg = tst->first_positional;
+	unsigned int arg_index = 1;
+
+	if ( sieve_command_is(tst, metadataexists_test) ) {
+		if ( !sieve_validate_positional_argument
+			(valdtr, tst, arg, "mailbox", arg_index++, SAAT_STRING) ) {
+			return FALSE;
+		}
+
+		if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
+			return FALSE;
+
+		arg = sieve_ast_argument_next(arg);
+	}
+
+	if ( !sieve_validate_positional_argument
+		(valdtr, tst, arg, "annotation-names", arg_index++, SAAT_STRING_LIST) ) {
+		return FALSE;
+	}
+
+	return sieve_validator_argument_activate(valdtr, tst, arg, FALSE);
+}
+
+/*
+ * Test generation
+ */
+
+static bool tst_metadataexists_generate
+(const struct sieve_codegen_env *cgenv, struct sieve_command *tst)
+{
+	if ( sieve_command_is(tst, metadataexists_test) ) {
+		sieve_operation_emit
+			(cgenv->sblock, tst->ext, &metadataexists_operation);
+	} else if ( sieve_command_is(tst, servermetadataexists_test) ) {
+		sieve_operation_emit
+			(cgenv->sblock, tst->ext, &servermetadataexists_operation);
+	} else {
+		i_unreached();
+	}
+
+ 	/* Generate arguments */
+	return sieve_generate_arguments(cgenv, tst, NULL);
+}
+
+/*
+ * Code dump
+ */
+
+static bool tst_metadataexists_operation_dump
+(const struct sieve_dumptime_env *denv, sieve_size_t *address)
+{
+	bool metadata = sieve_operation_is(denv->oprtn, metadataexists_operation);
+
+	if ( metadata )
+		sieve_code_dumpf(denv, "METADATAEXISTS");
+	else
+		sieve_code_dumpf(denv, "SERVERMETADATAEXISTS");
+
+	sieve_code_descend(denv);
+
+	if ( metadata && !sieve_opr_string_dump(denv, address, "mailbox") )
+		return FALSE;
+
+	return
+		sieve_opr_stringlist_dump(denv, address, "annotation-names");
+}
+
+/*
+ * Code execution
+ */
+
+static int tst_metadataexists_operation_execute
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	bool metadata = sieve_operation_is(renv->oprtn, metadataexists_operation);
+	struct sieve_stringlist *annotation_names;
+	string_t *mailbox, *annotation_item;
+	bool trace = FALSE;
+	bool all_exist = TRUE;
+	int ret;
+
+	/*
+	 * Read operands
+	 */
+
+	/* Read mailbox */
+	if ( metadata ) {
+		if ( (ret=sieve_opr_string_read(renv, address, "mailbox", &mailbox)) <= 0 )
+			return ret;
+	}
+
+	/* Read annotation names */
+	if ( (ret=sieve_opr_stringlist_read
+		(renv, address, "annotation-names", &annotation_names)) <= 0 )
+		return ret;
+
+	/*
+	 * Perform operation
+	 */
+
+	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_TESTS) ) {
+		if ( metadata )
+			sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "metadataexists test");
+		else
+			sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "servermetadataexists test");
+
+		sieve_runtime_trace_descend(renv);
+
+		trace = sieve_runtime_trace_active(renv, SIEVE_TRLVL_MATCHING);
+	}
+
+	if ( renv->scriptenv->user != NULL ) {
+		int ret;
+
+		annotation_item = NULL;
+		while ( (ret=sieve_stringlist_next_item(annotation_names, &annotation_item))
+			> 0 ) {
+			//const char *annotation = str_c(annotation_item);
+
+			/* IMPLEMENT ... */
+			all_exist = FALSE;
+		}
+
+		if ( ret < 0 ) {
+			sieve_runtime_trace_error
+				(renv, "invalid annotation name stringlist item");
+			return SIEVE_EXEC_BIN_CORRUPT;
+		}
+	}
+
+	if ( trace ) {
+		if ( all_exist )
+			sieve_runtime_trace(renv, 0, "all annotations exist");
+		else
+			sieve_runtime_trace(renv, 0, "some mailboxes no not exist");
+	}
+
+	sieve_interpreter_set_test_result(renv->interp, all_exist);
+	return SIEVE_EXEC_OK;
+}
diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index bc3c4a2dd31954d15974bd006b52b42fc490af5a..c1497fdff2882d1d1a021c9c3b733729dfb7c974 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -99,6 +99,8 @@ extern const struct sieve_extension_def spamtestplus_extension;
 extern const struct sieve_extension_def virustest_extension;
 extern const struct sieve_extension_def ihave_extension;
 extern const struct sieve_extension_def editheader_extension;
+extern const struct sieve_extension_def mboxmetadata_extension;
+extern const struct sieve_extension_def servermetadata_extension;
 
 /* vnd.dovecot. */
 extern const struct sieve_extension_def debug_extension;
@@ -175,7 +177,7 @@ const unsigned int sieve_deprecated_extensions_count =
 extern const struct sieve_extension_def ereject_extension;
 
 const struct sieve_extension_def *sieve_unfinished_extensions[] = {
-	&ereject_extension
+	&ereject_extension, &mboxmetadata_extension, &servermetadata_extension
 };
 
 const unsigned int sieve_unfinished_extensions_count =