diff --git a/Makefile.am b/Makefile.am
index 7261c7867206235b19944457a3c30146741d79e2..18b7c0e3db895ed58f2657756273e8c89d538fd2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,11 @@ endif
 
 # Testsuite tests
 
+if BUILD_ENOTIFY
+ENOTIFY_TESTS = \
+	tests/extensions/enotify/basic.svtest
+endif
+
 TESTSUITE_BIN = $(top_srcdir)/src/testsuite/testsuite
 
 test_cases = \
@@ -57,7 +62,8 @@ test_cases = \
 	tests/extensions/subaddress/basic.svtest \
 	tests/extensions/subaddress/rfc.svtest \
 	tests/extensions/vacation/errors.svtest \
-	tests/extensions/vacation/execute.svtest
+	tests/extensions/vacation/execute.svtest \
+	$(ENOTIFY_TESTS)
 
 $(test_cases):
 	@$(TESTSUITE_BIN) $@
diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c
index 7916f11eeeade478ab424ab6ab8f99c9051133f9..494775244e2dd81d74c28f21d637579ae0cfcbb0 100644
--- a/src/lib-sieve/plugins/enotify/cmd-notify.c
+++ b/src/lib-sieve/plugins/enotify/cmd-notify.c
@@ -67,16 +67,12 @@ static bool cmd_notify_validate_string_tag
 static bool cmd_notify_validate_stringlist_tag
 	(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
 		struct sieve_command_context *cmd);
+static bool cmd_notify_validate_importance_tag
+	(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
+		struct sieve_command_context *cmd);
 
 /* Argument objects */
 
-static const struct sieve_argument notify_importance_tag = { 
-	"importance", 
-	NULL, NULL,
-	cmd_notify_validate_string_tag, 
-	NULL, NULL 
-};
-
 static const struct sieve_argument notify_from_tag = { 
 	"from", 
 	NULL, NULL,
@@ -98,33 +94,40 @@ static const struct sieve_argument notify_message_tag = {
 	NULL, NULL 
 };
 
+static const struct sieve_argument notify_importance_tag = { 
+	"importance", 
+	NULL, NULL,
+	cmd_notify_validate_importance_tag, 
+	NULL, NULL 
+};
+
 /* Codes for optional arguments */
 
 enum cmd_notify_optional {
 	OPT_END,
-	OPT_IMPORTANCE,
 	OPT_FROM,
 	OPT_OPTIONS,
-	OPT_MESSAGE
+	OPT_MESSAGE,
+	OPT_IMPORTANCE
 };
 
 /* 
  * Notify operation 
  */
 
-static bool ext_notify_operation_dump
+static bool cmd_notify_operation_dump
 	(const struct sieve_operation *op,	
 		const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static int ext_notify_operation_execute
+static int cmd_notify_operation_execute
 	(const struct sieve_operation *op, 
 		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_operation notify_operation = { 
-	"notify",
+	"NOTIFY",
 	&enotify_extension,
-	0,
-	ext_notify_operation_dump, 
-	ext_notify_operation_execute
+	EXT_ENOTIFY_OPERATION_NOTIFY,
+	cmd_notify_operation_dump, 
+	cmd_notify_operation_execute
 };
 
 /* 
@@ -183,7 +186,6 @@ static bool cmd_notify_validate_string_tag
 	
 	/* Check syntax:
 	 *   :from <string>
-	 *   :importance <"1" / "2" / "3">
 	 *   :message <string>
 	 */
 	if ( !sieve_validate_tag_parameter
@@ -196,7 +198,7 @@ static bool cmd_notify_validate_string_tag
 		*arg = sieve_ast_argument_next(*arg);
 		
 	} else if ( tag->argument == &notify_message_tag ) {
-		/* Detach optional argument (emitted as mandatory) */
+		/* Skip parameter */
 		*arg = sieve_ast_argument_next(*arg);	
 	}
 			
@@ -226,6 +228,48 @@ static bool cmd_notify_validate_stringlist_tag
 	return TRUE;
 }
 
+static bool cmd_notify_validate_importance_tag
+(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
+{
+	const struct sieve_ast_argument *tag = *arg;
+	const char *impstr;
+
+	/* Detach the tag itself */
+	*arg = sieve_ast_arguments_detach(*arg,1);
+
+	/* Check syntax: 
+	 *   :importance <"1" / "2" / "3">
+	 */
+
+	if ( sieve_ast_argument_type(*arg) != SAAT_STRING ) {
+		/* Not a string */
+		sieve_argument_validate_error(validator, *arg, 
+			"the :importance tag for the notify command requires a string parameter, "
+			"but %s was found", sieve_ast_argument_name(*arg));
+		return FALSE;
+	}
+
+	impstr = sieve_ast_argument_strc(*arg);
+
+	if ( impstr[0] < '1' || impstr[0]  > '3' || impstr[1] != '\0' ) {
+		/* Invalid importance */
+		sieve_argument_validate_error(validator, *arg, 
+			"invalid :importance value for notify command: %s", impstr);
+		return FALSE;
+	} 
+
+	sieve_ast_argument_number_substitute(*arg, impstr[0] - '0');
+	(*arg)->arg_id_code = tag->arg_id_code;
+	(*arg)->argument = &number_argument;
+
+	/* Skip parameter */
+	*arg = sieve_ast_argument_next(*arg);
+			
+	return TRUE;
+}
+
+
 /* 
  * Command registration 
  */
@@ -282,7 +326,7 @@ static bool cmd_notify_generate
  * Code dump
  */
  
-static bool ext_notify_operation_dump
+static bool cmd_notify_operation_dump
 (const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {	
@@ -337,7 +381,7 @@ static bool ext_notify_operation_dump
  * Code execution
  */
  
-static int ext_notify_operation_execute
+static int cmd_notify_operation_execute
 (const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
@@ -378,8 +422,10 @@ static int ext_notify_operation_execute
 				}
 	
 				/* Enforce 0 < importance < 4 (just to be sure) */
-				if ( importance < 1 || importance > 3 )
+				if ( importance < 1 ) 
 					importance = 1;
+				else if ( importance > 3 )
+					importance = 3;
 				break;
 			case OPT_FROM:
 				if ( !sieve_opr_string_read(renv, address, &from) ) {
@@ -387,6 +433,12 @@ static int ext_notify_operation_execute
 					return SIEVE_EXEC_BIN_CORRUPT;
 				}
 				break;
+			case OPT_MESSAGE:
+				if ( !sieve_opr_string_read(renv, address, &message) ) {
+					sieve_runtime_trace_error(renv, "invalid from operand");
+					return SIEVE_EXEC_BIN_CORRUPT;
+				}
+				break;
 			case OPT_OPTIONS:
 				if ( (options=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 					sieve_runtime_trace_error(renv, "invalid options operand");
@@ -394,7 +446,8 @@ static int ext_notify_operation_execute
 				}
 				break;
 			default:
-				sieve_runtime_trace_error(renv, "unknown optional operand");
+				sieve_runtime_trace_error(renv, "unknown optional operand: %d", 
+					opt_code);
 				return SIEVE_EXEC_BIN_CORRUPT;
 			}
 		}
diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.h b/src/lib-sieve/plugins/enotify/ext-enotify-common.h
index 664cf10d144cda7af19a79f42b2780aedd73bcd6..d097b4faf0886e94c085bd6e90504e5f11668252 100644
--- a/src/lib-sieve/plugins/enotify/ext-enotify-common.h
+++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.h
@@ -16,4 +16,14 @@ extern const struct sieve_extension enotify_extension;
 
 extern const struct sieve_command notify_command;
 
+/*
+ * Operands
+ */
+
+extern const struct sieve_operation notify_operation;
+
+enum ext_variables_opcode {
+	EXT_ENOTIFY_OPERATION_NOTIFY
+};
+
 #endif /* __EXT_ENOTIFY_COMMON_H */
diff --git a/src/lib-sieve/plugins/enotify/ext-enotify.c b/src/lib-sieve/plugins/enotify/ext-enotify.c
index 8b02dbe6d73f6627a1c74e86ce519cc4efdb4bcc..cdcabeb3c9011d6617bbea5ff8338510b67e65da 100644
--- a/src/lib-sieve/plugins/enotify/ext-enotify.c
+++ b/src/lib-sieve/plugins/enotify/ext-enotify.c
@@ -26,6 +26,14 @@
 
 #include "ext-enotify-common.h"
 
+/*
+ * Operations
+ */
+
+const struct sieve_operation *ext_enotify_operations[] = {
+	&notify_operation
+};
+
 /* 
  * Extension
  */
@@ -41,7 +49,7 @@ const struct sieve_extension enotify_extension = {
 	ext_enotify_load,
 	ext_enotify_validator_load, 
 	NULL, NULL, NULL, NULL, NULL,
-	SIEVE_EXT_DEFINE_NO_OPERATIONS,
+	SIEVE_EXT_DEFINE_OPERATION(notify_operation),
 	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
 
diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c
index 5e57d31a02dbdd4d658dd9e58456f9665fb17499..7a0782a7dc92b414ce5071d1ff7daf64414c9bad 100644
--- a/src/lib-sieve/sieve-ast.c
+++ b/src/lib-sieve/sieve-ast.c
@@ -492,6 +492,13 @@ void sieve_ast_argument_string_setc
 	str_append(argument->_value.str, newstr);
 }
 
+void sieve_ast_argument_number_substitute
+(struct sieve_ast_argument *argument, unsigned int number)
+{
+	argument->type = SAAT_NUMBER;
+	argument->_value.number = number;
+}
+
 struct sieve_ast_argument *sieve_ast_argument_stringlist_create
 (struct sieve_ast_node *node, unsigned int source_line) 
 {
diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h
index 7e4b424cb1a44f5b429de82614616dc59e5b4376..f2fc4e3e27d8e6e6f0ac9e62447cb2b70756e026 100644
--- a/src/lib-sieve/sieve-ast.h
+++ b/src/lib-sieve/sieve-ast.h
@@ -246,7 +246,9 @@ void sieve_ast_argument_string_setc
 	(struct sieve_ast_argument *argument, const char *newstr);
 
 void sieve_ast_argument_number_set
-    (struct sieve_ast_argument *argument, unsigned int newnum);
+	(struct sieve_ast_argument *argument, unsigned int newnum);
+void sieve_ast_argument_number_substitute
+	(struct sieve_ast_argument *argument, unsigned int number);
 
 struct sieve_ast_argument *sieve_ast_argument_tag_insert
 (struct sieve_ast_argument *before, const char *tag, unsigned int source_line); 
diff --git a/tests/extensions/enotify/basic.svtest b/tests/extensions/enotify/basic.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..65397e24492257369c9cfafe9720832b829180dc
--- /dev/null
+++ b/tests/extensions/enotify/basic.svtest
@@ -0,0 +1,10 @@
+require "vnd.dovecot.testsuite";
+require "enotify";
+
+test "Valid notification" {
+	/* Test to catch runtime segfaults */
+	notify 
+		:message "This is probably very important"
+		:importance "1" 
+		"mailto:alm@example.com";
+}