diff --git a/TODO b/TODO
index 5d738f5b09caabf82106f861da42b0742637f1e1..894a41f94d8470c8b9f5148909c7b1f9b2ca10ac 100644
--- a/TODO
+++ b/TODO
@@ -2,8 +2,9 @@ Current:
 
 * Finish enotify extension:
 	- Mailto: prevent multiple notifications to a single recipient
+	- Cleanup method API.
 	- Regorous testing
-* Test new multiscript support
+* Test new multiscript support extensively. 
 
 Next (in order of descending priority/precedence):
 
diff --git a/src/lib-sieve/plugins/enotify/cmd-notify.c b/src/lib-sieve/plugins/enotify/cmd-notify.c
index 9d4112a6c037b48ce57e82f2c7e587cc136e05fd..e2929a9e33785dbbb15caa5732848c2853b53729 100644
--- a/src/lib-sieve/plugins/enotify/cmd-notify.c
+++ b/src/lib-sieve/plugins/enotify/cmd-notify.c
@@ -532,8 +532,24 @@ static int act_notify_check_duplicate
 	const struct sieve_action_data *act ATTR_UNUSED,
 	const struct sieve_action_data *act_other ATTR_UNUSED)
 {
-	/* No problems yet */
-	return 0;
+	const struct sieve_enotify_action *nact1, *nact2;
+	struct sieve_enotify_log nlog;
+		
+	if ( act->context == NULL || act_other->context == NULL )
+		return 0;
+
+	nact1 = (const struct sieve_enotify_action *) act->context;
+	nact2 = (const struct sieve_enotify_action *) act_other->context;
+
+	if ( nact1->method == NULL || nact1->method->action_check_duplicates == NULL )
+		return 0;
+
+	memset(&nlog, 0, sizeof(nlog));
+	nlog.location = act->location;
+	nlog.ehandler = sieve_result_get_error_handler(renv->result);
+
+	return nact1->method->action_check_duplicates
+		(&nlog, nact1->method_context, nact2->method_context, act_other->location);
 }
 
 /* Result printing */
diff --git a/src/lib-sieve/plugins/enotify/ntfy-mailto.c b/src/lib-sieve/plugins/enotify/ntfy-mailto.c
index 99d54ea4b38abbbff9cb5836fe5fd1ec1c9950ae..e087018038fab58d31c7f1396aabb50943e48ec5 100644
--- a/src/lib-sieve/plugins/enotify/ntfy-mailto.c
+++ b/src/lib-sieve/plugins/enotify/ntfy-mailto.c
@@ -32,7 +32,7 @@
 #include "sieve-address.h"
 #include "sieve-message.h"
 
-/* To be removed */
+/* FIXME: notify API: methods should not need to include sieve-result.h */
 #include "sieve-result.h"
 
 /*
@@ -69,6 +69,7 @@ static bool ntfy_mailto_compile_check_uri
 	(const struct sieve_enotify_log *nlog, const char *uri, const char *uri_body);
 static bool ntfy_mailto_compile_check_from
 	(const struct sieve_enotify_log *nlog, string_t *from);
+
 static const char *ntfy_mailto_runtime_get_notify_capability
 	(const struct sieve_enotify_log *nlog, const char *uri, const char *uri_body, 
 		const char *capability);
@@ -78,9 +79,15 @@ static bool ntfy_mailto_runtime_check_operands
 	(const struct sieve_enotify_log *nlog, const char *uri,const char *uri_body, 
 		string_t *message, string_t *from, pool_t context_pool, 
 		void **method_context);
+
+static int ntfy_mailto_action_check_duplicates
+	(const struct sieve_enotify_log *nlog, void *method_ctx1, void *method_ctx2,
+		const char *dupl_location);
+
 static void ntfy_mailto_action_print
 	(const struct sieve_result_print_env *rpenv, 
 		const struct sieve_enotify_action *act);	
+
 static bool ntfy_mailto_action_execute
 	(const struct sieve_enotify_exec_env *nenv, 
 		const struct sieve_enotify_action *act);
@@ -95,6 +102,7 @@ const struct sieve_enotify_method mailto_notify = {
 	ntfy_mailto_runtime_get_notify_capability,
 	ntfy_mailto_runtime_check_operands,
 	NULL,
+	ntfy_mailto_action_check_duplicates,
 	ntfy_mailto_action_print,
 	ntfy_mailto_action_execute
 };
@@ -745,6 +753,19 @@ static bool ntfy_mailto_runtime_check_operands
 	return TRUE;	
 }
 
+/*
+ * Action duplicates
+ */
+
+static int ntfy_mailto_action_check_duplicates
+(const struct sieve_enotify_log *nlog, void *method_ctx1, void *method_ctx2,
+	const char *dupl_location)
+{
+	/* FIXME: kill duplicate recipients */
+
+	return 0;
+}
+
 /*
  * Action printing
  */
diff --git a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
index 77b333c5b56a808621cda9d19b61caf2477ea7b4..2e4fa36c4af7cfe4f5b1150ff7ec9f0aad5985d7 100644
--- a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
+++ b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
@@ -68,6 +68,11 @@ struct sieve_enotify_method {
 	bool (*runtime_set_option)
 		(const struct sieve_enotify_log *nlog, void *method_context,
 			const char *option, const char *value);
+
+	/* Action duplicates */
+	int (*action_check_duplicates)
+		(const struct sieve_enotify_log *nlog, void *method_ctx1, 
+			void *method_ctx2, const char *dupl_location);
 		
 	/* Action print */
 	void (*action_print)
diff --git a/tests/extensions/enotify/execute.svtest b/tests/extensions/enotify/execute.svtest
index ef22672ea5bdf6a384db67493ad3b7a32ec1308c..c044e8d0168e5b2449483e3175a301eb7f7a75c0 100644
--- a/tests/extensions/enotify/execute.svtest
+++ b/tests/extensions/enotify/execute.svtest
@@ -77,3 +77,17 @@ test "RFC Example 6" {
 		test_fail "result execute failed";
 	}
 }
+
+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 not test_result_execute {
+		test_fail "result execute failed";
+	}
+}
diff --git a/tests/extensions/enotify/execute/duplicates.sieve b/tests/extensions/enotify/execute/duplicates.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..c16796d08d134cb28f5df5767be0f00d3d58c2c4
--- /dev/null
+++ b/tests/extensions/enotify/execute/duplicates.sieve
@@ -0,0 +1,4 @@
+require "enotify";
+
+notify :message "Incoming stupidity." "mailto:stephan@rename-it.nl";
+notify :message "There it is." "mailto:tss@iki.fi,stephan@rename-it.nl";