diff --git a/configure.in b/configure.in
index a6cd1750ddb99d26ce5695d475607d46ab54a769..fda744cb6de71b5004fc431b28e0aebcd0e79d0a 100644
--- a/configure.in
+++ b/configure.in
@@ -83,6 +83,16 @@ AC_ARG_ENABLE(header-install,
     want_headers=no)
 AM_CONDITIONAL(INSTALL_HEADERS, test "$want_headers" = "yes")
 
+AC_ARG_ENABLE(header-install,
+[  --enable-header-install Install development headers],
+    if test x$enableval = xno; then
+        want_headers=no
+    else
+        want_headers=yes
+    fi,
+    want_headers=no)
+AM_CONDITIONAL(INSTALL_HEADERS, test "$want_headers" = "yes")
+
 AC_ARG_ENABLE(valgrind,
 [AC_HELP_STRING([--enable-valgrind], [Enable Valgrind memory leak checks in testsuite [default=no]])],
     if test x$enableval = xno || test x$enableval = xauto; then
@@ -107,6 +117,9 @@ AC_SUBST(MODULE_LIBS)
 AC_SUBST(dovecot_incdir)
 AC_SUBST(moduledir)
 
+dovecot_pkgincludedir='$(includedir)/dovecot'
+AC_SUBST(dovecot_pkgincludedir)
+
 dovecot_pkglibexecdir='$(libexecdir)/dovecot'
 dovecot_pkglibdir='$(libdir)/dovecot'
 dovecot_pkgincludedir='$(includedir)/dovecot'
diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am
index f105c6a23eb406e91fb4737d591ab2cbdb5a3493..6f66f428c14cb93a1c5415d2f31efa4766d64220 100644
--- a/src/lib-sieve/Makefile.am
+++ b/src/lib-sieve/Makefile.am
@@ -8,7 +8,8 @@ AM_CPPFLAGS = \
 	-I$(dovecot_incdir)/src/lib-mail \
 	-I$(dovecot_incdir)/src/lib-storage \
 	-I$(dovecot_incdir)/src/lib-imap \
-	-I$(dovecot_incdir)/src/lib-master
+	-I$(dovecot_incdir)/src/lib-master \
+	-DMODULEDIR=\""$(moduledir)"\"
 
 tests = \
 	tst-truefalse.c \
@@ -146,3 +147,10 @@ if INSTALL_HEADERS
 else
   noinst_HEADERS = $(headers)
 endif
+
+if INSTALL_HEADERS
+  pkginc_libdir=$(dovecot_pkgincludedir)/sieve
+  pkginc_lib_HEADERS = $(headers)
+else
+  noinst_HEADERS = $(headers)
+endif
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index cc5c52456509a8a291dc1a067cd7662e79db96a9..00fdc4c9381ef89be1007aedfc844602e793804d 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -6,6 +6,7 @@
 #include "istream.h"
 #include "buffer.h"
 #include "eacces-error.h"
+#include "module-dir.h"
 
 #include "sieve-limits.h"
 #include "sieve-settings.h"
@@ -34,6 +35,81 @@
 #include <stdio.h>
 #include <dirent.h>
 
+/*
+ * Plugin support
+ */
+
+static struct module *sieve_modules = NULL;
+static int sieve_modules_refcount = 0;
+
+static void sieve_plugins_load(struct sieve_instance *svinst)
+{
+	struct module *module;
+
+	/* Physically load modules */
+
+	/* FIXME: sieve plugins may/cannot differ between Sieve instances */
+
+	if ( sieve_modules == NULL ) {
+		const char *plugins = sieve_setting_get(svinst, "sieve_plugins");
+
+		if ( plugins != NULL && *plugins != '\0' ) { 
+			const char *plugin_dir = sieve_setting_get(svinst, "sieve_plugin_dir");
+		
+			if ( plugin_dir == NULL || *plugin_dir == '\0' )
+				plugin_dir = MODULEDIR"/sieve";
+
+			sieve_modules = module_dir_load(plugin_dir, plugins, TRUE, SIEVE_VERSION);
+		}
+	}
+
+	sieve_modules_refcount++;
+
+	/* Call plugin load functions for this instance */
+
+	module = sieve_modules;
+	while ( module != NULL ) {
+		void (*load_func)(struct sieve_instance *svinst);
+
+		load_func = module_get_symbol
+			(module, t_strdup_printf("%s_load", module->name));
+		if ( load_func != NULL ) {
+			load_func(svinst);
+		}
+
+		module = module->next;
+	}
+}
+
+static void sieve_plugins_unload(struct sieve_instance *svinst)
+{
+	struct module *module;
+
+	/* Call plugin unload functions for this instance */
+
+	module = sieve_modules;
+	while ( module != NULL ) {
+		void (*unload_func)(struct sieve_instance *svinst);
+
+		unload_func = module_get_symbol
+			(module, t_strdup_printf("%s_unload", module->name));
+		if ( unload_func != NULL ) {
+			unload_func(svinst);
+		}
+
+		module = module->next;
+	}
+
+	/* Physically unload modules */
+
+	i_assert(sieve_modules_refcount > 0);
+
+	if ( --sieve_modules_refcount != 0 )
+        return;
+
+	module_dir_unload(&sieve_modules);
+}
+
 /* 
  * Main Sieve library interface
  */
@@ -80,11 +156,14 @@ struct sieve_instance *sieve_init
 		return NULL;
 	}
 
+	sieve_plugins_load(svinst);
+
 	return svinst;
 }
 
 void sieve_deinit(struct sieve_instance **svinst)
 {
+	sieve_plugins_unload(*svinst);
 	sieve_extensions_deinit(*svinst);
 
 	pool_unref(&(*svinst)->pool);