From d3f85202995853bba91c481b11bc88713158277c Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan.bosch@open-xchange.com>
Date: Sun, 27 Mar 2022 22:27:12 +0200
Subject: [PATCH] lib-sieve: plugins: Remove support for deprecated notify
 extension.

---
 Makefile.am                                   |   5 -
 configure.ac                                  |   1 -
 src/lib-sieve/Makefile.am                     |   1 -
 src/lib-sieve/plugins/Makefile.am             |   1 -
 src/lib-sieve/plugins/notify/Makefile.am      |  20 -
 src/lib-sieve/plugins/notify/cmd-denotify.c   | 389 --------
 src/lib-sieve/plugins/notify/cmd-notify.c     | 900 ------------------
 .../plugins/notify/ext-notify-common.c        | 354 -------
 .../plugins/notify/ext-notify-common.h        |  66 --
 .../plugins/notify/ext-notify-limits.h        |   7 -
 src/lib-sieve/plugins/notify/ext-notify.c     | 108 ---
 src/lib-sieve/sieve-extensions.c              |   2 -
 tests/deprecated/notify/basic.svtest          |  59 --
 tests/deprecated/notify/denotify.svtest       | 279 ------
 tests/deprecated/notify/errors.svtest         |  33 -
 .../notify/errors/conflict-ihave.sieve        |   8 -
 tests/deprecated/notify/errors/conflict.sieve |   4 -
 tests/deprecated/notify/errors/options.sieve  |  11 -
 tests/deprecated/notify/execute.svtest        |  25 -
 .../notify/execute/duplicates.sieve           |   4 -
 tests/deprecated/notify/mailto.svtest         | 317 ------
 21 files changed, 2594 deletions(-)
 delete mode 100644 src/lib-sieve/plugins/notify/Makefile.am
 delete mode 100644 src/lib-sieve/plugins/notify/cmd-denotify.c
 delete mode 100644 src/lib-sieve/plugins/notify/cmd-notify.c
 delete mode 100644 src/lib-sieve/plugins/notify/ext-notify-common.c
 delete mode 100644 src/lib-sieve/plugins/notify/ext-notify-common.h
 delete mode 100644 src/lib-sieve/plugins/notify/ext-notify-limits.h
 delete mode 100644 src/lib-sieve/plugins/notify/ext-notify.c
 delete mode 100644 tests/deprecated/notify/basic.svtest
 delete mode 100644 tests/deprecated/notify/denotify.svtest
 delete mode 100644 tests/deprecated/notify/errors.svtest
 delete mode 100644 tests/deprecated/notify/errors/conflict-ihave.sieve
 delete mode 100644 tests/deprecated/notify/errors/conflict.sieve
 delete mode 100644 tests/deprecated/notify/errors/options.sieve
 delete mode 100644 tests/deprecated/notify/execute.svtest
 delete mode 100644 tests/deprecated/notify/execute/duplicates.sieve
 delete mode 100644 tests/deprecated/notify/mailto.svtest

diff --git a/Makefile.am b/Makefile.am
index 39f32d6a5..a46430b65 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -182,11 +182,6 @@ test_cases = \
 	tests/extensions/vnd.dovecot/environment/variables.svtest \
 	tests/extensions/vnd.dovecot/report/errors.svtest \
 	tests/extensions/vnd.dovecot/report/execute.svtest \
-	tests/deprecated/notify/basic.svtest \
-	tests/deprecated/notify/mailto.svtest \
-	tests/deprecated/notify/errors.svtest \
-	tests/deprecated/notify/execute.svtest \
-	tests/deprecated/notify/denotify.svtest \
 	tests/deprecated/imapflags/execute.svtest \
 	tests/deprecated/imapflags/errors.svtest \
 	$(test_unfinished)
diff --git a/configure.ac b/configure.ac
index ebd85d9a3..e4defa0bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -214,7 +214,6 @@ src/lib-sieve/plugins/body/Makefile
 src/lib-sieve/plugins/variables/Makefile
 src/lib-sieve/plugins/enotify/Makefile
 src/lib-sieve/plugins/enotify/mailto/Makefile
-src/lib-sieve/plugins/notify/Makefile
 src/lib-sieve/plugins/environment/Makefile
 src/lib-sieve/plugins/mailbox/Makefile
 src/lib-sieve/plugins/date/Makefile
diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index 2e80871bb..7fb2a4fa2 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -67,7 +67,6 @@ plugins = \
 	$(extdir)/body/libsieve_ext_body.la \
 	$(extdir)/variables/libsieve_ext_variables.la \
 	$(extdir)/enotify/libsieve_ext_enotify.la \
-	$(extdir)/notify/libsieve_ext_notify.la \
 	$(extdir)/environment/libsieve_ext_environment.la \
 	$(extdir)/mailbox/libsieve_ext_mailbox.la \
 	$(extdir)/date/libsieve_ext_date.la \
diff --git a/src/lib-sieve/plugins/Makefile.am b/src/lib-sieve/plugins/Makefile.am
index 2a1c0548f..eb3c8f50d 100644
--- a/src/lib-sieve/plugins/Makefile.am
+++ b/src/lib-sieve/plugins/Makefile.am
@@ -14,7 +14,6 @@ SUBDIRS = \
 	body \
 	variables \
 	enotify \
-	notify \
 	environment \
 	mailbox \
 	date \
diff --git a/src/lib-sieve/plugins/notify/Makefile.am b/src/lib-sieve/plugins/notify/Makefile.am
deleted file mode 100644
index aaa76b357..000000000
--- a/src/lib-sieve/plugins/notify/Makefile.am
+++ /dev/null
@@ -1,20 +0,0 @@
-noinst_LTLIBRARIES = libsieve_ext_notify.la
-
-AM_CPPFLAGS = \
-	-I$(srcdir)/../.. \
-	-I$(srcdir)/../../util \
-	$(LIBDOVECOT_INCLUDE)
-
-commands = \
-	cmd-notify.c \
-	cmd-denotify.c
-
-libsieve_ext_notify_la_SOURCES = \
-	ext-notify.c \
-	ext-notify-common.c \
-	$(commands)
-
-noinst_HEADERS = \
-	ext-notify-common.h \
-	ext-notify-limits.h
-
diff --git a/src/lib-sieve/plugins/notify/cmd-denotify.c b/src/lib-sieve/plugins/notify/cmd-denotify.c
deleted file mode 100644
index 876980885..000000000
--- a/src/lib-sieve/plugins/notify/cmd-denotify.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
- */
-
-#include "lib.h"
-
-#include "sieve-common.h"
-#include "sieve-stringlist.h"
-#include "sieve-code.h"
-#include "sieve-extensions.h"
-#include "sieve-ast.h"
-#include "sieve-commands.h"
-#include "sieve-match-types.h"
-#include "sieve-comparators.h"
-#include "sieve-match.h"
-#include "sieve-actions.h"
-#include "sieve-validator.h"
-#include "sieve-generator.h"
-#include "sieve-interpreter.h"
-#include "sieve-dump.h"
-#include "sieve-result.h"
-
-#include "ext-notify-common.h"
-
-/*
- * Denotify command
- *
- * Syntax:
- *   denotify [MATCH-TYPE string] [<":low" / ":normal" / ":high">]
- */
-
-static bool cmd_denotify_registered
-	(struct sieve_validator *valdtr, const struct sieve_extension *ext,
-		struct sieve_command_registration *cmd_reg);
-static bool cmd_denotify_pre_validate
-	(struct sieve_validator *valdtr, struct sieve_command *cmd);
-static bool cmd_denotify_validate
-	(struct sieve_validator *valdtr, struct sieve_command *cmd);
-static bool cmd_denotify_generate
-	(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd);
-
-const struct sieve_command_def cmd_denotify = {
-	.identifier = "denotify",
-	.type = SCT_COMMAND,
-	.positional_args = 0,
-	.subtests = 0,
-	.block_allowed = FALSE,
-	.block_required = FALSE,
-	.registered = cmd_denotify_registered,
-	.pre_validate = cmd_denotify_pre_validate,
-	.validate = cmd_denotify_validate,
-	.generate = cmd_denotify_generate
-};
-
-/*
- * Tagged arguments
- */
-
-/* Forward declarations */
-
-static bool tag_match_type_is_instance_of
-	(struct sieve_validator *validator, struct sieve_command *cmd,
-		const struct sieve_extension *ext, const char *identifier, void **data);
-static bool tag_match_type_validate
-	(struct sieve_validator *validator, struct sieve_ast_argument **arg,
-		struct sieve_command *cmd);
-
-/* Argument object */
-
-const struct sieve_argument_def denotify_match_tag = {
-	.identifier = "MATCH-TYPE-STRING",
-	.is_instance_of = tag_match_type_is_instance_of,
-	.validate = tag_match_type_validate
-};
-
-/* Codes for optional operands */
-
-enum cmd_denotify_optional {
-	OPT_END,
-	OPT_IMPORTANCE,
-	OPT_MATCH_TYPE,
-	OPT_MATCH_KEY
-};
-
-/*
- * Denotify operation
- */
-
-static bool cmd_denotify_operation_dump
-	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
-static int cmd_denotify_operation_execute
-	(const struct sieve_runtime_env *renv, sieve_size_t *address);
-
-const struct sieve_operation_def denotify_operation = {
-	.mnemonic = "DENOTIFY",
-	.ext_def = &notify_extension,
-	.code = EXT_NOTIFY_OPERATION_DENOTIFY,
-	.dump = cmd_denotify_operation_dump,
-	.execute = cmd_denotify_operation_execute
-};
-
-/*
- * Command validation context
- */
-
-struct cmd_denotify_context_data {
-	struct sieve_ast_argument *match_key_arg;
-};
-
-/*
- * Tag validation
- */
-
-static bool tag_match_type_is_instance_of
-(struct sieve_validator *valdtr, struct sieve_command *cmd,
-	const struct sieve_extension *ext, const char *identifier, void **data)
-{
-	return match_type_tag.is_instance_of(valdtr, cmd, ext, identifier, data);
-}
-
-static bool tag_match_type_validate
-(struct sieve_validator *valdtr, struct sieve_ast_argument **arg,
-	struct sieve_command *cmd)
-{
-	struct cmd_denotify_context_data *cmd_data =
-        (struct cmd_denotify_context_data *) cmd->data;
-	struct sieve_ast_argument *tag = *arg;
-
-	i_assert(tag != NULL);
-
-	if ( !match_type_tag.validate(valdtr, arg, cmd) )
-		return FALSE;
-
-	if ( *arg == NULL ) {
-		sieve_argument_validate_error(valdtr, tag,
-			"the MATCH-TYPE argument (:%s) for the denotify command requires "
-			"an additional key-string parameter, but no more arguments were found",
-			sieve_ast_argument_tag(tag));
-		return FALSE;
-	}
-
-	if ( sieve_ast_argument_type(*arg) != SAAT_STRING )
-	{
-		sieve_argument_validate_error(valdtr, *arg,
-			"the MATCH-TYPE argument (:%s) for the denotify command requires "
-			"an additional key-string parameter, but %s was found",
-			sieve_ast_argument_tag(tag), sieve_ast_argument_name(*arg));
-		return FALSE;
-	}
-
-	if ( !sieve_validator_argument_activate(valdtr, cmd, *arg, FALSE) )
-		return FALSE;
-
-	tag->argument->def = &match_type_tag;
-	tag->argument->ext = NULL;
-
-	(*arg)->argument->id_code = OPT_MATCH_KEY;
-	cmd_data->match_key_arg = *arg;
-
-	*arg = sieve_ast_argument_next(*arg);
-
-	return TRUE;
-}
-
-/*
- * Command registration
- */
-
-static bool cmd_denotify_registered
-(struct sieve_validator *valdtr, const struct sieve_extension *ext,
-	struct sieve_command_registration *cmd_reg)
-{
-	sieve_validator_register_tag
-		(valdtr, cmd_reg, ext, &denotify_match_tag, OPT_MATCH_TYPE);
-
-	ext_notify_register_importance_tags(valdtr, cmd_reg, ext, OPT_IMPORTANCE);
-
-	return TRUE;
-}
-
-/*
- * Command validation
- */
-
-static bool cmd_denotify_pre_validate
-(struct sieve_validator *valdtr ATTR_UNUSED,
-	struct sieve_command *cmd)
-{
-	struct cmd_denotify_context_data *ctx_data;
-
-	/* Assign context */
-	ctx_data = p_new(sieve_command_pool(cmd),
-		struct cmd_denotify_context_data, 1);
-	cmd->data = (void *) ctx_data;
-
-	return TRUE;
-}
-
-static bool cmd_denotify_validate
-(struct sieve_validator *valdtr, struct sieve_command *cmd)
-{
-    struct cmd_denotify_context_data *ctx_data =
-        (struct cmd_denotify_context_data *) cmd->data;
-	struct sieve_ast_argument *key_arg = ctx_data->match_key_arg;
-	const struct sieve_match_type mcht_default =
-		SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
-	const struct sieve_comparator cmp_default =
-		SIEVE_COMPARATOR_DEFAULT(i_octet_comparator);
-
-	if ( key_arg != NULL ) {
-		if ( !sieve_match_type_validate
-			(valdtr, cmd, key_arg, &mcht_default, &cmp_default) )
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-/*
- * Code generation
- */
-
-static bool cmd_denotify_generate
-(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd)
-{
-	sieve_operation_emit(cgenv->sblock, cmd->ext, &denotify_operation);
-
-	/* Generate arguments */
-	return sieve_generate_arguments(cgenv, cmd, NULL);
-}
-
-/*
- * Code dump
- */
-
-static bool cmd_denotify_operation_dump
-(const struct sieve_dumptime_env *denv, sieve_size_t *address)
-{
-	const struct sieve_operation *op = denv->oprtn;
-	int opt_code = 0;
-
-	sieve_code_dumpf(denv, "%s", sieve_operation_mnemonic(op));
-	sieve_code_descend(denv);
-
-	for (;;) {
-		int opt;
-		bool opok = TRUE;
-
-		if ( (opt=sieve_opr_optional_dump(denv, address, &opt_code)) < 0 )
-			return FALSE;
-
-		if ( opt == 0 ) break;
-
-		switch ( opt_code ) {
-		case OPT_MATCH_KEY:
-			opok = sieve_opr_string_dump(denv, address, "key-string");
-			break;
-		case OPT_MATCH_TYPE:
-			opok = sieve_opr_match_type_dump(denv, address);
-			break;
-		case OPT_IMPORTANCE:
-			opok = sieve_opr_number_dump(denv, address, "importance");
-			break;
-		default:
-			return FALSE;
-		}
-
-		if ( !opok ) return FALSE;
-	}
-
-	return TRUE;
-}
-
-/*
- * Code execution
- */
-
-static int cmd_denotify_operation_execute
-(const struct sieve_runtime_env *renv, sieve_size_t *address)
-{
-	int opt_code = 0;
-	struct sieve_match_type mcht =
-		SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
-	const struct sieve_comparator cmp =
-		SIEVE_COMPARATOR_DEFAULT(i_octet_comparator);
-	struct sieve_stringlist *match_key = NULL;
-	sieve_number_t importance = 0;
-	struct sieve_match_context *mctx;
-	struct sieve_result_iterate_context *rictx;
-	const struct sieve_action *action;
-	int ret;
-
-	/*
-	 * Read operands
-	 */
-
-	/* Optional operands */
-
-	for (;;) {
-		int opt;
-
-		if ( (opt=sieve_opr_optional_read(renv, address, &opt_code)) < 0 )
-			return SIEVE_EXEC_BIN_CORRUPT;
-
-		if ( opt == 0 ) break;
-
-		switch ( opt_code ) {
-		case OPT_MATCH_TYPE:
-			ret = sieve_opr_match_type_read(renv, address, &mcht);
-			break;
-		case OPT_MATCH_KEY:
-			ret = sieve_opr_stringlist_read(renv, address, "match key", &match_key);
-			break;
-		case OPT_IMPORTANCE:
-			ret = sieve_opr_number_read(renv, address, "importance", &importance);
-			break;
-		default:
-			sieve_runtime_trace_error(renv, "unknown optional operand");
-			return SIEVE_EXEC_BIN_CORRUPT;
-		}
-
-		if ( ret <= 0 ) return ret;
-	}
-
-	/*
-	 * Perform operation
-	 */
-
-	/* Enforce 0 < importance < 4 (just to be sure) */
-
-	if ( importance < 1 )
-		importance = 1;
-	else if ( importance > 3 )
-		importance = 3;
-
-	/* Trace */
-
-	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "denotify action");
-
-	/* Either do string matching or just kill all notify actions */
-	if ( match_key != NULL ) {
-		/* Initialize match */
-		mctx = sieve_match_begin(renv, &mcht, &cmp);
-
-		/* Iterate through all notify actions and delete those that match */
-		rictx = sieve_result_iterate_init(renv->result);
-
-		while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) {
-			if ( sieve_action_is(action, act_notify_old) ) {
-				struct ext_notify_action *nact =
-					(struct ext_notify_action *) action->context;
-
-				if ( importance == 0 || nact->importance == importance ) {
-					int match;
-
-					if ( (match=sieve_match_value
-						(mctx, nact->id, strlen(nact->id), match_key)) < 0 )
-						break;
-
-					if ( match > 0 )
-						sieve_result_iterate_delete(rictx);
-				}
-			}
-		}
-
-		/* Finish match */
-		if ( sieve_match_end(&mctx, &ret) < 0 )
-			return ret;
-
-	} else {
-		/* Delete all notify actions */
-		rictx = sieve_result_iterate_init(renv->result);
-
-		while ( (action=sieve_result_iterate_next(rictx, NULL)) != NULL ) {
-
-			if ( sieve_action_is(action, act_notify_old) ) {
-				struct ext_notify_action *nact =
-					(struct ext_notify_action *) action->context;
-
-				if ( importance == 0 || nact->importance == importance )
-					sieve_result_iterate_delete(rictx);
-			}
-		}
-	}
-
-	return SIEVE_EXEC_OK;
-}
-
-
-
diff --git a/src/lib-sieve/plugins/notify/cmd-notify.c b/src/lib-sieve/plugins/notify/cmd-notify.c
deleted file mode 100644
index a683c3131..000000000
--- a/src/lib-sieve/plugins/notify/cmd-notify.c
+++ /dev/null
@@ -1,900 +0,0 @@
-/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
- */
-
-#include "lib.h"
-#include "array.h"
-#include "str.h"
-#include "ioloop.h"
-#include "str-sanitize.h"
-#include "ostream.h"
-#include "message-date.h"
-#include "mail-storage.h"
-
-#include "rfc2822.h"
-
-#include "sieve-common.h"
-#include "sieve-stringlist.h"
-#include "sieve-code.h"
-#include "sieve-extensions.h"
-#include "sieve-commands.h"
-#include "sieve-actions.h"
-#include "sieve-validator.h"
-#include "sieve-generator.h"
-#include "sieve-interpreter.h"
-#include "sieve-dump.h"
-#include "sieve-result.h"
-#include "sieve-address.h"
-#include "sieve-message.h"
-#include "sieve-smtp.h"
-
-#include "ext-notify-common.h"
-#include "ext-notify-limits.h"
-
-#include <ctype.h>
-
-/* Notify command (DEPRECATED)
- *
- * Syntax:
- *   notify [":method" string] [":id" string] [":options" string-list]
- *          [<":low" / ":normal" / ":high">] ["message:" string]
- *
- */
-
-static bool
-cmd_notify_registered(struct sieve_validator *valdtr,
-		      const struct sieve_extension *ext,
-		      struct sieve_command_registration *cmd_reg);
-static bool
-cmd_notify_pre_validate(struct sieve_validator *valdtr,
-			struct sieve_command *cmd);
-static bool
-cmd_notify_validate(struct sieve_validator *valdtr,
-		    struct sieve_command *cmd);
-static bool
-cmd_notify_generate(const struct sieve_codegen_env *cgenv,
-		    struct sieve_command *ctx);
-
-const struct sieve_command_def cmd_notify_old = {
-	.identifier = "notify",
-	.type = SCT_COMMAND,
-	.positional_args = 0,
-	.subtests = 0,
-	.block_allowed = FALSE,
-	.block_required = FALSE,
-	.registered = cmd_notify_registered,
-	.pre_validate = cmd_notify_pre_validate,
-	.validate = cmd_notify_validate,
-	.generate = cmd_notify_generate
-};
-
-/*
- * Tagged arguments
- */
-
-/* Forward declarations */
-
-static bool
-cmd_notify_validate_string_tag(struct sieve_validator *valdtr,
-			       struct sieve_ast_argument **arg,
-			       struct sieve_command *cmd);
-static bool
-cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr,
-				   struct sieve_ast_argument **arg,
-				   struct sieve_command *cmd);
-
-/* Argument objects */
-
-static const struct sieve_argument_def notify_method_tag = {
-	.identifier = "method",
-	.validate = cmd_notify_validate_string_tag
-};
-
-static const struct sieve_argument_def notify_options_tag = {
-	.identifier = "options",
-	.validate = cmd_notify_validate_stringlist_tag
-};
-
-static const struct sieve_argument_def notify_id_tag = {
-	.identifier = "id",
-	.validate = cmd_notify_validate_string_tag
-};
-
-static const struct sieve_argument_def notify_message_tag = {
-	.identifier = "message",
-	.validate = cmd_notify_validate_string_tag
-};
-
-/*
- * Notify operation
- */
-
-static bool
-cmd_notify_operation_dump(const struct sieve_dumptime_env *denv,
-			  sieve_size_t *address);
-static int
-cmd_notify_operation_execute(const struct sieve_runtime_env *renv,
-			     sieve_size_t *address);
-
-const struct sieve_operation_def notify_old_operation = {
-	.mnemonic = "NOTIFY",
-	.ext_def = &notify_extension,
-	.code = EXT_NOTIFY_OPERATION_NOTIFY,
-	.dump = cmd_notify_operation_dump,
-	.execute = cmd_notify_operation_execute
-};
-
-/* Codes for optional operands */
-
-enum cmd_notify_optional {
-  OPT_END,
-  OPT_MESSAGE,
-  OPT_IMPORTANCE,
-  OPT_OPTIONS,
-  OPT_ID
-};
-
-/*
- * Notify action
- */
-
-/* Forward declarations */
-
-static int
-act_notify_check_duplicate(const struct sieve_runtime_env *renv,
-			   const struct sieve_action *act,
-			   const struct sieve_action *act_other);
-static void
-act_notify_print(const struct sieve_action *action,
-		 const struct sieve_result_print_env *rpenv, bool *keep);
-static int
-act_notify_commit(const struct sieve_action_exec_env *aenv,
-		  void *tr_context);
-
-/* Action object */
-
-const struct sieve_action_def act_notify_old = {
-	.name = "notify",
-	.check_duplicate = act_notify_check_duplicate,
-	.print = act_notify_print,
-	.commit = act_notify_commit
-};
-
-/*
- * Command validation context
- */
-
-struct cmd_notify_context_data {
-	struct sieve_ast_argument *id;
-	struct sieve_ast_argument *method;
-	struct sieve_ast_argument *options;
-	struct sieve_ast_argument *message;
-};
-
-/*
- * Tag validation
- */
-
-static bool
-cmd_notify_validate_string_tag(struct sieve_validator *valdtr,
-			       struct sieve_ast_argument **arg,
-			       struct sieve_command *cmd)
-{
-	struct sieve_ast_argument *tag = *arg;
-	struct cmd_notify_context_data *ctx_data =
-		(struct cmd_notify_context_data *)cmd->data;
-
-	/* Detach the tag itself */
-	*arg = sieve_ast_arguments_detach(*arg, 1);
-
-	/* Check syntax:
-	 *   :id <string>
-	 *   :method <string>
-	 *   :message <string>
-	 */
-	if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0,
-					  SAAT_STRING, FALSE))
-		return FALSE;
-
-	if (sieve_argument_is(tag, notify_method_tag)) {
-		ctx_data->method = *arg;
-
-		/* Removed */
-		*arg = sieve_ast_arguments_detach(*arg, 1);
-	} else if (sieve_argument_is(tag, notify_id_tag)) {
-		ctx_data->id = *arg;
-
-		/* Skip parameter */
-		*arg = sieve_ast_argument_next(*arg);
-	} else if (sieve_argument_is(tag, notify_message_tag)) {
-		ctx_data->message = *arg;
-
-		/* Skip parameter */
-		*arg = sieve_ast_argument_next(*arg);
-	}
-	return TRUE;
-}
-
-static bool
-cmd_notify_validate_stringlist_tag(struct sieve_validator *valdtr,
-				   struct sieve_ast_argument **arg,
-				   struct sieve_command *cmd)
-{
-	struct sieve_ast_argument *tag = *arg;
-	struct cmd_notify_context_data *ctx_data =
-		(struct cmd_notify_context_data *)cmd->data;
-
-	/* Detach the tag itself */
-	*arg = sieve_ast_arguments_detach(*arg,1);
-
-	/* Check syntax:
-	 *   :options string-list
-	 */
-	if (!sieve_validate_tag_parameter(valdtr, cmd, tag, *arg, NULL, 0,
-					  SAAT_STRING_LIST, FALSE))
-		return FALSE;
-
-	/* Assign context */
-	ctx_data->options = *arg;
-
-	/* Skip parameter */
-	*arg = sieve_ast_argument_next(*arg);
-
-	return TRUE;
-}
-
-/*
- * Command registration
- */
-
-static bool
-cmd_notify_registered(struct sieve_validator *valdtr,
-		      const struct sieve_extension *ext,
-		      struct sieve_command_registration *cmd_reg)
-{
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &notify_method_tag, 0);
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &notify_id_tag, OPT_ID);
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &notify_message_tag, OPT_MESSAGE);
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &notify_options_tag, OPT_OPTIONS);
-
-	ext_notify_register_importance_tags(valdtr, cmd_reg, ext,
-					    OPT_IMPORTANCE);
-
-	return TRUE;
-}
-
-/*
- * Command validation
- */
-
-static bool
-cmd_notify_pre_validate(struct sieve_validator *valdtr ATTR_UNUSED,
-			struct sieve_command *cmd)
-{
-	struct cmd_notify_context_data *ctx_data;
-
-	/* Create context */
-	ctx_data = p_new(sieve_command_pool(cmd),
-			 struct cmd_notify_context_data, 1);
-	cmd->data = ctx_data;
-
-	return TRUE;
-}
-
-static int
-cmd_notify_address_validate(void *context, struct sieve_ast_argument *arg)
-{
-	struct sieve_validator *valdtr = (struct sieve_validator *)context;
-
-	if (sieve_argument_is_string_literal(arg)) {
-		string_t *address = sieve_ast_argument_str(arg);
-		const char *error;
-		int result;
-
-		T_BEGIN {
-			result = (sieve_address_validate_str(address, &error) ?
-				  1 : -1);
-
-			if (result <= 0) {
-				sieve_argument_validate_error(
-					valdtr, arg,
-					"specified :options address '%s' is invalid for "
-					"the mailto notify method: %s",
-					str_sanitize(str_c(address), 128),
-					error);
-			}
-		} T_END;
-
-		return result;
-	}
-
-	return 1;
-}
-
-static bool
-cmd_notify_validate(struct sieve_validator *valdtr, struct sieve_command *cmd)
-{
-	struct cmd_notify_context_data *ctx_data =
-		(struct cmd_notify_context_data *)cmd->data;
-
-	/* Check :method argument */
-	if (ctx_data->method != NULL)	{
-		const char *method = sieve_ast_argument_strc(ctx_data->method);
-
-		if (strcasecmp(method, "mailto") != 0) {
-			sieve_command_validate_error(
-				valdtr, cmd,
-				"the notify command of the deprecated notify extension "
-				"only supports the 'mailto' notification method");
-			return FALSE;
-		}
-	}
-
-	/* Check :options argument */
-	if (ctx_data->options != NULL) {
-		struct sieve_ast_argument *option = ctx_data->options;
-
-		/* Parse and check options */
-		if (sieve_ast_stringlist_map(
-			&option, (void *)valdtr,
-			cmd_notify_address_validate) <= 0) {
-			return FALSE;
-		}
-	} else {
-		sieve_command_validate_warning(
-			valdtr, cmd,
-			"no :options (and hence recipients) specified for the notify command");
-	}
-
-	return TRUE;
-}
-
-/*
- * Code generation
- */
-
-static bool
-cmd_notify_generate(const struct sieve_codegen_env *cgenv,
-		    struct sieve_command *cmd)
-{
-	sieve_operation_emit(cgenv->sblock, cmd->ext, &notify_old_operation);
-
-	/* Generate arguments */
-	return sieve_generate_arguments(cgenv, cmd, NULL);
-}
-
-/*
- * Code dump
- */
-
-static bool
-cmd_notify_operation_dump(const struct sieve_dumptime_env *denv,
-			  sieve_size_t *address)
-{
-	int opt_code = 0;
-
-	sieve_code_dumpf(denv, "NOTIFY");
-	sieve_code_descend(denv);
-
-	/* Dump optional operands */
-	for (;;) {
-		int opt;
-		bool opok = TRUE;
-
-		if ((opt = sieve_opr_optional_dump(denv, address,
-						   &opt_code)) < 0)
-			return FALSE;
-
-		if (opt == 0)
-			break;
-
-		switch (opt_code) {
-		case OPT_IMPORTANCE:
-			opok = sieve_opr_number_dump(denv, address,
-						     "importance");
-			break;
-		case OPT_ID:
-			opok = sieve_opr_string_dump(denv, address,
-						     "id");
-			break;
-		case OPT_OPTIONS:
-			opok = sieve_opr_stringlist_dump(denv, address,
-							 "options");
-			break;
-		case OPT_MESSAGE:
-			opok = sieve_opr_string_dump(denv, address,
-						     "message");
-			break;
-		default:
-			return FALSE;
-		}
-
-		if (!opok)
-			return FALSE;
-	}
-
-	return TRUE;
-}
-
-/*
- * Code execution
- */
-
-
-static int
-cmd_notify_operation_execute(const struct sieve_runtime_env *renv,
-			     sieve_size_t *address)
-{
-	const struct sieve_extension *this_ext = renv->oprtn->ext;
-	struct ext_notify_action *act;
-	pool_t pool;
-	int opt_code = 0;
-	sieve_number_t importance = 1;
-	struct sieve_stringlist *options = NULL;
-	string_t *message = NULL, *id = NULL;
-	int ret = 0;
-
-	/*
-	 * Read operands
-	 */
-
-	/* Optional operands */
-
-	for (;;) {
-		int opt;
-
-		if ((opt = sieve_opr_optional_read(renv, address,
-						   &opt_code)) < 0)
-			return SIEVE_EXEC_BIN_CORRUPT;
-
-		if (opt == 0)
-			break;
-
-		switch (opt_code) {
-		case OPT_IMPORTANCE:
-			ret = sieve_opr_number_read(renv, address, "importance",
-						    &importance);
-			break;
-		case OPT_ID:
-			ret = sieve_opr_string_read(renv, address, "id", &id);
-			break;
-		case OPT_MESSAGE:
-			ret = sieve_opr_string_read(renv, address, "from",
-						    &message);
-			break;
-		case OPT_OPTIONS:
-			ret = sieve_opr_stringlist_read(renv, address,
-							"options", &options);
-			break;
-		default:
-			sieve_runtime_trace_error(
-				renv, "unknown optional operand");
-			return SIEVE_EXEC_BIN_CORRUPT;
-		}
-
-		if (ret <= 0) return ret;
-	}
-
-	/*
-	 * Perform operation
-	 */
-
-	/* Enforce 0 < importance < 4 (just to be sure) */
-
-	if (importance < 1)
-		importance = 1;
-	else if (importance > 3)
-		importance = 3;
-
-	/* Trace */
-
-	sieve_runtime_trace(renv, SIEVE_TRLVL_ACTIONS, "notify action");
-
-	/* Compose action */
-	if (options != NULL) {
-		string_t *raw_address;
-		string_t *out_message;
-
-		pool = sieve_result_pool(renv->result);
-		act = p_new(pool, struct ext_notify_action, 1);
-		if (id != NULL)
-			act->id = p_strdup(pool, str_c(id));
-		act->importance = importance;
-
-		/* Process message */
-
-		out_message = t_str_new(1024);
-		if ((ret = ext_notify_construct_message(
-			renv, (message == NULL ? NULL : str_c(message)),
-			out_message)) <= 0)
-			return ret;
-		act->message = p_strdup(pool, str_c(out_message));
-
-		/* Normalize and verify all :options addresses */
-
-		sieve_stringlist_reset(options);
-
-		p_array_init(&act->recipients, pool, 4);
-
-		raw_address = NULL;
-		while ((ret = sieve_stringlist_next_item(
-			options, &raw_address)) > 0) {
-			const char *error = NULL;
-			const struct smtp_address *address;
-
-			/* Add if valid address */
-			address = sieve_address_parse_str(raw_address, &error);
-			if (address != NULL) {
-				const struct ext_notify_recipient *rcpts;
-				unsigned int rcpt_count, i;
-
-				/* Prevent duplicates */
-				rcpts = array_get(&act->recipients, &rcpt_count);
-
-				for (i = 0; i < rcpt_count; i++) {
-					if (smtp_address_equals(rcpts[i].address,
-								address))
-						break;
-				}
-
-				/* Add only if unique */
-				if (i != rcpt_count) {
-					sieve_runtime_warning(
-						renv, NULL,
-						"duplicate recipient '%s' specified in the :options argument of "
-						"the deprecated notify command",
-						str_sanitize(str_c(raw_address), 128));
-
-				} else if (array_count(&act->recipients) >=
-					EXT_NOTIFY_MAX_RECIPIENTS) {
-					sieve_runtime_warning(renv, NULL,
-						"more than the maximum %u recipients are specified "
-						"for the deprecated notify command; "
-						"the rest is discarded",
-						EXT_NOTIFY_MAX_RECIPIENTS);
-					break;
-
-				} else {
-					struct ext_notify_recipient recipient;
-
-					recipient.full =
-						p_strdup(pool, str_c(raw_address));
-					recipient.address =
-						smtp_address_clone(pool, address);
-
-					array_append(&act->recipients, &recipient, 1);
-				}
-			} else {
-				sieve_runtime_error(
-					renv, NULL,
-					"specified :options address '%s' is invalid for "
-					"the deprecated notify command: %s",
-					str_sanitize(str_c(raw_address), 128), error);
-				return SIEVE_EXEC_FAILURE;
-			}
-		}
-
-		if (ret < 0) {
-			sieve_runtime_trace_error(
-				renv, "invalid options stringlist");
-			return SIEVE_EXEC_BIN_CORRUPT;
-		}
-
-		if (sieve_result_add_action(renv, this_ext, "notify",
-					    &act_notify_old, NULL, (void *)act,
-					    0, FALSE) < 0)
-			return SIEVE_EXEC_FAILURE;
-	}
-
-	return SIEVE_EXEC_OK;
-}
-
-/*
- * Action
- */
-
-/* Runtime verification */
-
-static int
-act_notify_check_duplicate(const struct sieve_runtime_env *renv ATTR_UNUSED,
-			   const struct sieve_action *act ATTR_UNUSED,
-			   const struct sieve_action *act_other ATTR_UNUSED)
-{
-	struct ext_notify_action *new_nact, *old_nact;
-	const struct ext_notify_recipient *new_rcpts;
-	const struct ext_notify_recipient *old_rcpts;
-	unsigned int new_count, old_count, i, j;
-	unsigned int del_start = 0, del_len = 0;
-
-	if (act->context == NULL || act_other->context == NULL)
-		return 0;
-
-	new_nact = (struct ext_notify_action *)act->context;
-	old_nact = (struct ext_notify_action *)act_other->context;
-
-	new_rcpts = array_get(&new_nact->recipients, &new_count);
-	old_rcpts = array_get(&old_nact->recipients, &old_count);
-
-	for (i = 0; i < new_count; i++) {
-		for (j = 0; j < old_count; j++) {
-			if (smtp_address_equals(new_rcpts[i].address,
-						old_rcpts[j].address))
-				break;
-		}
-
-		if (j == old_count) {
-			/* Not duplicate */
-			if (del_len > 0) {
-				/* Perform pending deletion */
-				array_delete(&new_nact->recipients,
-					     del_start, del_len);
-
-				/* Make sure the loop integrity is maintained */
-				i -= del_len;
-				new_rcpts = array_get(&new_nact->recipients,
-						      &new_count);
-			}
-
-			del_len = 0;
-		} else {
-			/* Mark deletion */
-			if (del_len == 0)
-				del_start = i;
-			del_len++;
-		}
-	}
-
-	/* Perform pending deletion */
-	if (del_len > 0)
-		array_delete(&new_nact->recipients, del_start, del_len);
-
-	return (array_count(&new_nact->recipients) > 0 ? 0 : 1);
-}
-
-/* Result printing */
-
-static void
-act_notify_print(const struct sieve_action *action,
-		 const struct sieve_result_print_env *rpenv,
-		 bool *keep ATTR_UNUSED)
-{
-	const struct ext_notify_action *act =
-		(const struct ext_notify_action *)action->context;
-	const struct ext_notify_recipient *recipients;
-	unsigned int count, i;
-
-	sieve_result_action_printf(
-		rpenv, "send (deprecated) notification with method 'mailto':");
-
-	/* Print main method parameters */
-
-	sieve_result_printf(rpenv, "    => importance    : %llu\n",
-			    (unsigned long long)act->importance);
-
-	if (act->message != NULL) {
-		sieve_result_printf(
-			rpenv, "    => message       : %s\n", act->message);
-	}
-	if (act->id != NULL) {
-		sieve_result_printf(
-			rpenv, "    => id            : %s \n", act->id);
-	}
-
-	/* Print mailto: recipients */
-
-	sieve_result_printf(rpenv, "    => recipients    :\n");
-
-	recipients = array_get(&act->recipients, &count);
-	if (count == 0) {
-		sieve_result_printf(
-			rpenv, "       NONE, action has no effect\n");
-	} else {
-		for (i = 0; i < count; i++) {
-			sieve_result_printf(
-				rpenv, "       + To: %s\n", recipients[i].full);
-		}
-	}
-
-	/* Finish output with an empty line */
-
-	sieve_result_printf(rpenv, "\n");
-}
-
-/* Result execution */
-
-static bool contains_8bit(const char *msg)
-{
-	const unsigned char *s = (const unsigned char *)msg;
-
-	for (; *s != '\0'; s++) {
-		if ((*s & 0x80) != 0)
-			return TRUE;
-	}
-	return FALSE;
-}
-
-static bool
-act_notify_send(const struct sieve_action_exec_env *aenv,
-		const struct ext_notify_action *act)
-{
-	const struct sieve_execute_env *eenv = aenv->exec_env;
-	const struct sieve_script_env *senv = eenv->scriptenv;
-	const struct ext_notify_recipient *recipients;
-	struct sieve_smtp_context *sctx;
-	unsigned int count, i;
-	struct ostream *output;
-	string_t *msg, *to, *all;
-	const char *outmsgid, *error;
-	int ret;
-
-	/* Get recipients */
-	recipients = array_get(&act->recipients, &count);
-	if (count == 0) {
-		sieve_result_warning(
-			aenv, "notify action specifies no recipients; "
-			"action has no effect");
-		return TRUE;
-	}
-
-	/* Just to be sure */
-	if (!sieve_smtp_available(senv)) {
-		sieve_result_global_warning(
-			aenv, "notify action has no means to send mail");
-		return TRUE;
-	}
-
-	/* Compose common headers */
-	msg = t_str_new(512);
-	rfc2822_header_write(msg, "X-Sieve", SIEVE_IMPLEMENTATION);
-	rfc2822_header_write(msg, "Date", message_date_create(ioloop_time));
-
-	/* Set importance */
-	switch (act->importance) {
-	case 1:
-		rfc2822_header_write(msg, "X-Priority", "1 (Highest)");
-		rfc2822_header_write(msg, "Importance", "High");
-		break;
-	case 3:
-		rfc2822_header_write(msg, "X-Priority", "5 (Lowest)");
-		rfc2822_header_write(msg, "Importance", "Low");
-		break;
-	case 2:
-	default:
-		rfc2822_header_write(msg, "X-Priority", "3 (Normal)");
-		rfc2822_header_write(msg, "Importance", "Normal");
-		break;
-	}
-
-	rfc2822_header_write(msg, "From", sieve_get_postmaster_address(senv));
-
-	rfc2822_header_write(msg, "Subject", "[SIEVE] New mail notification");
-
-	rfc2822_header_write(msg, "Auto-Submitted", "auto-generated (notify)");
-	rfc2822_header_write(msg, "Precedence", "bulk");
-
-	rfc2822_header_write(msg, "MIME-Version", "1.0");
-	if (contains_8bit(act->message)) {
-		rfc2822_header_write(msg, "Content-Type",
-				     "text/plain; charset=utf-8");
-		rfc2822_header_write(msg, "Content-Transfer-Encoding", "8bit");
-	} else {
-		rfc2822_header_write(msg, "Content-Type",
-				     "text/plain; charset=us-ascii");
-		rfc2822_header_write(msg, "Content-Transfer-Encoding", "7bit");
-	}
-
-	outmsgid = sieve_message_get_new_id(eenv->svinst);
-	rfc2822_header_write(msg, "Message-ID", outmsgid);
-
-	if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0 &&
-	    sieve_message_get_sender(aenv->msgctx) != NULL) {
-		sctx = sieve_smtp_start(senv, sieve_get_postmaster_smtp(senv));
-	} else {
-		sctx = sieve_smtp_start(senv, NULL);
-	}
-
-	/* Add all recipients (and compose To header field) */
-	to = t_str_new(128);
-	all = t_str_new(256);
-	for (i = 0; i < count; i++) {
-		sieve_smtp_add_rcpt(sctx, recipients[i].address);
-		if (i > 0)
-			str_append(to, ", ");
-		str_append(to, recipients[i].full);
-		if (i < 3) {
-			if (i > 0)
-				str_append(all, ", ");
-			str_append(all, smtp_address_encode_path(
-				recipients[i].address));
-		} else if (i == 3) {
-			str_printfa(all, ", ... (%u total)", count);
-		}
-	}
-
-	rfc2822_header_write_address(msg, "To", str_c(to));
-
-	/* Generate message body */
-	str_printfa(msg, "\r\n%s\r\n", act->message);
-
-	output = sieve_smtp_send(sctx);
-	o_stream_nsend(output, str_data(msg), str_len(msg));
-
-	if ((ret = sieve_smtp_finish(sctx, &error)) <= 0) {
-		if (ret < 0) {
-			sieve_result_global_error(
-				aenv, "failed to send mail notification to %s: "
-				"%s (temporary failure)", str_c(all),
-				str_sanitize(error, 512));
-		} else {
-			sieve_result_global_log_error(
-				aenv, "failed to send mail notification to %s: "
-				"%s (permanent failure)", str_c(all),
-				str_sanitize(error, 512));
-		}
-	} else {
-		struct event_passthrough *e =
-			sieve_action_create_finish_event(aenv)->
-			add_str("notify_target", str_c(all));
-
-		sieve_result_event_log(aenv, e->event(),
-				       "sent mail notification to %s",
-				       str_c(all));
-	}
-
-	return TRUE;
-}
-
-static int
-act_notify_commit(const struct sieve_action_exec_env *aenv,
-		  void *tr_context ATTR_UNUSED)
-{
-	const struct sieve_execute_env *eenv = aenv->exec_env;
-	struct mail *mail = eenv->msgdata->mail;
-	const struct ext_notify_action *act =
-		(const struct ext_notify_action *)aenv->action->context;
-	const char *const *hdsp;
-	bool result;
-	int ret;
-
-	/* Is the message an automatic reply ? */
-	if ((ret = mail_get_headers(mail, "auto-submitted", &hdsp)) < 0) {
-		return sieve_result_mail_error(
-			aenv, mail,
-			"failed to read `auto-submitted' header field");
-	}
-
-	/* Theoretically multiple headers could exist, so lets make sure */
-	if (ret > 0) {
-		while (*hdsp != NULL) {
-			if (strcasecmp(*hdsp, "no") != 0) {
-				const struct smtp_address *sender = NULL;
-				const char *from;
-
-				if ((eenv->flags & SIEVE_EXECUTE_FLAG_NO_ENVELOPE) == 0)
-					sender = sieve_message_get_sender(aenv->msgctx);
-				from = (sender == NULL ? "" :
-					t_strdup_printf(" from <%s>",
-							smtp_address_encode(sender)));
-
-				sieve_result_global_log(
-					aenv,
-					"not sending notification for auto-submitted message%s",
-					from);
-				return SIEVE_EXEC_OK;
-			}
-			hdsp++;
-		}
-	}
-
-	T_BEGIN {
-		result = act_notify_send(aenv, act);
-	} T_END;
-
-	if (!result)
-		return SIEVE_EXEC_FAILURE;
-	eenv->exec_status->significant_action_executed = TRUE;
-	return SIEVE_EXEC_OK;
-}
diff --git a/src/lib-sieve/plugins/notify/ext-notify-common.c b/src/lib-sieve/plugins/notify/ext-notify-common.c
deleted file mode 100644
index ad344bb0f..000000000
--- a/src/lib-sieve/plugins/notify/ext-notify-common.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
- */
-
-#include "lib.h"
-#include "str.h"
-#include "istream.h"
-#include "rfc822-parser.h"
-#include "message-parser.h"
-#include "message-decoder.h"
-#include "mail-storage.h"
-
-#include "sieve-common.h"
-#include "sieve-code.h"
-#include "sieve-message.h"
-#include "sieve-extensions.h"
-#include "sieve-commands.h"
-#include "sieve-actions.h"
-#include "sieve-validator.h"
-#include "sieve-generator.h"
-#include "sieve-interpreter.h"
-#include "sieve-dump.h"
-#include "sieve-result.h"
-
-#include "ext-notify-common.h"
-
-#include <ctype.h>
-
-/*
- * Importance argument
- */
-
-static bool
-tag_importance_validate(struct sieve_validator *valdtr,
-			struct sieve_ast_argument **arg,
-			struct sieve_command *cmd);
-
-static const struct sieve_argument_def importance_low_tag = {
-	.identifier = "low",
-	.validate = tag_importance_validate,
-};
-
-static const struct sieve_argument_def importance_normal_tag = {
-	.identifier = "normal",
-	.validate = tag_importance_validate,
-};
-
-static const struct sieve_argument_def importance_high_tag = {
-	.identifier = "high",
-	.validate = tag_importance_validate,
-};
-
-static bool
-tag_importance_validate(struct sieve_validator *valdtr ATTR_UNUSED,
-			struct sieve_ast_argument **arg,
-			struct sieve_command *cmd ATTR_UNUSED)
-{
-	struct sieve_ast_argument *tag = *arg;
-
-	if (sieve_argument_is(tag, importance_low_tag))
-		sieve_ast_argument_number_substitute(tag, 3);
-	else if (sieve_argument_is(tag, importance_normal_tag))
-		sieve_ast_argument_number_substitute(tag, 2);
-	else
-		sieve_ast_argument_number_substitute(tag, 1);
-
-	tag->argument = sieve_argument_create(tag->ast, &number_argument,
-					      tag->argument->ext,
-					      tag->argument->id_code);
-
-	/* Skip parameter */
-	*arg = sieve_ast_argument_next(*arg);
-
-	return TRUE;
-}
-
-void ext_notify_register_importance_tags(
-	struct sieve_validator *valdtr,
-	struct sieve_command_registration *cmd_reg,
-	const struct sieve_extension *ext, unsigned int id_code)
-{
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &importance_low_tag, id_code);
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &importance_normal_tag, id_code);
-	sieve_validator_register_tag(valdtr, cmd_reg, ext,
-				     &importance_high_tag, id_code);
-}
-
-/*
- * Body extraction
- */
-
-/* FIXME: overlaps somewhat with body extension */
-
-struct ext_notify_message_context {
-	pool_t pool;
-	buffer_t *body_text;
-};
-
-static struct ext_notify_message_context *
-ext_notify_get_message_context(const struct sieve_extension *this_ext,
-			       struct sieve_message_context *msgctx)
-{
-	struct ext_notify_message_context *ctx;
-
-	/* Get message context (contains cached message body information) */
-	ctx = (struct ext_notify_message_context *)
-		sieve_message_context_extension_get(msgctx, this_ext);
-
-	/* Create it if it does not exist already */
-	if (ctx == NULL) {
-		pool_t pool = sieve_message_context_pool(msgctx);
-		ctx = p_new(pool, struct ext_notify_message_context, 1);
-		ctx->pool = pool;
-		ctx->body_text = NULL;
-
-		/* Register context */
-		sieve_message_context_extension_set(msgctx, this_ext,
-						    (void *)ctx);
-	}
-
-	return ctx;
-}
-
-static bool _is_text_content(const struct message_header_line *hdr)
-{
-	struct rfc822_parser_context parser;
-	string_t *content_type;
-	const char *data;
-
-	/* Initialize parsing */
-	rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL);
-	(void)rfc822_skip_lwsp(&parser);
-
-	/* Parse content type */
-	content_type = t_str_new(64);
-	if (rfc822_parse_content_type(&parser, content_type) < 0)
-		return FALSE;
-
-	/* Content-type value must end here, otherwise it is invalid after all
-	 */
-	(void)rfc822_skip_lwsp(&parser);
-	if (parser.data != parser.end && *parser.data != ';')
-		return FALSE;
-
-	/* Success */
-	data = str_c(content_type);
-	if (str_begins_with(data, "text/"))
-		return TRUE;
-	return FALSE;
-}
-
-static int
-cmd_notify_extract_body_text(const struct sieve_runtime_env *renv,
-			     const char **body_text_r, size_t *body_size_r)
-{
-	const struct sieve_execute_env *eenv = renv->exec_env;
-	const struct sieve_extension *this_ext = renv->oprtn->ext;
-	struct ext_notify_message_context *mctx;
-	struct mail *mail = eenv->msgdata->mail;
-	struct message_parser_ctx *parser;
-	struct message_decoder_context *decoder;
-	struct message_part *parts;
-	struct message_block block, decoded;
-	struct istream *input;
-	bool is_text, save_body;
-	int ret = 1;
-
-	*body_text_r = NULL;
-	*body_size_r = 0;
-
-	/* Return cached result if available */
-	mctx = ext_notify_get_message_context(this_ext, renv->msgctx);
-	if (mctx->body_text != NULL) {
-		*body_text_r = (const char *)
-			buffer_get_data(mctx->body_text, body_size_r);
-		return SIEVE_EXEC_OK;
-	}
-
-	/* Create buffer */
-	mctx->body_text = buffer_create_dynamic(mctx->pool, 1024*64);
-
-	/* Get the message stream */
-	if (mail_get_stream(mail, NULL, NULL, &input) < 0) {
-		return sieve_runtime_mail_error(renv, mail, "notify action: "
-						"failed to read input message");
-	}
-
-	/* Initialize body decoder */
-	decoder = message_decoder_init(NULL, 0);
-
-	struct message_parser_settings mparser_set = {
-		.hdr_flags = 0,
-		.flags = 0,
-	};
-	parser = message_parser_init(mctx->pool, input, &mparser_set);
-	is_text = TRUE;
-	save_body = FALSE;
-	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) {
-		if (block.hdr != NULL || block.size == 0) {
-			/* Decode block */
-			(void)message_decoder_decode_next_block(decoder, &block,
-								&decoded);
-
-			/* Check for end of headers */
-			if (block.hdr == NULL) {
-				save_body = is_text;
-				continue;
-			}
-
-			/* We're interested of only Content-Type: header */
-			if (strcasecmp(block.hdr->name, "Content-Type") != 0)
-				continue;
-
-			/* Header can have folding whitespace. Acquire the full
-			   value before continuing */
-			if (block.hdr->continues) {
-				block.hdr->use_full_value = TRUE;
-				continue;
-			}
-
-			/* Is it a text part? */
-			T_BEGIN {
-				is_text = _is_text_content(block.hdr);
-			} T_END;
-
-			continue;
-		}
-
-		/* Read text body */
-		if (save_body) {
-			(void)message_decoder_decode_next_block(decoder, &block,
-								&decoded);
-			buffer_append(mctx->body_text, decoded.data,
-				      decoded.size);
-			is_text = TRUE;
-		}
-	}
-
-	/* Cleanup */
-	(void)message_parser_deinit(&parser, &parts);
-	message_decoder_deinit(&decoder);
-
-	if (ret < 0 && input->stream_errno != 0) {
-		sieve_runtime_critical(renv, NULL, "notify action: "
-				       "failed to read input message",
-				       "notify action: read(%s) failed: %s",
-				       i_stream_get_name(input),
-				       i_stream_get_error(input));
-		return SIEVE_EXEC_TEMP_FAILURE;
-	}
-
-	/* Return status */
-	*body_text_r = (const char *)buffer_get_data(mctx->body_text,
-						     body_size_r);
-	return SIEVE_EXEC_OK;
-}
-
-int ext_notify_construct_message(const struct sieve_runtime_env *renv,
-				 const char *msg_format,
-				 string_t *out_msg)
-{
-	const struct sieve_execute_env *eenv = renv->exec_env;
-	const struct sieve_message_data *msgdata = eenv->msgdata;
-	struct sieve_message_context *msgctx = renv->msgctx;
-	const struct smtp_address *return_path =
-		sieve_message_get_sender(msgctx);
-	const char *p;
-	int ret;
-
-	if (msg_format == NULL)
-		msg_format = "$from$: $subject$";
-
-	/* Scan message for substitutions */
-	p = msg_format;
-	while (*p != '\0') {
-		const char *header;
-
-		if (str_begins_icase(p, "$from$", &p)) {
-			/* Fetch sender from original message */
-			if ((ret = mail_get_first_header_utf8(
-				msgdata->mail, "from", &header)) < 0) {
-				return sieve_runtime_mail_error(
-					renv, msgdata->mail,
-					"failed to read header field `from'");
-			}
-			if (ret > 0)
-				str_append(out_msg, header);
-		} else if (str_begins_icase(p, "$env-from$", &p)) {
-			if (return_path != NULL)
-				smtp_address_write(out_msg, return_path);
-		} else if (str_begins_icase(p, "$subject$", &p)) {
-			/* Fetch sender from oriinal message */
-			if ((ret = mail_get_first_header_utf8(
-				msgdata->mail, "subject", &header)) < 0) {
-				return sieve_runtime_mail_error(
-					renv, msgdata->mail,
-					"failed to read header field `subject'");
-			}
-			if (ret > 0)
-				 str_append(out_msg, header);
-		} else if (str_begins_icase(p, "$text", &p) &&
-			   (*p == '[' || *p == '$')) {
-			size_t num = 0;
-			const char *begin = p;
-			bool valid = TRUE;
-
-			if (*p == '[') {
-				p += 1;
-
-				while (i_isdigit(*p)) {
-					num = num * 10 + (*p - '0');
-					p++;
-				}
-
-				if (*p++ != ']' || *p++ != '$') {
-					str_append_data(out_msg, begin,
-							p-begin);
-					valid = FALSE;
-				}
-			} else {
-				p += 1;
-			}
-
-			if (valid) {
-				size_t body_size;
-				const char *body_text;
-
-				if ((ret = cmd_notify_extract_body_text(
-					renv, &body_text, &body_size)) <= 0)
-					return ret;
-
-				if (num > 0 && num < body_size) {
-					str_append_data(out_msg, body_text,
-							num);
-				} else {
-					str_append_data(out_msg, body_text,
-							body_size);
-				}
-			}
-		} else {
-			size_t len;
-
-			/* Find next substitution */
-			len = strcspn(p + 1, "$") + 1;
-
-			/* Copy normal text */
-			str_append_data(out_msg, p, len);
-			p += len;
-		}
-	}
-
-	return SIEVE_EXEC_OK;
-}
diff --git a/src/lib-sieve/plugins/notify/ext-notify-common.h b/src/lib-sieve/plugins/notify/ext-notify-common.h
deleted file mode 100644
index 09db2cb2e..000000000
--- a/src/lib-sieve/plugins/notify/ext-notify-common.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef EXT_NOTIFY_COMMON_H
-#define EXT_NOTIFY_COMMON_H
-
-/*
- * Extension
- */
-
-extern const struct sieve_extension_def notify_extension;
-
-/*
- * Commands
- */
-
-extern const struct sieve_command_def cmd_notify_old;
-extern const struct sieve_command_def cmd_denotify;
-
-/*
- * Arguments
- */
-
-void ext_notify_register_importance_tags(
-	struct sieve_validator *valdtr,
-	struct sieve_command_registration *cmd_reg,
-	const struct sieve_extension *this_ext, unsigned int id_code);
-
-/*
- * Operations
- */
-
-extern const struct sieve_operation_def notify_old_operation;
-extern const struct sieve_operation_def denotify_operation;
-
-enum ext_notify_opcode {
-	EXT_NOTIFY_OPERATION_NOTIFY,
-	EXT_NOTIFY_OPERATION_DENOTIFY,
-};
-
-/*
- * Actions
- */
-
-extern const struct sieve_action_def act_notify_old;
-
-struct ext_notify_recipient {
-	const char *full;
-	const struct smtp_address *address;
-};
-
-ARRAY_DEFINE_TYPE(recipients, struct ext_notify_recipient);
-
-struct ext_notify_action {
-	const char *id;
-	const char *message;
-	sieve_number_t importance;
-
-	ARRAY_TYPE(recipients) recipients;
-};
-
-/*
- * Message construct
- */
-
-int ext_notify_construct_message(const struct sieve_runtime_env *renv,
-				 const char *msg_format, string_t *out_msg);
-
-#endif
diff --git a/src/lib-sieve/plugins/notify/ext-notify-limits.h b/src/lib-sieve/plugins/notify/ext-notify-limits.h
deleted file mode 100644
index 5fab7cb47..000000000
--- a/src/lib-sieve/plugins/notify/ext-notify-limits.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef EXT_NOTIFY_LIMITS_H
-#define EXT_NOTIFY_LIMITS_H
-
-#define EXT_NOTIFY_MAX_RECIPIENTS  8
-#define EXT_NOTIFY_MAX_MESSAGE     256
-
-#endif
diff --git a/src/lib-sieve/plugins/notify/ext-notify.c b/src/lib-sieve/plugins/notify/ext-notify.c
deleted file mode 100644
index e79e04975..000000000
--- a/src/lib-sieve/plugins/notify/ext-notify.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file
- */
-
-/* Extension notify
- * ----------------
- *
- * Authors: Stephan Bosch
- * Specification: draft-ietf-sieve-notify-00.txt
- * Implementation: full, but deprecated; provided for backwards compatibility
- * Status: testing
- *
- */
-
-#include "sieve-common.h"
-
-#include "sieve-code.h"
-#include "sieve-extensions.h"
-#include "sieve-actions.h"
-#include "sieve-commands.h"
-#include "sieve-validator.h"
-#include "sieve-generator.h"
-#include "sieve-interpreter.h"
-#include "sieve-result.h"
-
-#include "ext-notify-common.h"
-
-/*
- * Operations
- */
-
-const struct sieve_operation_def *ext_notify_operations[] = {
-	&notify_old_operation,
-	&denotify_operation
-};
-
-/*
- * Extension
- */
-
-static bool ext_notify_validator_load
-	(const struct sieve_extension *ext, struct sieve_validator *valdtr);
-
-const struct sieve_extension_def notify_extension = {
-	.name = "notify",
-	.validator_load = ext_notify_validator_load,
-	SIEVE_EXT_DEFINE_OPERATIONS(ext_notify_operations)
-};
-
-/*
- * Extension validation
- */
-
-static bool ext_notify_validator_check_conflict
-	(const struct sieve_extension *ext,
-		struct sieve_validator *valdtr, void *context,
-		struct sieve_ast_argument *require_arg,
-		const struct sieve_extension *ext_other,
-		bool required);
-static bool ext_notify_validator_validate
-	(const struct sieve_extension *ext,
-		struct sieve_validator *valdtr, void *context,
-		struct sieve_ast_argument *require_arg,
-		bool required);
-
-const struct sieve_validator_extension notify_validator_extension = {
-	.ext = &notify_extension,
-	.check_conflict = ext_notify_validator_check_conflict,
-	.validate = ext_notify_validator_validate	
-};
-
-static bool ext_notify_validator_load
-(const struct sieve_extension *ext, struct sieve_validator *valdtr)
-{
-	/* Register validator extension to check for conflict with enotify */
-	sieve_validator_extension_register
-		(valdtr, ext, &notify_validator_extension, NULL);
-	return TRUE;
-}
-
-static bool ext_notify_validator_check_conflict
-(const struct sieve_extension *ext ATTR_UNUSED,
-	struct sieve_validator *valdtr, void *context ATTR_UNUSED,
-	struct sieve_ast_argument *require_arg,
-	const struct sieve_extension *ext_other,
-	bool required ATTR_UNUSED)
-{
-	/* Check for conflict with enotify */
-	if ( sieve_extension_name_is(ext_other, "enotify") ) {
-		sieve_argument_validate_error(valdtr, require_arg,
-			"the (deprecated) notify extension cannot be used "
-			"together with the enotify extension");
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-static bool ext_notify_validator_validate
-(const struct sieve_extension *ext,
-	struct sieve_validator *valdtr, void *context ATTR_UNUSED,
-	struct sieve_ast_argument *require_arg ATTR_UNUSED,
-	bool required ATTR_UNUSED)
-{
-	/* No conflicts: register new commands */
-	sieve_validator_register_command(valdtr, ext, &cmd_notify_old);
-	sieve_validator_register_command(valdtr, ext, &cmd_denotify);
-	return TRUE;
-}
diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index a1cb81056..f794a25da 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -165,12 +165,10 @@ const unsigned int sieve_extra_extensions_count =
  */
 
 extern const struct sieve_extension_def imapflags_extension;
-extern const struct sieve_extension_def notify_extension;
 extern const struct sieve_extension_def vnd_duplicate_extension;
 
 const struct sieve_extension_def *sieve_deprecated_extensions[] = {
 	&imapflags_extension,
-	&notify_extension,
 	&vnd_duplicate_extension
 };
 
diff --git a/tests/deprecated/notify/basic.svtest b/tests/deprecated/notify/basic.svtest
deleted file mode 100644
index 974f8ca5b..000000000
--- a/tests/deprecated/notify/basic.svtest
+++ /dev/null
@@ -1,59 +0,0 @@
-require "vnd.dovecot.testsuite";
-require "notify";
-require "body";
-
-test "Execute" {
-	/* Test to catch runtime segfaults */
-	notify
-		:message "This is probably very important"
-		:low
-		:method "mailto"
-		:options ["stephan@example.com", "stephan@example.org"];
-
-	if not test_result_execute {
-		test_fail "Execute failed";
-	}
-}
-
-test_result_reset;
-
-test_set "message" text:
-To: user@example.com
-From: stephan@example.org
-Subject: Mail
-
-Test!
-.
-;
-
-test "Substitutions" {
-	notify
-		:message "$from$: $subject$"
-		:options "stephan@example.com";
-	if not test_result_execute {
-		test_fail "Execute failed";
-	}
-	test_message :smtp 0;
-	if not body :contains "stephan@example.org: Mail" {
-		test_fail "Substitution failed";
-	}
-}
-
-test_result_reset;
-
-test_set "message" text:
-To: user@example.com
-
-Test!
-.
-;
-
-test "Empty substitutions" {
-	notify
-		:message "$from$: $subject$"
-		:options "stephan@example.com";
-	if not test_result_execute {
-		test_fail "Execute failed";
-	}
-}
-
diff --git a/tests/deprecated/notify/denotify.svtest b/tests/deprecated/notify/denotify.svtest
deleted file mode 100644
index 9f752e127..000000000
--- a/tests/deprecated/notify/denotify.svtest
+++ /dev/null
@@ -1,279 +0,0 @@
-require "vnd.dovecot.testsuite";
-require "notify";
-require "envelope";
-
-/*
- * Denotify all
- */
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Denotify All" {
-	notify :options "timo@example.com";
-	notify :options "stephan@dovecot.example.net";
-	notify :options "postmaster@frop.example.org";
-	denotify;
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if test_message :smtp 0 {
-		test_fail "no notifications should have been sent";
-	}
-}
-
-/*
- * Denotify First
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Denotify ID First" {
-	/* #1 */
-	notify :options "timo@example.com" :id "aap";
-
-	/* #2 */
-	notify :options "stephan@dovecot.example.net" :id "noot";
-
-	/* #3 */
-	notify :options "postmaster@frop.example.org" :id "mies";
-
-	denotify :is "aap";
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if not test_message :smtp 0 {
-		test_fail "two notifications should have been sent (#2 missing)";
-	}
-
-	if not envelope "to" "stephan@dovecot.example.net" {
-		test_fail "message #2 unexpectedly missing from output";
-	}
-
-	if not test_message :smtp 1 {
-		test_fail "two notifications should have been sent (#3 missing)";
-	}
-
-	if not envelope "to" "postmaster@frop.example.org" {
-		test_fail "message #3 unexpectedly missing from output";
-	}
-
-	if test_message :smtp 2 {
-		test_fail "too many notifications sent";
-	}
-}
-
-/*
- * Denotify Middle
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Denotify ID Middle" {
-	/* #1 */
-	notify :options "timo@example.com" :id "aap";
-
-	/* #2 */
-	notify :options "stephan@dovecot.example.net" :id "noot";
-
-	/* #3 */
-	notify :options "postmaster@frop.example.org" :id "mies";
-
-	denotify :is "noot";
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if not test_message :smtp 0 {
-		test_fail "two notifications should have been sent (#1 missing)";
-	}
-
-	if not envelope "to" "timo@example.com" {
-		test_fail "message #1 unexpectedly missing from output";
-	}
-
-	if not test_message :smtp 1 {
-		test_fail "two notifications should have been sent (#3 missing)";
-	}
-
-	if not envelope "to" "postmaster@frop.example.org" {
-		test_fail "message #3 unexpectedly missing from output";
-	}
-
-	if test_message :smtp 2 {
-		test_fail "too many notifications sent";
-	}
-}
-
-/*
- * Denotify Last
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Denotify ID Last" {
-	/* #1 */
-	notify :options "timo@example.com" :id "aap";
-
-	/* #2 */
-	notify :options "stephan@dovecot.example.net" :id "noot";
-
-	/* #3 */
-	notify :options "postmaster@frop.example.org" :id "mies";
-
-	denotify :is "mies";
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if not test_message :smtp 0 {
-		test_fail "two notifications should have been sent (#1 missing)";
-	}
-
-	if not envelope "to" "timo@example.com" {
-		test_fail "message #1 unexpectedly missing from output";
-	}
-
-	if not test_message :smtp 1 {
-		test_fail "two notifications should have been sent (#2 missing)";
-	}
-
-	if not envelope "to" "stephan@dovecot.example.net" {
-		test_fail "message #2 unexpectedly missing from output";
-	}
-
-	if test_message :smtp 2 {
-		test_fail "too many notifications sent";
-	}
-}
-
-
-/*
- * Denotify Matching
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Denotify Matching" {
-	/* #1 */
-	notify :options "timo@example.com" :id "frop";
-
-	/* #2 */
-	notify :options "stephan@dovecot.example.net" :id "noot";
-
-	/* #3 */
-	notify :options "postmaster@frop.example.org" :id "friep";
-
-	denotify :matches "fr*";
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if not test_message :smtp 0 {
-		test_fail "one notification should have been sent";
-	}
-
-	if not envelope "to" "stephan@dovecot.example.net" {
-		test_fail "message #2 unexpectedly missing from output";
-	}
-
-	if test_message :smtp 1 {
-		test_fail "too many notifications sent";
-	}
-}
-
-
-/*
- * Denotify Matching
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Denotify Matching Importance" {
-	/* #1 */
-	notify :options "timo@example.com" :id "frop" :low;
-
-	/* #2 */
-	notify :options "stephan@dovecot.example.net" :id "frml" :high;
-
-	/* #3 */
-	notify :options "postmaster@frop.example.org" :id "friep" :low;
-
-	denotify :matches "fr*" :low;
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if not test_message :smtp 0 {
-		test_fail "one notification should have been sent";
-	}
-
-	if not envelope "to" "stephan@dovecot.example.net" {
-		test_fail "message #2 unexpectedly missing from output";
-	}
-
-	if test_message :smtp 1 {
-		test_fail "too many notifications sent";
-	}
-}
-
-
diff --git a/tests/deprecated/notify/errors.svtest b/tests/deprecated/notify/errors.svtest
deleted file mode 100644
index 549cb6b87..000000000
--- a/tests/deprecated/notify/errors.svtest
+++ /dev/null
@@ -1,33 +0,0 @@
-require "vnd.dovecot.testsuite";
-require "comparator-i;ascii-numeric";
-require "relational";
-
-test "Invalid :options argument (FIXME: count only)" {
-	if test_script_compile "errors/options.sieve" {
-		test_fail "compile should have failed";
-	}
-
-	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-		test_fail "wrong number of errors reported";
-	}
-}
-
-test "Deprecated notify extension used with enotify" {
-	if test_script_compile "errors/conflict.sieve" {
-		test_fail "compile should have failed";
-	}
-
-	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-		test_fail "wrong number of errors reported";
-	}
-}
-
-test "Deprecated notify extension used with enotify (ihave)" {
-	if test_script_compile "errors/conflict-ihave.sieve" {
-		test_fail "compile should have failed";
-	}
-
-	if not test_error :count "eq" :comparator "i;ascii-numeric" "3" {
-		test_fail "wrong number of errors reported";
-	}
-}
diff --git a/tests/deprecated/notify/errors/conflict-ihave.sieve b/tests/deprecated/notify/errors/conflict-ihave.sieve
deleted file mode 100644
index 9686f033c..000000000
--- a/tests/deprecated/notify/errors/conflict-ihave.sieve
+++ /dev/null
@@ -1,8 +0,0 @@
-require "enotify";
-require "ihave";
-
-# 1: Conflict
-if ihave "notify" {
-	# 2: Syntax wrong for enotify (and not skipped in compile)
-	notify :options "frop@frop.example.org";
-}
diff --git a/tests/deprecated/notify/errors/conflict.sieve b/tests/deprecated/notify/errors/conflict.sieve
deleted file mode 100644
index 46a62835f..000000000
--- a/tests/deprecated/notify/errors/conflict.sieve
+++ /dev/null
@@ -1,4 +0,0 @@
-require "enotify";
-require "notify";
-
-notify :options "frop@frop.example.org";
diff --git a/tests/deprecated/notify/errors/options.sieve b/tests/deprecated/notify/errors/options.sieve
deleted file mode 100644
index c86fea071..000000000
--- a/tests/deprecated/notify/errors/options.sieve
+++ /dev/null
@@ -1,11 +0,0 @@
-require "notify";
-
-# 1: empty option
-notify :options "";
-
-# 2: invalid address syntax
-notify :options "frop#frop.example.org";
-
-# Valid
-notify :options "frop@frop.example.org";
-
diff --git a/tests/deprecated/notify/execute.svtest b/tests/deprecated/notify/execute.svtest
deleted file mode 100644
index 90fde474e..000000000
--- a/tests/deprecated/notify/execute.svtest
+++ /dev/null
@@ -1,25 +0,0 @@
-require "vnd.dovecot.testsuite";
-require "relational";
-
-
-/*
- * Execution testing (currently just meant to trigger any segfaults)
- */
-
-test "Duplicate recipients" {
-	if not test_script_compile "execute/duplicates.sieve" {
-		test_fail "script compile failed";
-	}
-
-	if not test_script_run {
-		test_fail "script execute failed";
-	}
-
-	if test_result_action :count "ne" "2" {
-		test_fail "second notify action was discarded entirely";
-	}
-
-	if not test_result_execute {
-		test_fail "result execute failed";
-	}
-}
diff --git a/tests/deprecated/notify/execute/duplicates.sieve b/tests/deprecated/notify/execute/duplicates.sieve
deleted file mode 100644
index ef3fa5fd0..000000000
--- a/tests/deprecated/notify/execute/duplicates.sieve
+++ /dev/null
@@ -1,4 +0,0 @@
-require "notify";
-
-notify :message "Incoming stupidity." :options ["stephan@example.org", "stephan@friep.example.com", "idiot@example.org"];
-notify :message "There it is." :options ["tss@example.net", "stephan@example.org", "idiot@example.org", "nico@frop.example.org", "stephan@friep.example.com"];
diff --git a/tests/deprecated/notify/mailto.svtest b/tests/deprecated/notify/mailto.svtest
deleted file mode 100644
index 172433984..000000000
--- a/tests/deprecated/notify/mailto.svtest
+++ /dev/null
@@ -1,317 +0,0 @@
-require "vnd.dovecot.testsuite";
-
-require "notify";
-require "body";
-require "relational";
-require "comparator-i;ascii-numeric";
-
-/*
- * Simple test
- */
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Simple" {
-	notify :method "mailto" :options "stephan@example.org";
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	test_message :smtp 0;
-
-	if not header :matches "Auto-Submitted" "auto-generated*" {
-		test_fail "auto-submitted header set inappropriately";
-	}
-
-	if not exists "X-Sieve" {
-		test_fail "x-sieve header missing from outgoing message";
-	}
-}
-
-/*
- * Multiple recipients
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Multiple recipients" {
-	notify :options ["timo@example.com","stephan@dovecot.example.net","postmaster@frop.example.org"];
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	test_message :smtp 0;
-
-	if not address :is "to" "timo@example.com" {
-		test_fail "first To address missing";
-	}
-
-	test_message :smtp 1;
-
-	if not address :is "to" "stephan@dovecot.example.net" {
-		test_fail "second To address missing";
-	}
-
-	if not header :matches "Auto-Submitted" "auto-generated*" {
-		test_fail "auto-submitted header not found for second message";
-	}
-
-	test_message :smtp 2;
-
-	if not address :is "to" "postmaster@frop.example.org" {
-		test_fail "third To address missing";
-	}
-
-	if not header :matches "Auto-Submitted" "auto-generated*" {
-		test_fail "auto-submitted header not found for third message";
-	}
-
-	if not address :count "eq" :comparator "i;ascii-numeric" "to" "3" {
-		test_fail "wrong number of recipients in To header";
-	}
-
-	if not address :count "eq" :comparator "i;ascii-numeric" "cc" "0" {
-		test_fail "too many recipients in Cc header";
-	}
-}
-
-/*
- * Duplicate recipients
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Duplicate recipients" {
-	notify :options ["timo@example.com", "stephan@dovecot.example.net", "stephan@dovecot.example.net"];
-	notify :options ["timo@example.com", "stephan@example.org"];
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	test_message :smtp 2;
-
-	if address "To" "stephan@dovecot.example.net" {
-		test_fail "duplicate recipient not removed from first message";
-	}
-
-	if address "To" "timo@example.com" {
-		test_fail "duplicate recipient not removed from second message";
-	}
-}
-
-/*
- * Notifying on automated messages
- */
-
-test_result_reset;
-
-test_set "message" text:
-From: stephan@example.org
-To: nico@frop.example.org
-Auto-submitted: auto-notify
-Subject: Frop!
-
-Klutsefluts.
-.
-;
-
-test "Notifying on automated messages" {
-	notify :options "stephan@example.org";
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	if test_message :smtp 0 {
-		test_fail "notified of auto-submitted message";
-	}
-}
-
-test_result_reset;
-
-test_set "message" text:
-To: nico@frop.example.org
-From: stephan@example.org
-Subject: Test
-
-Test. Test
-Frop!
-.
-;
-
-test "Body; Singular Message" {
-	notify :low :id "frop" :options "stephan@example.org"
-    	:message text:
-Received interesting message:
-
-$text$
-
-You have been notified.
-.
-;
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	test_message :smtp 0;
-
-	if not body :raw :contains "Received interesting message" {
-		test_fail "notification has no heading";
-	}
-
-	if not body :raw :contains "You have been notified" {
-		test_fail "notification has no footer";
-	}
-
-	if not allof(
-		body :raw :contains "Test. Test",
-		body :raw :contains "Frop" ) {
-		test_fail "notification has no original message";
-	}
-}
-
-test_result_reset;
-
-test_set "message" text:
-To: nico@frop.example.org
-From: stephan@example.org
-Subject: Test
-
-Test. Test
-Frop!
-.
-;
-
-test "Body; $text[maxsize]$" {
-	notify :low :id "frop" :options "sirius@example.org"
-    	:message text:
-Received interesting message:
-
-$text[5]$
-
-You have been notified.
-.
-;
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	test_message :smtp 0;
-
-	if not body :raw :contains "Received interesting message" {
-		test_fail "notification has no heading";
-	}
-
-	if not body :raw :contains "You have been notified" {
-		test_fail "notification has no footer";
-	}
-
-	if anyof(
-		body :raw :contains "Test. Test",
-		body :raw :contains "Frop" ) {
-		test_fail "original message in notification is not truncated";
-	}
-
-	if not body :raw :contains "Test." {
-		test_fail "notification does not contain the required message";
-	}
-}
-
-test_result_reset;
-
-test_set "message" text:
-From: Whomever <whoever@example.com>
-To: Someone <someone@example.com>
-Date: Sat, 10 Oct 2009 00:30:04 +0200
-Subject: whatever
-Content-Type: multipart/mixed; boundary=outer
-
-This is a multi-part message in MIME format.
-
---outer
-Content-Type: multipart/alternative; boundary=inner
-
-This is a nested multi-part message in MIME format.
-
---inner
-Content-Type: application/sieve; charset="us-ascii"
-
-keep;
-
---inner
-Content-Type: text/plain; charset="us-ascii"
-
-Friep!
-
---inner--
-
-This is the end of the inner MIME multipart.
-
---outer
-Content-Type: message/rfc822
-
-From: Someone Else
-Subject: hello request
-
-Please say Hello
-
---outer--
-
-This is the end of the outer MIME multipart.
-.
-;
-
-test "Body; Multipart Message" {
-	notify :low :id "frop" :options "stephan@example.org"
-    	:message text:
-Received interesting message:
-
-$text$
-
-You have been notified.
-.
-;
-
-	if not test_result_execute {
-		test_fail "failed to execute notify";
-	}
-
-	test_message :smtp 0;
-
-	if not body :raw :contains "Friep!" {
-		test_fail "notification has incorrect content";
-	}
-}
-
-
-
-- 
GitLab