diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.c b/src/lib-sieve/plugins/enotify/ext-enotify-common.c
index 5e34d842d68c1cc2e5017e26968b03461398e31d..5227f620e5ad134fff37521cbca034805f8bca7c 100644
--- a/src/lib-sieve/plugins/enotify/ext-enotify-common.c
+++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.c
@@ -66,9 +66,11 @@ static const struct sieve_enotify_method *ext_enotify_method_register
 	const struct sieve_enotify_method_def *nmth_def) 
 {
 	struct sieve_enotify_method *nmth;
+	int nmth_id = (int) array_count(&ectx->notify_methods);
 
 	nmth = array_append_space(&ectx->notify_methods);
 	nmth->def = nmth_def;
+	nmth->id = nmth_id;
 	nmth->svinst = svinst;
 
 	if ( nmth_def->load != NULL )
@@ -116,6 +118,27 @@ const struct sieve_enotify_method *sieve_enotify_method_register
 	return NULL;
 }
 
+void sieve_enotify_method_unregister
+(const struct sieve_enotify_method *nmth)
+{
+	struct sieve_instance *svinst = nmth->svinst;
+	const struct sieve_extension *ntfy_ext =
+		sieve_extension_get_by_name(svinst, "enotify");
+
+	if ( ntfy_ext != NULL ) {
+		struct ext_enotify_context *ectx = 
+			(struct ext_enotify_context *) ntfy_ext->context;
+		int nmth_id = nmth->id;
+
+		if ( nmth_id >= 0 && nmth_id < (int)array_count(&ectx->notify_methods) ) {
+			struct sieve_enotify_method *nmth_mod =
+				array_idx_modifiable(&ectx->notify_methods, nmth_id);
+			
+			nmth_mod->def = NULL;
+		}
+	}
+}
+
 const struct sieve_enotify_method *ext_enotify_method_find
 (const struct sieve_extension *ntfy_ext, const char *identifier) 
 {
@@ -147,13 +170,14 @@ static const char *ext_notify_get_methods_string
 	string_t *result = t_str_new(128);
 	 
 	methods = array_get(&ectx->notify_methods, &meth_count);
-		
+	
 	if ( meth_count > 0 ) {
-		str_append(result, methods[0].def->identifier);
-		
-		for ( i = 1; i < meth_count; i++ ) {
-			str_append_c(result, ' ');
-			str_append(result, methods[i].def->identifier);
+		for ( i = 0; i < meth_count; i++ ) {
+			if ( str_len(result) > 0 )
+				str_append_c(result, ' ');
+
+			if ( methods[i].def != NULL )
+				str_append(result, methods[i].def->identifier);
 		}
 		
 		return str_c(result);
diff --git a/src/lib-sieve/plugins/enotify/ext-enotify.c b/src/lib-sieve/plugins/enotify/ext-enotify.c
index 3507d593952bd7eebe70b76c66f097e985c260b7..263e54204973c41cd0501f44aee128b3034cf708 100644
--- a/src/lib-sieve/plugins/enotify/ext-enotify.c
+++ b/src/lib-sieve/plugins/enotify/ext-enotify.c
@@ -71,7 +71,7 @@ static bool ext_enotify_load(const struct sieve_extension *ext, void **context)
 
 	ext_enotify_methods_init(ext->svinst, ectx);
 
-	sieve_extension_capabilities_register(ext->svinst, ext, &notify_capabilities);
+	sieve_extension_capabilities_register(ext, &notify_capabilities);
 
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
index 769faa332514e04995049595d99a5b0b5324ad63..e455d7e5b8975c83ff4b02dbab1b38fc5bb13b7c 100644
--- a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
+++ b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
@@ -84,6 +84,7 @@ struct sieve_enotify_method_def {
 
 struct sieve_enotify_method {
 	const struct sieve_enotify_method_def *def;
+	int id;
 
 	struct sieve_instance *svinst;
 	void *context;
@@ -91,7 +92,9 @@ struct sieve_enotify_method {
 
 const struct sieve_enotify_method *sieve_enotify_method_register
 	(struct sieve_instance *svinst, 
-		const struct sieve_enotify_method_def *nmth_def); 
+		const struct sieve_enotify_method_def *nmth_def);
+void  sieve_enotify_method_unregister
+	(const struct sieve_enotify_method *nmth);
 
 /*
  * Notify method environment
diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index fcc8add387da37ee7dcb5d3ca24ef4b233eb98f6..b858903e7793f2551779f8ccaa1298c283678e1b 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -238,6 +238,25 @@ const struct sieve_extension *const *sieve_extensions_get_preloaded
  * Extension registry
  */
 
+static bool _sieve_extension_load(struct sieve_extension *ext)
+{
+	/* Call load handler */
+	if ( ext->def != NULL && ext->def->load != NULL && 
+		!ext->def->load(ext, &ext->context) ) {
+		sieve_sys_error("failed to load '%s' extension support.", ext->def->name);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void _sieve_extension_unload(struct sieve_extension *ext)
+{
+    /* Call unload handler */
+    if ( ext->def != NULL && ext->def->unload != NULL )
+        ext->def->unload(ext);
+}
+
 static void sieve_extension_registry_init(struct sieve_instance *svinst)
 {	
 	struct sieve_extension_registry *ext_reg = svinst->ext_reg;
@@ -260,8 +279,7 @@ static void sieve_extension_registry_deinit(struct sieve_instance *svinst)
 	while ( hash_table_iterate(itx, &key, &value) ) {
 		struct sieve_extension *ext = (struct sieve_extension *) value;
 		
-		if ( ext->def != NULL && ext->def->unload != NULL )
-			ext->def->unload(ext);
+		_sieve_extension_unload(ext);
 	}
 
 	hash_table_iterate_deinit(&itx); 	
@@ -269,18 +287,6 @@ static void sieve_extension_registry_deinit(struct sieve_instance *svinst)
 	hash_table_destroy(&ext_reg->extension_index);
 }
 
-static bool _sieve_extension_load(struct sieve_extension *ext)
-{
-	/* Call load handler */
-	if ( ext->def != NULL && ext->def->load != NULL && 
-		!ext->def->load(ext, &ext->context) ) {
-		sieve_sys_error("failed to load '%s' extension support.", ext->def->name);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
 bool sieve_extension_reload(const struct sieve_extension *ext)
 {
 	struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg;
@@ -307,7 +313,7 @@ static struct sieve_extension *_sieve_extension_register
 
 	/* Register extension if it is not registered already */
 	if ( ext == NULL ) {
-		int ext_id = array_count(&ext_reg->extensions);
+		int ext_id = (int)array_count(&ext_reg->extensions);
 
 		/* Add extension to the registry */
 
@@ -318,6 +324,12 @@ static struct sieve_extension *_sieve_extension_register
 
 		hash_table_insert
 			(ext_reg->extension_index, (void *) extdef->name, (void *) ext);
+
+	/* Re-register it if it were previously unregistered 
+	 * (not going to happen) 
+	 */
+	} else if ( ext->def == NULL ) {
+		ext->def = extdef;
 	}
 
 	/* Enable extension */
@@ -345,10 +357,26 @@ const struct sieve_extension *sieve_extension_register
 	return _sieve_extension_register(svinst, extdef, load, FALSE);
 }
 
+void sieve_extension_unregister(const struct sieve_extension *ext)
+{
+    struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg;
+    struct sieve_extension *mod_ext;
+    int ext_id = ext->id;
+
+    if ( ext_id > 0 && ext_id < (int) array_count(&ext_reg->extensions) ) {
+        mod_ext = array_idx_modifiable(&ext_reg->extensions, ext_id);
+
+		sieve_extension_capabilities_unregister(ext);
+		_sieve_extension_unload(mod_ext);
+		mod_ext->loaded = FALSE;
+		mod_ext->def = NULL;
+    }
+}
+
 const struct sieve_extension *sieve_extension_require
 (struct sieve_instance *svinst, const struct sieve_extension_def *extdef)
 {
-  return _sieve_extension_register(svinst, extdef, TRUE, TRUE);
+	return _sieve_extension_register(svinst, extdef, TRUE, TRUE);
 }
 
 int sieve_extensions_get_count(struct sieve_instance *svinst)
@@ -367,7 +395,7 @@ const struct sieve_extension *sieve_extension_get_by_id
 	if ( ext_id < array_count(&ext_reg->extensions) ) {
 		ext = array_idx(&ext_reg->extensions, ext_id);
 
-		if ( ext->enabled )
+		if ( ext->def != NULL && ext->enabled )
 			return ext;
 	}
 	
@@ -386,7 +414,7 @@ const struct sieve_extension *sieve_extension_get_by_name
 	ext = (const struct sieve_extension *) 
 		hash_table_lookup(ext_reg->extension_index, name);
 
-	if ( ext == NULL || !ext->enabled )
+	if ( ext == NULL || ext->def == NULL || !ext->enabled )
 		return NULL;
 		
 	return ext;
@@ -406,7 +434,8 @@ const char *sieve_extensions_get_string(struct sieve_instance *svinst)
 		
 		/* Find first listable extension */
 		while ( i < ext_count && 
-			!( exts[i].enabled && *(exts[i].def->name) != '@' ) )
+			!( exts[i].enabled && exts[i].def != NULL &&
+			*(exts[i].def->name) != '@' ) )
 			i++;
 
 		if ( i < ext_count ) {
@@ -416,7 +445,8 @@ const char *sieve_extensions_get_string(struct sieve_instance *svinst)
 
 	 		/* Add others */
 			for ( ; i < ext_count; i++ ) {
-				if ( exts[i].enabled && *(exts[i].def->name) != '@' ) {
+				if ( exts[i].enabled && exts[i].def != NULL && 
+					*(exts[i].def->name) != '@' ) {
 					str_append_c(extstr, ' ');
 					str_append(extstr, exts[i].def->name);
 				}
@@ -493,7 +523,7 @@ void sieve_extensions_set_string
 					ext = (const struct sieve_extension *) 
 						hash_table_lookup(ext_reg->extension_index, name);
 	
-				if ( ext == NULL ) {
+				if ( ext == NULL || ext->def == NULL ) {
 					sieve_sys_warning(
 						"ignored unknown extension '%s' while configuring "
 						"available extensions", name);
@@ -550,7 +580,8 @@ void sieve_extensions_set_string
 
 			/* Perform actual activation/deactivation */
 
-			if ( exts[i].id >= 0 && *(exts[i].def->name) != '@' ) {
+			if ( exts[i].id >= 0 && exts[i].def != NULL && 
+				*(exts[i].def->name) != '@' ) {
 				if ( disabled && !exts[i].required )
 					sieve_extension_disable(&exts[i]);
 				else
@@ -605,9 +636,10 @@ void sieve_capability_registry_deinit(struct sieve_instance *svinst)
 }
 
 void sieve_extension_capabilities_register
-(struct sieve_instance *svinst, const struct sieve_extension *ext, 
+(const struct sieve_extension *ext, 
 	const struct sieve_extension_capabilities *cap) 
-{	
+{		
+	struct sieve_instance *svinst = ext->svinst;
 	struct sieve_extension_registry *ext_reg = svinst->ext_reg;
 	struct sieve_capability_registration *reg = 
 		p_new(svinst->pool, struct sieve_capability_registration, 1);
@@ -619,11 +651,29 @@ void sieve_extension_capabilities_register
 		(ext_reg->capabilities_index, (void *) cap->name, (void *) reg);
 }
 
+void sieve_extension_capabilities_unregister
+(const struct sieve_extension *ext) 
+{
+	struct sieve_extension_registry *ext_reg = ext->svinst->ext_reg;
+	struct hash_iterate_context *hictx;
+	void *key = NULL, *value = NULL;
+
+	hictx = hash_table_iterate_init(ext_reg->capabilities_index);
+	while ( hash_table_iterate(hictx, key, value) ) {
+		struct sieve_capability_registration *reg = 
+			(struct sieve_capability_registration *) value;
+
+		if ( reg->ext == ext )
+			hash_table_remove(ext_reg->capabilities_index, key);		
+	}
+	hash_table_iterate_deinit(&hictx);
+}
+
 const char *sieve_extension_capabilities_get_string
 (struct sieve_instance *svinst, const char *cap_name) 
 {
 	struct sieve_extension_registry *ext_reg = svinst->ext_reg;
-  const struct sieve_capability_registration *cap_reg = 
+	const struct sieve_capability_registration *cap_reg = 
 		(const struct sieve_capability_registration *) 
 			hash_table_lookup(ext_reg->capabilities_index, cap_name);
 	const struct sieve_extension_capabilities *cap;
diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h
index d639de7bd452992fd2cf93b9e5fc3872bbb516db..fc9bc6ac85602fd6621b6475f75ced20274fccb7 100644
--- a/src/lib-sieve/sieve-extensions.h
+++ b/src/lib-sieve/sieve-extensions.h
@@ -118,6 +118,8 @@ const struct sieve_extension *sieve_extension_require
 	(struct sieve_instance *svinst, const struct sieve_extension_def *extension);
 bool sieve_extension_reload(const struct sieve_extension *ext);
 
+void sieve_extension_unregister(const struct sieve_extension *ext);
+
 int sieve_extensions_get_count(struct sieve_instance *svinst);
 
 const struct sieve_extension *sieve_extension_get_by_id
@@ -148,8 +150,11 @@ struct sieve_extension_capabilities {
 };
 
 void sieve_extension_capabilities_register
-	(struct sieve_instance *svinst, const struct sieve_extension *ext, 
+	(const struct sieve_extension *ext, 
 		const struct sieve_extension_capabilities *cap);
+void sieve_extension_capabilities_unregister
+	(const struct sieve_extension *ext);
+
 const char *sieve_extension_capabilities_get_string
 	(struct sieve_instance *svinst, const char *cap_name);
 
diff --git a/src/lib-sieve/sieve-plugins.c b/src/lib-sieve/sieve-plugins.c
index cf80ab5ba08d1b80c6361ee98ee2a2c924c13008..ad37c86e47848922c6afbddf335aa33ed8f926ea 100644
--- a/src/lib-sieve/sieve-plugins.c
+++ b/src/lib-sieve/sieve-plugins.c
@@ -13,6 +13,9 @@
 
 struct sieve_plugin {
 	struct module *module;
+	
+	void *context;
+
 	struct sieve_plugin *next;
 };
 
@@ -103,7 +106,7 @@ void sieve_plugins_load(struct sieve_instance *svinst, const char *path, const c
  	for (i = 0; module_names[i] != NULL; i++) {
 		struct sieve_plugin *plugin;
 		const char *name = module_names[i];
-		void (*load_func)(struct sieve_instance *svinst);
+		void (*load_func)(struct sieve_instance *svinst, void **context);
 
 		/* Find the module */
 		module = sieve_plugin_module_find(name);
@@ -129,7 +132,7 @@ void sieve_plugins_load(struct sieve_instance *svinst, const char *path, const c
 		load_func = module_get_symbol
 			(module, t_strdup_printf("%s_load", module->name));
 		if ( load_func != NULL ) {
-			load_func(svinst);
+			load_func(svinst, &plugin->context);
 		}
 
 		/* Add plugin to the instance */
@@ -159,12 +162,12 @@ void sieve_plugins_unload(struct sieve_instance *svinst)
 	plugin = svinst->plugins;
 	while ( plugin != NULL ) {
 		struct module *module = plugin->module;
-		void (*unload_func)(struct sieve_instance *svinst);
+		void (*unload_func)(struct sieve_instance *svinst, void *context);
 
 		unload_func = module_get_symbol
 			(module, t_strdup_printf("%s_unload", module->name));
 		if ( unload_func != NULL ) {
-			unload_func(svinst);
+			unload_func(svinst, plugin->context);
 		}
 
 		plugin = plugin->next;
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 76ed25b31e4b81b80d5df165ee81e67fb298a0ae..123b465564b2477fa9ad0acced3825c0e3784801 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -88,10 +88,10 @@ struct sieve_instance *sieve_init
 
 void sieve_deinit(struct sieve_instance **svinst)
 {
-	sieve_extensions_deinit(*svinst);
-
 	sieve_plugins_unload(*svinst);
 
+	sieve_extensions_deinit(*svinst);
+
 	pool_unref(&(*svinst)->pool);
 
 	*svinst = NULL;