diff --git a/src/lib-sieve-tool/mail-raw.c b/src/lib-sieve-tool/mail-raw.c
index c9268d7e473c6046a0cdb85a3086b9da30097ee6..44c964398b5617841404fa7acef6b70c7e6f9e81 100644
--- a/src/lib-sieve-tool/mail-raw.c
+++ b/src/lib-sieve-tool/mail-raw.c
@@ -16,6 +16,7 @@
 #include "safe-mkstemp.h"
 #include "close-keep-errno.h"
 #include "mkdir-parents.h"
+#include "abspath.h"
 #include "message-address.h"
 #include "mbox-from.h"
 #include "raw-storage.h"
@@ -50,11 +51,12 @@ static const char *wanted_headers[] = {
  * Global data
  */
 
-static struct mail_namespace *raw_ns;
-static struct mail_namespace_settings raw_ns_set;
-static struct mail_user *raw_mail_user;
+struct mail_raw_user {
+	struct mail_namespace *ns;;
+	struct mail_user *mail_user;
 
-char *raw_tmp_prefix;
+	char *tmp_prefix;
+};
 
 /*
  * Raw mail implementation
@@ -148,7 +150,7 @@ static struct istream *create_raw_stream
 
 	input_list[0] = input2; input_list[1] = NULL;
 	input = i_stream_create_seekable(input_list, MAIL_MAX_MEMORY_BUFFER,
-		seekable_fd_callback, raw_mail_user);
+		seekable_fd_callback, NULL);
 	i_stream_unref(&input2);
 	return input;
 }
@@ -157,39 +159,50 @@ static struct istream *create_raw_stream
  * Init/Deinit
  */
 
-void mail_raw_init
-(struct master_service *service, const char *user,
+struct mail_raw_user *mail_raw_user_init
+(struct master_service *service, const char *username,
 	struct mail_user *mail_user) 
 {
+	struct mail_raw_user *ruser;
+	struct mail_namespace_settings ns_set;
 	const char *errstr;
 	void **sets;
+
+	ruser = i_new(struct mail_raw_user, 1);
 	
 	sets = master_service_settings_get_others(service);
 
-	raw_mail_user = mail_user_alloc(user, mail_user->set_info, sets[0]);
-	mail_user_set_home(raw_mail_user, "/");
+	ruser->mail_user = mail_user_alloc(username, mail_user->set_info, sets[0]);
+	mail_user_set_home(ruser->mail_user, "/");
    
-	if (mail_user_init(raw_mail_user, &errstr) < 0)
+	if (mail_user_init(ruser->mail_user, &errstr) < 0)
 		i_fatal("Raw user initialization failed: %s", errstr);
 
-	memset(&raw_ns_set, 0, sizeof(raw_ns_set));
-	raw_ns_set.location = ":LAYOUT=none";
+	memset(&ns_set, 0, sizeof(ns_set));
+	ns_set.location = ":LAYOUT=none";
 
-	raw_ns = mail_namespaces_init_empty(raw_mail_user);
-	raw_ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
-	raw_ns->set = &raw_ns_set;
+	ruser->ns = mail_namespaces_init_empty(ruser->mail_user);
+	ruser->ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
+	ruser->ns->set = &ns_set;
     
-	if (mail_storage_create(raw_ns, "raw", 0, &errstr) < 0)
+	if (mail_storage_create(ruser->ns, "raw", 0, &errstr) < 0)
 		i_fatal("Couldn't create internal raw storage: %s", errstr);
 
-	raw_tmp_prefix = i_strdup(mail_user_get_temp_prefix(mail_user));
+	ruser->tmp_prefix = i_strdup(mail_user_get_temp_prefix(ruser->mail_user));
+
+	return ruser;
 }
 
-void mail_raw_deinit(void)
+void mail_raw_user_deinit(struct mail_raw_user **_ruser)
 {
-	i_free(raw_tmp_prefix);
+	struct mail_raw_user *ruser = *_ruser;
 
-	mail_user_unref(&raw_mail_user);
+	*_ruser = NULL;
+
+	mail_user_unref(&ruser->mail_user);
+
+	i_free(ruser->tmp_prefix);
+	i_free(ruser);	
 }
 
 /*
@@ -197,26 +210,18 @@ void mail_raw_deinit(void)
  */
 
 static struct mail_raw *mail_raw_create
-(struct istream *input, const char *mailfile, const char *sender,
-	time_t mtime)
+(struct mail_raw_user *ruser, struct istream *input, 
+	const char *mailfile, const char *sender, time_t mtime)
 {
 	pool_t pool;
+	struct mail_namespace *raw_ns = ruser->ns;
 	struct raw_mailbox *raw_box;
 	struct mail_raw *mailr;
 	enum mail_error error;
 	struct mailbox_header_lookup_ctx *headers_ctx;
 
-	if ( mailfile != NULL ) {
-		if ( *mailfile != '/') {
-			char cwd[PATH_MAX];
-
-			/* Expand relative paths */
-			if (getcwd(cwd, sizeof(cwd)) == NULL)
-				i_fatal("getcwd() failed: %m");
-
-			mailfile = t_strconcat(cwd, "/", mailfile, NULL);		
-		} 
-	}
+	if ( mailfile != NULL && *mailfile != '/' )
+		mailfile = t_abspath(mailfile);		
 
 	pool = pool_alloconly_create("mail_raw", 1024);
 	mailr = p_new(pool, struct mail_raw, 1);
@@ -227,24 +232,24 @@ static struct mail_raw *mail_raw_create
 			MAILBOX_FLAG_NO_INDEX_FILES);
 
 		if (mailbox_open_stream(mailr->box, input) < 0) {
-            i_fatal("Can't open mail stream as raw: %s",
-                mail_storage_get_last_error(raw_ns->storage, &error));
-        }
+			i_fatal("Can't open mail stream as raw: %s",
+				mail_storage_get_last_error(raw_ns->storage, &error));
+		}
 	} else {
 		mtime = (time_t)-1;
 		mailr->box = mailbox_alloc(raw_ns->list, mailfile,
 			MAILBOX_FLAG_NO_INDEX_FILES);
 
 		if ( mailbox_open(mailr->box) < 0 ) {
-    	    i_fatal("Can't open mail stream as raw: %s",
-        	    mail_storage_get_last_error(raw_ns->storage, &error));
-	    }
+			i_fatal("Can't open mail stream as raw: %s",
+				mail_storage_get_last_error(raw_ns->storage, &error));
+		}
 	}
 
-    if ( mailbox_sync(mailr->box, 0) < 0 ) {
-        i_fatal("Can't sync delivery mail: %s",
-            mail_storage_get_last_error(raw_ns->storage, &error));
-    }
+	if ( mailbox_sync(mailr->box, 0) < 0 ) {
+		i_fatal("Can't sync delivery mail: %s",
+		mail_storage_get_last_error(raw_ns->storage, &error));
+	}
 
 	raw_box = (struct raw_mailbox *)mailr->box;
 	raw_box->envelope_sender = sender != NULL ? sender : DEFAULT_ENVELOPE_SENDER;
@@ -259,21 +264,23 @@ static struct mail_raw *mail_raw_create
 	return mailr;
 }
 
-struct mail_raw *mail_raw_open_data(string_t *mail_data)
+struct mail_raw *mail_raw_open_data
+(struct mail_raw_user *ruser, string_t *mail_data)
 {
 	struct mail_raw *mailr;
 	struct istream *input;
 
 	input = i_stream_create_from_data(str_data(mail_data), str_len(mail_data));
 	
-	mailr = mail_raw_create(input, NULL, NULL, (time_t)-1);
+	mailr = mail_raw_create(ruser, input, NULL, NULL, (time_t)-1);
 
 	i_stream_unref(&input);
 
 	return mailr;
 }
 	
-struct mail_raw *mail_raw_open_file(const char *path)
+struct mail_raw *mail_raw_open_file
+(struct mail_raw_user *ruser, const char *path)
 {
 	struct mail_raw *mailr;
 	struct istream *input = NULL;
@@ -285,7 +292,7 @@ struct mail_raw *mail_raw_open_file(const char *path)
 		input = create_raw_stream(0, &mtime, &sender);
 	}
 
-	mailr = mail_raw_create(input, path, sender, mtime);
+	mailr = mail_raw_create(ruser, input, path, sender, mtime);
 
 	if ( input != NULL )
 		i_stream_unref(&input);
@@ -293,12 +300,13 @@ struct mail_raw *mail_raw_open_file(const char *path)
 	return mailr;
 }
 
-void mail_raw_close(struct mail_raw *mailr) 
+void mail_raw_close(struct mail_raw **mailr) 
 {
-	mail_free(&mailr->mail);
-	mailbox_transaction_rollback(&mailr->trans);
-	mailbox_free(&mailr->box);
+	mail_free(&(*mailr)->mail);
+	mailbox_transaction_rollback(&(*mailr)->trans);
+	mailbox_free(&(*mailr)->box);
 
-	pool_unref(&mailr->pool);
+	pool_unref(&(*mailr)->pool);
+	*mailr = NULL;
 }
 
diff --git a/src/lib-sieve-tool/mail-raw.h b/src/lib-sieve-tool/mail-raw.h
index 8a89c02957fa341a62c006ecd403b0dbce146612..68943049aa1b4fcfd6ca4d4d319d02d8a265a758 100644
--- a/src/lib-sieve-tool/mail-raw.h
+++ b/src/lib-sieve-tool/mail-raw.h
@@ -15,14 +15,16 @@ struct mail_raw {
 	struct mailbox_transaction_context *trans;
 };
 
-void mail_raw_init
-(struct master_service *service, const char *user, 
+struct mail_raw_user *mail_raw_user_init
+(struct master_service *service, const char *username,
 	struct mail_user *mail_user);
-void mail_raw_deinit(void);
+void mail_raw_user_deinit(struct mail_raw_user **_ruser);
 
-struct mail_raw *mail_raw_open_file(const char *path);
-struct mail_raw *mail_raw_open_data(string_t *mail_data);
-void mail_raw_close(struct mail_raw *mailr);
+struct mail_raw *mail_raw_open_file
+	(struct mail_raw_user *ruser, const char *path);
+struct mail_raw *mail_raw_open_data
+	(struct mail_raw_user *ruser, string_t *mail_data);
+void mail_raw_close(struct mail_raw **mailr);
 
 
 #endif /* __MAIL_RAW_H */
diff --git a/src/lib-sieve-tool/sieve-tool.c b/src/lib-sieve-tool/sieve-tool.c
index ef5659071a18f75bfd222b055b035f48560c51dc..8a8a06f0dda9ed86aaef8d258ea4521dcd170091 100644
--- a/src/lib-sieve-tool/sieve-tool.c
+++ b/src/lib-sieve-tool/sieve-tool.c
@@ -8,11 +8,18 @@
 #include "ostream.h"
 #include "hostpid.h"
 #include "dict.h"
+#include "mail-namespace.h"
 #include "mail-storage.h"
 #include "mail-user.h"
+#include "master-service.h"
+#include "master-service-settings.h"
+#include "mail-storage-service.h"
 
 #include "sieve.h"
 #include "sieve-plugins.h"
+#include "sieve-extensions.h"
+
+#include "mail-raw.h"
 
 #include "sieve-tool.h"
 
@@ -21,97 +28,398 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <pwd.h>
+#include <sysexits.h>
 
 /*
  * Global state
  */
 
-/* Sieve instance */
+struct sieve_tool {
+	char *name;
+
+	bool no_config;
+
+	char *username;
+	char *homedir;
+	
+	char *sieve_extensions;
+	ARRAY_TYPE(const_string) sieve_plugins;
+
+	sieve_tool_setting_callback_t setting_callback;
+	void *setting_callback_context;
 
-struct sieve_instance *sieve_instance;
+	struct sieve_instance *svinst;
+
+	struct mail_storage_service_ctx *storage_service;
+	struct mail_storage_service_user *service_user;
+	struct mail_user *mail_user_dovecot;
+	struct mail_user *mail_user;
+
+	struct mail_raw_user *mail_raw_user;
+	struct mail_raw *mail_raw;
+
+	unsigned int debug:1;
+};
+
+struct sieve_tool *sieve_tool;
 
 /*
  * Settings management
  */
 
-const char *sieve_tool_get_setting
+static const char *sieve_tool_sieve_get_setting
 (void *context, const char *identifier)
 {
-	struct mail_user *mail_user = (struct mail_user *) context;
+	struct sieve_tool *tool = (struct sieve_tool *) context;
+
+	if ( tool->setting_callback != NULL )
+		return tool->setting_callback(tool->setting_callback_context, identifier);
 
-	if ( mail_user == NULL )
+	if ( tool->mail_user == NULL )
 		return NULL;
 
-	return mail_user_plugin_getenv(mail_user, identifier);
+	return mail_user_plugin_getenv(tool->mail_user, identifier);
 }
 
-const char *sieve_tool_get_homedir
+static const char *sieve_tool_sieve_get_homedir
 (void *context)
 {
-	struct mail_user *mail_user = (struct mail_user *) context;
-	const char *home = NULL;
-
-	if ( mail_user == NULL )
-		return NULL;
-
-	if ( mail_user_get_home(mail_user, &home) <= 0 )
-		return NULL;
+	struct sieve_tool *tool = (struct sieve_tool *) context;
 
-	return home;
+	return sieve_tool_get_homedir(tool);
 }
 
 const struct sieve_environment sieve_tool_sieve_env = {
-	sieve_tool_get_homedir,
-	sieve_tool_get_setting
+	sieve_tool_sieve_get_homedir,
+	sieve_tool_sieve_get_setting
 };
 
 /*
  * Initialization
  */
 
-void sieve_tool_init
-(const struct sieve_environment *env, void *context, bool debug)
+struct sieve_tool *sieve_tool_init
+(const char *name, int *argc, char **argv[], const char *getopt_str,
+	bool no_config)
 {
-	if ( env == NULL ) env = &sieve_tool_sieve_env;
+	struct sieve_tool *tool;
+	enum master_service_flags service_flags =
+		MASTER_SERVICE_FLAG_STANDALONE;
 
-	if ( (sieve_instance=sieve_init(env, context, debug)) == NULL )
-		i_fatal("failed to initialize sieve implementation\n");
+	if ( no_config )
+		service_flags |= MASTER_SERVICE_FLAG_NO_CONFIG_SETTINGS;
+
+	master_service = master_service_init
+		(name, service_flags, argc, argv, getopt_str);
+
+	tool = i_new(struct sieve_tool, 1);
+	tool->name = i_strdup(name);
+	tool->no_config = no_config;
+	
+	i_array_init(&tool->sieve_plugins, 16);
+
+	return tool;
 }
 
-void sieve_tool_deinit(void)
+int sieve_tool_getopt(struct sieve_tool *tool)
 {
-	sieve_deinit(&sieve_instance);
+	int c;
+
+	while ( (c = master_getopt(master_service)) > 0 ) {
+		switch ( c ) { 
+		case 'x':
+			/* extensions */
+			if ( tool->sieve_extensions != NULL ) {
+				i_fatal_status(EX_USAGE, 
+					"Duplicate -x option specified, but only one allowed.");
+			}
+
+			tool->sieve_extensions = i_strdup(optarg);
+			break;
+		case 'u':
+			tool->username = i_strdup(optarg);
+			break;
+		case 'P': 
+			/* Plugin */
+			{
+				const char *plugin;			
+
+				plugin = t_strdup(optarg);
+				array_append(&tool->sieve_plugins, &plugin, 1);
+			}
+			break;
+		case 'D':
+			tool->debug = TRUE;
+			break;
+		default:
+			return c;
+		}
+	}
 
+	return c;
 }
 
+static void sieve_tool_load_plugins
+(struct sieve_tool *tool)
+{
+	unsigned int i, count;
+	const char * const *plugins;
+
+	plugins = array_get(&tool->sieve_plugins, &count);
+	for ( i = 0; i < count; i++ ) {
+		const char *path, *file = strrchr(plugins[i], '/');
+
+		if ( file != NULL ) {
+			path = t_strdup_until(plugins[i], file);
+			file = file+1;
+		} else {
+			path = NULL;
+			file = plugins[i];
+		}
+
+		sieve_plugins_load(tool->svinst, path, file);		
+	}
+}
+
+struct sieve_instance *sieve_tool_init_finish
+(struct sieve_tool *tool)
+{
+	enum mail_storage_service_flags storage_service_flags =
+		MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR |
+		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
+	struct mail_storage_service_input service_input;
+	const char *username = tool->username;
+	const char *errstr;
+
+	master_service_init_finish(master_service);
+
+	if ( username == NULL )
+		username = tool->username = i_strdup(getenv("USER"));
+	else
+		storage_service_flags |=
+			MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+
+	memset(&service_input, 0, sizeof(service_input));
+	service_input.module = tool->name;
+	service_input.service = tool->name;
+	service_input.username = username;
+
+	tool->storage_service = mail_storage_service_init
+		(master_service, NULL, storage_service_flags);
+	if (mail_storage_service_lookup_next
+		(tool->storage_service, &service_input, &tool->service_user, 
+			&tool->mail_user_dovecot, &errstr) <= 0)
+		i_fatal("%s", errstr);
+
+	if ( master_service_set
+		(master_service, "mail_full_filesystem_access=yes") < 0 )
+		i_unreached();
+
+	/* Initialize Sieve Engine */
+	if ( (tool->svinst=sieve_init(&sieve_tool_sieve_env, tool, tool->debug)) 
+		== NULL )
+		i_fatal("failed to initialize sieve implementation\n");
+
+	/* Load Sieve plugins */
+	if ( array_count(&tool->sieve_plugins) > 0 ) {
+		sieve_tool_load_plugins(tool);
+	}
+
+	/* Set active Sieve extensions */
+	if ( tool->sieve_extensions != NULL ) {
+		sieve_set_extensions(tool->svinst, tool->sieve_extensions);
+	} else if ( tool->no_config ) {
+		sieve_set_extensions(tool->svinst, NULL);
+	}
+
+	return tool->svinst;
+}
+
+void sieve_tool_deinit(struct sieve_tool **_tool)
+{
+	struct sieve_tool *tool = *_tool;
+
+	*_tool = NULL;
+
+	/* Deinitialize Sieve engine */
+	sieve_deinit(&tool->svinst);
+
+	/* Free options */
+
+	if ( tool->username != NULL )
+		i_free(tool->username);
+	if ( tool->homedir != NULL )
+		i_free(tool->homedir);
+
+	if ( tool->sieve_extensions != NULL ) 
+		i_free(tool->sieve_extensions);
+	array_free(&tool->sieve_plugins);
+
+	/* Free raw mail */
+
+	if ( tool->mail_raw != NULL )
+		mail_raw_close(&tool->mail_raw);
+
+	if ( tool->mail_raw_user != NULL )
+		mail_raw_user_deinit(&tool->mail_raw_user);
+	
+	/* Free mail service */
+
+	if ( tool->mail_user != NULL )
+		mail_user_unref(&tool->mail_user);
+	if ( tool->mail_user_dovecot != NULL )
+		mail_user_unref(&tool->mail_user_dovecot);
+
+	mail_storage_service_user_free(&tool->service_user);
+	mail_storage_service_deinit(&tool->storage_service);
+
+	/* Free sieve tool object */
+
+	i_free(tool->name);
+	i_free(tool);
+
+	/* Deinitialize service */
+	master_service_deinit(&master_service);
+}
 
 /*
- * Commonly needed functionality
+ * Mail environment
  */
 
-const char *sieve_tool_get_user(void)
+void sieve_tool_init_mail_user
+(struct sieve_tool *tool, const char *mail_location)
+{
+	struct mail_user *mail_user_dovecot = tool->mail_user_dovecot;
+	const char *username = tool->username;
+	struct mail_namespace_settings ns_set;
+	struct mail_namespace *ns = NULL;
+	const char *home = NULL, *errstr = NULL;
+
+	tool->mail_user = mail_user_alloc
+		(username, mail_user_dovecot->set_info, mail_user_dovecot->unexpanded_set);
+
+	if ( (home=sieve_tool_get_homedir(sieve_tool)) != NULL ) {
+		mail_user_set_home(tool->mail_user, home);
+	}
+
+	if ( mail_user_init(tool->mail_user, &errstr) < 0 )
+ 		i_fatal("Test user initialization failed: %s", errstr);
+
+	memset(&ns_set, 0, sizeof(ns_set));
+	ns_set.location = mail_location;
+	ns_set.inbox = TRUE;
+	ns_set.subscriptions = TRUE;
+
+	ns = mail_namespaces_init_empty(tool->mail_user);
+	ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
+	ns->set = &ns_set;
+
+	if ( mail_storage_create(ns, NULL, 0, &errstr) < 0 )
+		i_fatal("Test storage creation failed: %s", errstr);
+}
+
+struct mail *sieve_tool_open_file_as_mail
+(struct sieve_tool *tool, const char *path)
 {
-	const char *user;
-	uid_t process_euid;
-	struct passwd *pw;
+	if ( tool->mail_raw_user == NULL )
+		tool->mail_raw_user = mail_raw_user_init
+			(master_service, tool->username, tool->mail_user_dovecot);
 
-	user = getenv("USER");
+	if ( tool->mail_raw != NULL )
+		mail_raw_close(&tool->mail_raw);
 
-	if ( user == NULL || *user == '\0' ) {
-		process_euid = geteuid();
+	tool->mail_raw = mail_raw_open_file(tool->mail_raw_user, path);
 
-		if ((pw = getpwuid(process_euid)) != NULL) {
-			user = t_strdup(pw->pw_name);
-		}
+	return tool->mail_raw->mail; 
+}
 
-		if ( user == NULL || *user == '\0' ) {
-			i_fatal("couldn't lookup our username (uid=%s)", dec2str(process_euid));
-		}
+struct mail *sieve_tool_open_data_as_mail
+(struct sieve_tool *tool, string_t *mail_data)
+{
+	if ( tool->mail_raw_user == NULL )
+		tool->mail_raw_user = mail_raw_user_init
+			(master_service, tool->username, tool->mail_user_dovecot);
+
+	if ( tool->mail_raw != NULL )
+		mail_raw_close(&tool->mail_raw);
+
+	tool->mail_raw = mail_raw_open_data(tool->mail_raw_user, mail_data);
+
+	return tool->mail_raw->mail; 
+}
+
+/*
+ * Configuration
+ */
+
+void sieve_tool_set_homedir(struct sieve_tool *tool, const char *homedir)
+{
+	if ( tool->homedir != NULL ) {
+		if ( strcmp(homedir, tool->homedir) == 0 )
+			return;
+
+		i_free(tool->homedir);
 	}
 	
-	return user;
+	tool->homedir = i_strdup(homedir);
+
+	if ( tool->mail_user_dovecot != NULL )
+		mail_user_set_home(tool->mail_user_dovecot, tool->homedir);
+	if ( tool->mail_user != NULL )
+		mail_user_set_home(tool->mail_user, tool->homedir);
+}
+
+void sieve_tool_set_setting_callback
+(struct sieve_tool *tool, sieve_tool_setting_callback_t callback, void *context)
+{
+	tool->setting_callback = callback;	
+	tool->setting_callback_context = context;
+}
+
+/*
+ * Accessors
+ */
+
+const char *sieve_tool_get_username
+(struct sieve_tool *tool)
+{
+	return tool->username;
 }
 
+const char *sieve_tool_get_homedir
+(struct sieve_tool *tool)
+{
+	const char *home = NULL;
+
+	if ( tool->homedir != NULL )
+		return tool->homedir;
+
+	if ( tool->mail_user_dovecot != NULL &&
+		mail_user_get_home(tool->mail_user_dovecot, &home) > 0 ) {
+		tool->homedir = i_strdup(home);
+		return tool->homedir;
+	}
+
+	home = getenv("HOME");
+	if ( home != NULL ) {
+		tool->homedir = i_strdup(home);
+		return tool->homedir;
+	}
+		
+	return NULL;
+}
+
+struct mail_user *sieve_tool_get_mail_user
+(struct sieve_tool *tool)
+{
+	return ( tool->mail_user == NULL ?
+		tool->mail_user_dovecot : tool->mail_user );
+}
+
+/*
+ * Commonly needed functionality
+ */
+
 void sieve_tool_get_envelope_data
 	(struct mail *mail, const char **recipient, const char **sender)
 {
@@ -134,33 +442,12 @@ void sieve_tool_get_envelope_data
 		*sender = "sender@example.com";
 }
 
-void sieve_tool_load_plugins(ARRAY_TYPE(const_string) *plugins)
-{
-	unsigned int i, count;
-	const char * const*_plugins;
-
-	_plugins = array_get(plugins, &count);
-	for ( i = 0; i < count; i++ ) {
-		const char *path, *file = strrchr(_plugins[i], '/');
-
-		if ( file != NULL ) {
-			path = t_strdup_until(_plugins[i], file);
-			file = file+1;
-		} else {
-			path = NULL;
-			file = _plugins[i];
-		}
-
-		sieve_plugins_load(sieve_instance, path, file);		
-	}
-}
-
 /*
  * Sieve script handling
  */
 
 struct sieve_binary *sieve_tool_script_compile
-(const char *filename, const char *name)
+(struct sieve_instance *svinst, const char *filename, const char *name)
 {
 	struct sieve_error_handler *ehandler;
 	struct sieve_binary *sbin;
@@ -168,7 +455,7 @@ struct sieve_binary *sieve_tool_script_compile
 	ehandler = sieve_stderr_ehandler_create(0);
 	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
-	if ( (sbin = sieve_compile(sieve_instance, filename, name, ehandler)) == NULL )
+	if ( (sbin = sieve_compile(svinst, filename, name, ehandler)) == NULL )
 		i_error("failed to compile sieve script '%s'", filename);
 
 	sieve_error_handler_unref(&ehandler);
@@ -176,7 +463,8 @@ struct sieve_binary *sieve_tool_script_compile
 	return sbin;
 }
 	
-struct sieve_binary *sieve_tool_script_open(const char *filename)
+struct sieve_binary *sieve_tool_script_open
+(struct sieve_instance *svinst, const char *filename)
 {
 	struct sieve_error_handler *ehandler;
 	struct sieve_binary *sbin;
@@ -184,9 +472,9 @@ struct sieve_binary *sieve_tool_script_open(const char *filename)
 	ehandler = sieve_stderr_ehandler_create(0);
 	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
-	if ( (sbin = sieve_open(sieve_instance, filename, NULL, ehandler, NULL)) == NULL ) {
+	if ( (sbin = sieve_open(svinst, filename, NULL, ehandler, NULL)) == NULL ) {
 		sieve_error_handler_unref(&ehandler);
-		i_fatal("Failed to compile sieve script");
+		i_fatal("failed to compile sieve script");
 	}
 
 	sieve_error_handler_unref(&ehandler);
diff --git a/src/lib-sieve-tool/sieve-tool.h b/src/lib-sieve-tool/sieve-tool.h
index 4d95bb3f6d342ab16df870b8a7ea3b52171feab2..0222d80c8d8b69d235e0562f34346a0dfe0b41f1 100644
--- a/src/lib-sieve-tool/sieve-tool.h
+++ b/src/lib-sieve-tool/sieve-tool.h
@@ -6,45 +6,81 @@
 
 #include "sieve-common.h"
 
-/* Functionality common to all Sieve command line tools. */
+/* 
+ * Types
+ */
+
+typedef const char *(*sieve_tool_setting_callback_t)
+	(void *context, const char *identifier);
+
+/*
+ * Global variables
+ */
+
+extern struct sieve_tool *sieve_tool;
 
 /*
- * Sieve instance
+ * Initialization
  */
 
-extern struct sieve_instance *sieve_instance;
+struct sieve_tool *sieve_tool_init
+	(const char *name, int *argc, char **argv[], const char *getopt_str,
+		bool no_config);
+
+int sieve_tool_getopt(struct sieve_tool *tool);
 
-const char *sieve_tool_get_setting(void *context, const char *identifier);
-const char *sieve_tool_get_homedir(void *context);
+struct sieve_instance *sieve_tool_init_finish(struct sieve_tool *tool);
 
-extern const struct sieve_environment sieve_tool_env;
+void sieve_tool_deinit(struct sieve_tool **_tool);
 
 /*
- * Initialization
+ * Mail environment
+ */
+
+void sieve_tool_init_mail_user
+	(struct sieve_tool *tool, const char *mail_location);
+
+struct mail *sieve_tool_open_file_as_mail
+	(struct sieve_tool *tool, const char *path);
+struct mail *sieve_tool_open_data_as_mail
+	(struct sieve_tool *tool, string_t *mail_data);
+
+/*
+ * Accessors
  */
 
-void sieve_tool_init
-	(const struct sieve_environment *env, void *context, bool debug);
-void sieve_tool_deinit(void);
+const char *sieve_tool_get_username
+	(struct sieve_tool *tool);
+const char *sieve_tool_get_homedir
+(struct sieve_tool *tool);
+struct mail_user *sieve_tool_get_mail_user
+	(struct sieve_tool *tool);
 
 /*
- * Commonly needed functionality
+ * Configuration
  */
 
-const char *sieve_tool_get_user(void);
+void sieve_tool_set_homedir(struct sieve_tool *tool, const char *homedir);
+void sieve_tool_set_setting_callback
+	(struct sieve_tool *tool, sieve_tool_setting_callback_t callback,
+		void *context);
+
+/*
+ * Commonly needed functionality
+ */
 
 void sieve_tool_get_envelope_data
 	(struct mail *mail, const char **recipient, const char **sender);
 
-void sieve_tool_load_plugins(ARRAY_TYPE(const_string) *plugins);
-
 /*
  * Sieve script handling
  */
 
 struct sieve_binary *sieve_tool_script_compile
-	(const char *filename, const char *name);
-struct sieve_binary *sieve_tool_script_open(const char *filename);
-void sieve_tool_dump_binary_to(struct sieve_binary *sbin, const char *filename);
+	(struct sieve_instance *svinst, const char *filename, const char *name);
+struct sieve_binary *sieve_tool_script_open
+	(struct sieve_instance *svinst, const char *filename);
+void sieve_tool_dump_binary_to
+	(struct sieve_binary *sbin, const char *filename);
 
 #endif /* __SIEVE_TOOL_H */
diff --git a/src/sieve-tools/sieve-filter.c b/src/sieve-tools/sieve-filter.c
index 868f2adc6c08c2ccf537b320f1105ee27b86dc81..fd4479233d3880be32f879dfd4e8a89b8aa5d48c 100644
--- a/src/sieve-tools/sieve-filter.c
+++ b/src/sieve-tools/sieve-filter.c
@@ -11,15 +11,11 @@
 #include "mail-namespace.h"
 #include "mail-storage.h"
 #include "mail-search-build.h"
-#include "master-service.h"
-#include "master-service-settings.h"
-#include "mail-storage-service.h"
 
 #include "sieve.h"
 #include "sieve-extensions.h"
 #include "sieve-binary.h"
 
-#include "mail-raw.h"
 #include "sieve-tool.h"
 
 #include "sieve-ext-debug.h"
@@ -31,7 +27,6 @@
 #include <pwd.h>
 #include <sysexits.h>
 
-
 /*
  * Print help
  */
@@ -221,70 +216,38 @@ static int filter_mailbox
 
 int main(int argc, char **argv) 
 {
-	enum mail_storage_service_flags service_flags = 0;
-	struct mail_storage_service_ctx *storage_service;
-	struct mail_storage_service_user *service_user;
-	struct mail_storage_service_input service_input;
-	struct mail_user *mail_user_dovecot = NULL;
-	struct mail_user *mail_user = NULL;
-	ARRAY_TYPE (const_string) plugins;
-	const char *scriptfile, *recipient, *sender, *extensions,
-	*src_mailbox, *dst_mailbox, *src_mailstore, *dst_mailstore; 
-	const char *user, *home, *errstr;
-	struct mail_namespace_settings ns_set;
-	struct mail_namespace *src_ns = NULL, *dst_ns = NULL;
-	struct mail_storage *dst_storage, *src_storage;
+	struct sieve_instance *svinst;
+	const char *scriptfile, *recipient, *sender,
+	*src_mailbox, *dst_mailbox, *src_mailstore, *dst_mailstore;
+	struct mail_user *mail_user;
+	struct mail_namespace *src_ns, *dst_ns;
 	struct sieve_binary *main_sbin;
 	struct sieve_script_env scriptenv;
 	struct sieve_error_handler *ehandler;
-	bool force_compile = FALSE, debug = FALSE;
+	bool force_compile = FALSE;
 	enum mailbox_flags open_flags =
-	MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_IGNORE_ACLS;
+		MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_IGNORE_ACLS;
 	enum mail_error error;
 	struct discard_action discard_action = 
 	{ DISCARD_ACTION_KEEP, "Trash" };
 	struct mailbox *src_box;
 	int c;
 
-	master_service = master_service_init("sieve-test",
-		MASTER_SERVICE_FLAG_STANDALONE, &argc, &argv, "m:x:P:CD");
-
-	sieve_tool_init(FALSE);
-
-	t_array_init(&plugins, 4);
-
-	user = getenv("USER");
+	sieve_tool = sieve_tool_init("sieve-filter", &argc, &argv, "m:x:P:CD", FALSE);
 
 	/* Parse arguments */
-	scriptfile = recipient = sender = extensions = src_mailstore = dst_mailstore 
-		= NULL;
+	scriptfile = recipient = sender = src_mailstore = dst_mailstore = NULL;
 	src_mailbox = dst_mailbox = "INBOX";
 	force_compile = FALSE;
-	while ((c = master_getopt(master_service)) > 0) {
+	while ((c = sieve_tool_getopt(sieve_tool)) > 0) {
 		switch (c) {
 		case 'm':
 			/* default mailbox (keep box) */
 			dst_mailbox = optarg;
 			break;
-		case 'x':
-			/* extensions */
-			extensions = optarg;
-			break;
-		case 'P':
-			/* Plugin */
-			{
-				const char *plugin;
-
-				plugin = t_strdup(optarg);
-				array_append(&plugins, &plugin, 1);
-			}
-			break;
 		case 'C':
 			force_compile = TRUE;
 			break;
-		case 'D':
-			debug = TRUE;
-			break;
 		default:
 			print_help();
 			i_fatal_status(EX_USAGE, "Unknown argument: %c", c);
@@ -315,18 +278,10 @@ int main(int argc, char **argv)
 		i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
 	}
 
-	sieve_tool_sieve_init(NULL, debug);
+	svinst = sieve_tool_init_finish(sieve_tool);
 
-	if ( array_count(&plugins) > 0 ) {
-		sieve_tool_load_plugins(&plugins);
-	}
-
-	if ( extensions != NULL ) {
-		sieve_set_extensions(sieve_instance, extensions);
-	}
-
-	/* Register tool-specific extensions */
-	(void) sieve_extension_register(sieve_instance, &debug_extension, TRUE);
+	/* Register Sieve debug extension */
+	(void) sieve_extension_register(svinst, &debug_extension, TRUE);
 
 	/* Create error handler */
 	ehandler = sieve_stderr_ehandler_create(0);
@@ -335,56 +290,14 @@ int main(int argc, char **argv)
 
 	/* Compile main sieve script */
 	if ( force_compile ) {
-		main_sbin = sieve_tool_script_compile(scriptfile, NULL);
+		main_sbin = sieve_tool_script_compile(svinst, scriptfile, NULL);
 		(void) sieve_save(main_sbin, NULL);
 	} else {
-		main_sbin = sieve_tool_script_open(scriptfile);
+		main_sbin = sieve_tool_script_open(svinst, scriptfile);
 	}
 
-	user = sieve_tool_get_user();
-	home = getenv("HOME");
-
-	/* Initialize mail storages */
-	env_put("DOVECONF_ENV=1");
-	env_put(t_strdup_printf("MAIL=maildir:/tmp/dovecot-test-%s", user));
-
-	master_service_init_finish(master_service);
-
-	memset(&service_input, 0, sizeof(service_input));
-	service_input.module = "sieve-test";
-	service_input.service = "sieve-test";
-	service_input.username = user;
-
- 	storage_service = mail_storage_service_init
-		(master_service, NULL, service_flags);
-	if (mail_storage_service_lookup_next(storage_service, &service_input,
-		                 &service_user, &mail_user_dovecot, &errstr) <= 0)
-		i_fatal("%s", errstr);
-
-	/* Initialize namespaces */
-	mail_user = mail_user_alloc
-		(user, mail_user_dovecot->set_info, mail_user_dovecot->unexpanded_set);
-	mail_user_set_home(mail_user, home);
-	if ( mail_user_init(mail_user, &errstr) < 0 )
-		i_fatal("Test user initialization failed: %s", errstr);
-
-
- 	memset(&ns_set, 0, sizeof(ns_set));
-	ns_set.location = src_mailstore;
-
-	/*if ( dst_mailstore != NULL ) {
-	}*/
-
-	src_ns = mail_namespaces_init_empty(mail_user);
-	src_ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
-	src_ns->set = &ns_set;
-
-	if ( mail_storage_create(src_ns, NULL, 0, &errstr) < 0 )
-		i_fatal("Test storage creation failed: %s", errstr);
-
-	if ( master_service_set
-		(master_service, "mail_full_filesystem_access=yes") < 0 )
-		i_unreached();	
+	sieve_tool_init_mail_user(sieve_tool, src_mailstore);
+	mail_user = sieve_tool_get_mail_user(sieve_tool);
 
 /*	if ( dst_mailstore != NULL ) {
 		folder = "#src/";
@@ -395,26 +308,23 @@ int main(int argc, char **argv)
 
 		discard_action.type = DISCARD_ACTION_KEEP;	
 	} else {*/
-		dst_ns = src_ns;
+		dst_ns = src_ns = mail_user->namespaces;
 		discard_action.type = DISCARD_ACTION_DELETE;	
 /*	}*/
 
-	src_storage = src_ns->storage;
-	dst_storage = dst_ns->storage;
-
 	/* Open the source mailbox */	
 	src_box = mailbox_alloc(src_ns->list, src_mailbox, open_flags);
-    if ( mailbox_open(src_box) < 0 ) {
+  if ( mailbox_open(src_box) < 0 ) {
 		i_fatal("Couldn't open mailbox '%s': %s", 
-			src_mailbox, mail_storage_get_last_error(src_storage, &error));
-    }
+			src_mailbox, mail_storage_get_last_error(src_ns->storage, &error));
+  }
 
 	/* Compose script environment */
 	memset(&scriptenv, 0, sizeof(scriptenv));
 	scriptenv.mailbox_autocreate = TRUE;
 	scriptenv.default_mailbox = dst_mailbox;
 	scriptenv.user = mail_user;
-	scriptenv.username = user;
+	scriptenv.username = sieve_tool_get_username(sieve_tool);
 	scriptenv.hostname = "host.example.com";
 	scriptenv.postmaster_address = "postmaster@example.com";
 	scriptenv.smtp_open = NULL;
@@ -429,24 +339,13 @@ int main(int argc, char **argv)
 	
 	/* Close the mailbox */
 	if ( src_box != NULL )
-		mailbox_close(&src_box);
-
-	/* De-initialize mail user objects */
-	if ( mail_user != NULL )
-		mail_user_unref(&mail_user);
-
-	if ( mail_user_dovecot != NULL )
-		mail_user_unref(&mail_user_dovecot);
-
-    /* Cleanup error handler */
-    sieve_error_handler_unref(&ehandler);
-    sieve_system_ehandler_reset();
+		mailbox_free(&src_box);
 
-    sieve_tool_deinit();
+	/* Cleanup error handler */
+	sieve_error_handler_unref(&ehandler);
+	sieve_system_ehandler_reset();
 
-    mail_storage_service_user_free(&service_user);
-    mail_storage_service_deinit(&storage_service);
-    master_service_deinit(&master_service);
+	sieve_tool_deinit(&sieve_tool);
 
 	return 0;
 }
diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index 2594d860269c748cd32c8ca20f21f9165aaada62..166f6ee46140b5a931f504b418917b7a2f57dc2f 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -18,7 +18,6 @@
 #include "sieve-binary.h"
 #include "sieve-extensions.h"
 
-#include "mail-raw.h"
 #include "sieve-tool.h"
 
 #include "sieve-ext-debug.h"
@@ -103,23 +102,11 @@ static void duplicate_mark
 
 int main(int argc, char **argv) 
 {
-	enum master_service_flags service_flags =
-		MASTER_SERVICE_FLAG_STANDALONE;
-	enum mail_storage_service_flags storage_service_flags =
-		MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR |
-		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
-	struct mail_storage_service_ctx *storage_service;
-	struct mail_storage_service_user *service_user;
-	struct mail_storage_service_input service_input;
-	struct mail_user *mail_user_dovecot = NULL;
+	struct sieve_instance *svinst;
 	ARRAY_TYPE (const_string) scriptfiles;
-	ARRAY_TYPE (const_string) plugins;
 	const char *scriptfile, *recipient, *sender, *mailbox, *dumpfile, *mailfile, 
-		*mailloc, *extensions, *username; 
-	const char *errstr;
-	struct mail_raw *mailr;
-	struct mail_namespace_settings ns_set;
-	struct mail_namespace *ns = NULL;
+		*mailloc; 
+	struct mail *mail;
 	struct sieve_binary *main_sbin, *sbin = NULL;
 	struct sieve_message_data msgdata;
 	struct sieve_script_env scriptenv;
@@ -127,21 +114,18 @@ int main(int argc, char **argv)
 	struct sieve_error_handler *ehandler;
 	struct ostream *teststream = NULL;
 	bool force_compile = FALSE, execute = FALSE;
-	bool debug = FALSE, trace = FALSE;
+	bool trace = FALSE;
 	int exit_status = EXIT_SUCCESS;
 	int ret, c;
 
-	master_service = master_service_init("sieve-test", 
-		service_flags, &argc, &argv, "r:f:m:d:l:x:s:P:eCtD");
+	sieve_tool = sieve_tool_init
+		("sieve-test", &argc, &argv, "r:f:m:d:l:s:eCtDP:x:u:", FALSE);
 
 	t_array_init(&scriptfiles, 16);
-	t_array_init(&plugins, 4);
 	
 	/* Parse arguments */
-	scriptfile = recipient = sender = mailbox = dumpfile = mailfile = mailloc = 
-		extensions = NULL;
-	username = getenv("USER");
-	while ((c = master_getopt(master_service)) > 0) {
+	scriptfile = recipient = sender = mailbox = dumpfile = mailfile = mailloc = NULL;
+	while ((c = sieve_tool_getopt(sieve_tool)) > 0) {
 		switch (c) {
 		case 'r':
 			/* destination address */
@@ -163,15 +147,6 @@ int main(int argc, char **argv)
 			/* mail location */
 			mailloc = optarg;
 			break;
-		case 'x':
-			/* extensions */
-			extensions = optarg;
-			break;
-		case 'u':
-			storage_service_flags |=
-				MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
-			username = optarg;
-			break;
 		case 's': 
 			/* scriptfile executed before main script */
 			{
@@ -181,15 +156,6 @@ int main(int argc, char **argv)
 				array_append(&scriptfiles, &file, 1);
 			}
 			break;
-		case 'P': 
-			/* Plugin */
-			{
-				const char *plugin;			
-
-				plugin = t_strdup(optarg);
-				array_append(&plugins, &plugin, 1);
-			}
-			break;
 		case 'e':
 			execute = TRUE;
 			break;
@@ -199,9 +165,6 @@ int main(int argc, char **argv)
 		case 't':
 			trace = TRUE;
 			break;
-		case 'D':
-			debug = TRUE;
-			break;
 		default:
 			print_help();
 			i_fatal_status(EX_USAGE, "Unknown argument: %c", c);
@@ -228,33 +191,11 @@ int main(int argc, char **argv)
 		i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
 	}
 
-	master_service_init_finish(master_service);
-
-	memset(&service_input, 0, sizeof(service_input));
-	service_input.module = "sieve-test";
-	service_input.service = "sieve-test";
-	service_input.username = username;
-
-	storage_service = mail_storage_service_init
-		(master_service, NULL, storage_service_flags);
-	if (mail_storage_service_lookup_next(storage_service, &service_input,
-					     &service_user, &mail_user_dovecot, &errstr) <= 0)
-		i_fatal("%s", errstr);
-
-	/* Initialize Sieve */
-
-	sieve_tool_init(NULL, (void *) mail_user_dovecot, debug);
-
-	if ( array_count(&plugins) > 0 ) {
-		sieve_tool_load_plugins(&plugins);
-	}
-
-	if ( extensions != NULL ) {
-		sieve_set_extensions(sieve_instance, extensions);
-	}
+	/* Finish tool initialization */
+	svinst = sieve_tool_init_finish(sieve_tool);
 
-	/* Register tool-specific extensions */
-	(void) sieve_extension_register(sieve_instance, &debug_extension, TRUE);
+	/* Register debug extension */
+	(void) sieve_extension_register(svinst, &debug_extension, TRUE);
 
 	/* Create error handler */
 	ehandler = sieve_stderr_ehandler_create(0);
@@ -263,67 +204,39 @@ int main(int argc, char **argv)
 
 	/* Compile main sieve script */
 	if ( force_compile ) {
-		main_sbin = sieve_tool_script_compile(scriptfile, NULL);
+		main_sbin = sieve_tool_script_compile(svinst, scriptfile, NULL);
 		if ( main_sbin != NULL )
 			(void) sieve_save(main_sbin, NULL);
 	} else {
-		main_sbin = sieve_tool_script_open(scriptfile);
+		main_sbin = sieve_tool_script_open(svinst, scriptfile);
 	}
 
 	if ( main_sbin == NULL ) {
 		exit_status = EXIT_FAILURE;
 	} else {
-		struct mail_user *mail_user = NULL;
-
 		/* Dump script */
 		sieve_tool_dump_binary_to(main_sbin, dumpfile);
 	
 		/* Obtain mail namespaces from -l argument */
 		if ( mailloc != NULL ) {
-			const char *home, *errstr;
-
-			mail_user = mail_user_alloc
-				(username, mail_user_dovecot->set_info, mail_user_dovecot->unexpanded_set);
-
-			if ( mail_user_get_home(mail_user_dovecot, &home) > 0 ||
-				(home=getenv("HOME")) != NULL ) {
-				mail_user_set_home(mail_user, home);
-			}
-
-			if ( mail_user_init(mail_user, &errstr) < 0 )
-        		i_fatal("Test user initialization failed: %s", errstr);
-
-			memset(&ns_set, 0, sizeof(ns_set));
-			ns_set.location = mailloc;
-
-			ns = mail_namespaces_init_empty(mail_user);
-			ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
-			ns->set = &ns_set;
-
-			if ( mail_storage_create(ns, NULL, 0, &errstr) < 0 )
-		        i_fatal("Test storage creation failed: %s", errstr);
+			sieve_tool_init_mail_user(sieve_tool, mailloc);
 		}
 
-		if ( master_service_set
-			(master_service, "mail_full_filesystem_access=yes") < 0 )
-			i_unreached(); 
-
 		/* Initialize raw mail object */
-		mail_raw_init(master_service, username, mail_user_dovecot);
-		mailr = mail_raw_open_file(mailfile);
+		mail = sieve_tool_open_file_as_mail(sieve_tool, mailfile);
 
-		sieve_tool_get_envelope_data(mailr->mail, &recipient, &sender);
+		sieve_tool_get_envelope_data(mail, &recipient, &sender);
 
 		if ( mailbox == NULL )
 			mailbox = "INBOX";
 
 		/* Collect necessary message data */
 		memset(&msgdata, 0, sizeof(msgdata));
-		msgdata.mail = mailr->mail;
+		msgdata.mail = mail;
 		msgdata.return_path = sender;
 		msgdata.to_address = recipient;
-		msgdata.auth_user = username;
-		(void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id);
+		msgdata.auth_user = sieve_tool_get_username(sieve_tool);
+		(void)mail_get_first_header(mail, "Message-ID", &msgdata.id);
 
 		/* Create stream for test and trace output */
 		if ( !execute || trace )
@@ -332,8 +245,8 @@ int main(int argc, char **argv)
 		/* Compose script environment */
 		memset(&scriptenv, 0, sizeof(scriptenv));
 		scriptenv.default_mailbox = "INBOX";
-		scriptenv.user = mail_user == NULL ? mail_user_dovecot : mail_user;
-		scriptenv.username = username;
+		scriptenv.user = sieve_tool_get_mail_user(sieve_tool);
+		scriptenv.username = sieve_tool_get_username(sieve_tool);
 		scriptenv.hostname = "host.example.com";
 		scriptenv.postmaster_address = "postmaster@example.com";
 		scriptenv.smtp_open = sieve_smtp_open;
@@ -368,10 +281,10 @@ int main(int argc, char **argv)
 
 			if ( execute )
 				mscript = sieve_multiscript_start_execute
-					(sieve_instance, &msgdata, &scriptenv);
+					(svinst, &msgdata, &scriptenv);
 			else
 				mscript = sieve_multiscript_start_test
-					(sieve_instance, &msgdata, &scriptenv, teststream);
+					(svinst, &msgdata, &scriptenv, teststream);
 		
 			/* Execute scripts sequentially */
 			sfiles = array_get(&scriptfiles, &count); 
@@ -386,11 +299,11 @@ int main(int argc, char **argv)
 		
 				/* Compile sieve script */
 				if ( force_compile ) {
-					sbin = sieve_tool_script_compile(sfiles[i], sfiles[i]);
+					sbin = sieve_tool_script_compile(svinst, sfiles[i], sfiles[i]);
 					if ( sbin != NULL )
 						(void) sieve_save(sbin, NULL);
 				} else {
-					sbin = sieve_tool_script_open(sfiles[i]);
+					sbin = sieve_tool_script_open(svinst, sfiles[i]);
 				}
 			
 				if ( sbin == NULL ) {
@@ -440,8 +353,9 @@ int main(int argc, char **argv)
 			exit_status = EXIT_FAILURE;
 			break;
 		default:
-			exit_status = EXIT_FAILURE;
 			i_info("final result: unrecognized return value?!");	
+			exit_status = EXIT_FAILURE;
+			break;
 		}
 
 		if ( teststream != NULL )
@@ -452,28 +366,13 @@ int main(int argc, char **argv)
 			sieve_close(&sbin);
 		if ( main_sbin != NULL ) 
 			sieve_close(&main_sbin);
-		
-		/* De-initialize raw mail object */
-		mail_raw_close(mailr);
-		mail_raw_deinit();
-
-		/* De-initialize mail user objects */
-		if ( mail_user != NULL )
-			mail_user_unref(&mail_user);
 	}
 	
 	/* Cleanup error handler */
 	sieve_error_handler_unref(&ehandler);
 	sieve_system_ehandler_reset();
 
-	sieve_tool_deinit();
-
-	if ( mail_user_dovecot != NULL )
-		mail_user_unref(&mail_user_dovecot);
-
-	mail_storage_service_user_free(&service_user);
-	mail_storage_service_deinit(&storage_service);
-	master_service_deinit(&master_service);
+	sieve_tool_deinit(&sieve_tool);
 	
 	return exit_status;
 }
diff --git a/src/sieve-tools/sievec.c b/src/sieve-tools/sievec.c
index 88419b438c8f7bb4b4fe973949e7adea89e6100c..7fce62c8b74ca46acd7d5a99dd12b7976690a57f 100644
--- a/src/sieve-tools/sievec.c
+++ b/src/sieve-tools/sievec.c
@@ -43,50 +43,23 @@ static void print_help(void)
 
 int main(int argc, char **argv) 
 {
-	enum master_service_flags service_flags =
-		MASTER_SERVICE_FLAG_STANDALONE;
-	enum mail_storage_service_flags storage_service_flags =
-		MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR |
-		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
-	struct mail_storage_service_ctx *storage_service;
-	struct mail_storage_service_user *service_user;
-	struct mail_storage_service_input service_input;
-	struct mail_user *mail_user_dovecot = NULL;
-	ARRAY_TYPE(const_string) plugins;
+	struct sieve_instance *svinst;
 	struct stat st;
 	struct sieve_binary *sbin;
 	bool dump = FALSE;
-	const char *scriptfile, *outfile, *extensions, *username;
-	const char *errstr;
+	const char *scriptfile, *outfile;
 	int exit_status = EXIT_SUCCESS;
 	int c;
 		
-	master_service = master_service_init("sievec", 
-		service_flags, &argc, &argv, "dx:P:");
-
-	t_array_init(&plugins, 4);	
+	sieve_tool = sieve_tool_init("sievec", &argc, &argv, "dP:x:u:", FALSE);
 		
-	scriptfile = outfile = extensions = NULL;
-	username = getenv("USER");
-	while ((c = master_getopt(master_service)) > 0) {
+	scriptfile = outfile = NULL;
+	while ((c = sieve_tool_getopt(sieve_tool)) > 0) {
 		switch (c) {
 		case 'd':
 			/* dump file */
 			dump = TRUE;
 			break;
-		case 'x':
-			/* extensions */
-			extensions = optarg;
-			break;
-		case 'P': 
-			/* Plugin */
-			{
-				const char *plugin;			
-
-				plugin = t_strdup(optarg);
-				array_append(&plugins, &plugin, 1);
-			}
-			break;
 		default:
 			print_help();
 			i_fatal_status(EX_USAGE, "Unknown argument: %c", c);
@@ -107,33 +80,10 @@ int main(int argc, char **argv)
 		outfile = "-";
 	}
 
-	master_service_init_finish(master_service);
-
-	memset(&service_input, 0, sizeof(service_input));
-	service_input.module = "sievec";
-	service_input.service = "sievec";
-	service_input.username = username;
-
-	storage_service = mail_storage_service_init
-		(master_service, NULL, storage_service_flags);
-	if (mail_storage_service_lookup_next(storage_service, &service_input,
-					     &service_user, &mail_user_dovecot, &errstr) <= 0)
-		i_fatal("%s", errstr);
-
-	/* Initialize Sieve */
+	svinst = sieve_tool_init_finish(sieve_tool);
 
-	sieve_tool_init(NULL, (void *) mail_user_dovecot, FALSE);
-
-	if ( array_count(&plugins) > 0 ) {
-		sieve_tool_load_plugins(&plugins);
-	}
-
-	if ( extensions != NULL ) {
-		sieve_set_extensions(sieve_instance, extensions);
-	}
-
-	/* Register tool-specific extensions */
-	(void) sieve_extension_register(sieve_instance, &debug_extension, TRUE);
+	/* Register debug extension */
+	(void) sieve_extension_register(svinst, &debug_extension, TRUE);
 
 	if ( stat(scriptfile, &st) == 0 && S_ISDIR(st.st_mode) ) {
 		/* Script directory */
@@ -172,7 +122,7 @@ int main(int argc, char **argv)
 				else
 					file = t_strconcat(scriptfile, "/", dp->d_name, NULL);
 
-				sbin = sieve_tool_script_compile(file, dp->d_name);
+				sbin = sieve_tool_script_compile(svinst, file, dp->d_name);
 
 				if ( sbin != NULL ) {
 					sieve_save(sbin, NULL);		
@@ -189,7 +139,7 @@ int main(int argc, char **argv)
 		 * 
 		 *   NOTE: For consistency, stat errors are handled here as well 
 		 */	
-		sbin = sieve_tool_script_compile(scriptfile, NULL);
+		sbin = sieve_tool_script_compile(svinst, scriptfile, NULL);
 
 		if ( sbin != NULL ) {
 			if ( dump ) 
@@ -204,14 +154,7 @@ int main(int argc, char **argv)
 		}
 	}
 		
-	sieve_tool_deinit();
-
-	if ( mail_user_dovecot != NULL )
-		mail_user_unref(&mail_user_dovecot);
-
-	mail_storage_service_user_free(&service_user);
-	mail_storage_service_deinit(&storage_service);
-	master_service_deinit(&master_service);
+	sieve_tool_deinit(&sieve_tool);
 
 	return exit_status;
 }
diff --git a/src/sieve-tools/sieved.c b/src/sieve-tools/sieved.c
index 81753ca598ec6268e48c46af477264226da763a7..61747cbc18c39df18022ad67bb65cdd651175b11 100644
--- a/src/sieve-tools/sieved.c
+++ b/src/sieve-tools/sieved.c
@@ -41,49 +41,19 @@ static void print_help(void)
 
 int main(int argc, char **argv) 
 {
-	enum master_service_flags service_flags =
-		MASTER_SERVICE_FLAG_STANDALONE;
-	enum mail_storage_service_flags storage_service_flags =
-		MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR |
-		MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
-	struct mail_storage_service_ctx *storage_service;
-	struct mail_storage_service_user *service_user;
-	struct mail_storage_service_input service_input;
-	struct mail_user *mail_user_dovecot = NULL;
-	ARRAY_TYPE(const_string) plugins;
+	struct sieve_instance *svinst;
 	struct sieve_binary *sbin;
-	const char *binfile, *outfile, *extensions, *username;
-	const char *errstr;
+	const char *binfile, *outfile;
 	int exit_status = EXIT_SUCCESS;
 	int c;
 
-	master_service = master_service_init("sieved", 
-		service_flags, &argc, &argv, "x:P:");
-	
-	t_array_init(&plugins, 4);
-	
-	binfile = outfile = extensions = NULL;
-	username = getenv("USER");
-	while ((c = master_getopt(master_service)) > 0) {
-		switch (c) {
-		case 'x':
-			/* extensions */
-			extensions = optarg;
-			break;
-		case 'P': 
-			/* Plugin */
-			{
-				const char *plugin;			
-
-				plugin = t_strdup(optarg);
-				array_append(&plugins, &plugin, 1);
-			}
-			break;
-		default:
-			print_help();
-			i_fatal_status(EX_USAGE, "Unknown argument: %c", c);
-			break;
-		}
+	sieve_tool = sieve_tool_init("sieved", &argc, &argv, "P:x:", FALSE);
+		
+	binfile = outfile = NULL;
+
+	if ( (c = sieve_tool_getopt(sieve_tool)) > 0 ) {
+		print_help();
+		i_fatal_status(EX_USAGE, "Unknown argument: %c", c);
 	}
 
 	if ( optind < argc ) {
@@ -97,38 +67,14 @@ int main(int argc, char **argv)
 		outfile = argv[optind++];
 	} 
 	
-	/* Initialize Service */
-
-	master_service_init_finish(master_service);
-
-	memset(&service_input, 0, sizeof(service_input));
-	service_input.module = "sieved";
-	service_input.service = "sieved";
-	service_input.username = username;
-
-	storage_service = mail_storage_service_init
-		(master_service, NULL, storage_service_flags);
-	if (mail_storage_service_lookup_next(storage_service, &service_input,
-					     &service_user, &mail_user_dovecot, &errstr) <= 0)
-		i_fatal("%s", errstr);
-
-	/* Initialize Sieve */
+	/* Finish tool initialization */
+	svinst = sieve_tool_init_finish(sieve_tool);
 
-	sieve_tool_init(NULL, (void *) mail_user_dovecot, FALSE);
-
-	if ( array_count(&plugins) > 0 ) {
-		sieve_tool_load_plugins(&plugins);
-	}
-
-	if ( extensions != NULL ) {
-		sieve_set_extensions(sieve_instance, extensions);
-	}
-
-	/* Register tool-specific extensions */
-	(void) sieve_extension_register(sieve_instance, &debug_extension, TRUE);
+	/* Register debug extension */
+	(void) sieve_extension_register(svinst, &debug_extension, TRUE);
 		
-	sbin = sieve_load(sieve_instance, binfile);
-
+	/* Dump binary */
+	sbin = sieve_load(svinst, binfile);
 	if ( sbin != NULL ) {
 		sieve_tool_dump_binary_to(sbin, outfile == NULL ? "-" : outfile);
 	
@@ -138,14 +84,7 @@ int main(int argc, char **argv)
 		exit_status = EXIT_FAILURE;
 	}
 
-	sieve_tool_deinit();
-
-	if ( mail_user_dovecot != NULL )
-		mail_user_unref(&mail_user_dovecot);
-
-	mail_storage_service_user_free(&service_user);
-	mail_storage_service_deinit(&storage_service);
-	master_service_deinit(&master_service);
+	sieve_tool_deinit(&sieve_tool);
 
 	return exit_status;
 }
diff --git a/src/testsuite/testsuite-binary.c b/src/testsuite/testsuite-binary.c
index c635a2946a6f40af0f419de80f5d0052501ea26a..11485a8cfc69bddad8badbeb04c376d858093445 100644
--- a/src/testsuite/testsuite-binary.c
+++ b/src/testsuite/testsuite-binary.c
@@ -67,7 +67,9 @@ bool testsuite_binary_save(struct sieve_binary *sbin, const char *name)
 
 struct sieve_binary *testsuite_binary_load(const char *name)
 {
-	return sieve_load(sieve_instance, 
+	struct sieve_instance *svinst = testsuite_sieve_instance;
+
+	return sieve_load(svinst, 
 		t_strdup_printf("%s/%s.svbin", testsuite_binary_tmp, name));
 }
 
diff --git a/src/testsuite/testsuite-common.c b/src/testsuite/testsuite-common.c
index c23c80a2cc54158d88627e2663138c0bee4eecc3..657b764bdbf74f05892cea8beeb65a57abc59ee6 100644
--- a/src/testsuite/testsuite-common.c
+++ b/src/testsuite/testsuite-common.c
@@ -44,11 +44,13 @@
  * Global data
  */
 
+struct sieve_instance *testsuite_sieve_instance = NULL;
+
 /* Test context */
 
 static string_t *test_name;
-unsigned int test_index;
-unsigned int test_failures;
+static unsigned int test_index;
+static unsigned int test_failures;
 
 /* Extension */
 
@@ -234,6 +236,8 @@ const char *testsuite_tmp_dir_get(void)
 
 void testsuite_init(struct sieve_instance *svinst, bool log_stdout)
 {
+	testsuite_sieve_instance = svinst;
+
 	testsuite_test_context_init();
 	testsuite_log_init(log_stdout);
 	testsuite_tmp_dir_init();
diff --git a/src/testsuite/testsuite-common.h b/src/testsuite/testsuite-common.h
index a336de73c32de15964e9ba0bf4d5ba662090ab14..72b43f8a3c188c7a7ada3e704e2b84f4512c0dcb 100644
--- a/src/testsuite/testsuite-common.h
+++ b/src/testsuite/testsuite-common.h
@@ -9,10 +9,10 @@
 #include "sieve-tool.h"
 
 /*
- * Extension
+ * Global data
  */
 
-/* Extension */
+extern struct sieve_instance *testsuite_sieve_instance;
 
 extern const struct sieve_extension_def testsuite_extension;
 
@@ -20,6 +20,7 @@ extern const struct sieve_extension *testsuite_ext;
 
 extern const struct sieve_script_env *testsuite_scriptenv;
 
+
 /* 
  * Validator context 
  */
diff --git a/src/testsuite/testsuite-mailstore.c b/src/testsuite/testsuite-mailstore.c
index ca5b95512eb529f4eec66d164403b6a3e70ca5d4..c95a844260cd9b3114fdbd222e41cac006badf8c 100644
--- a/src/testsuite/testsuite-mailstore.c
+++ b/src/testsuite/testsuite-mailstore.c
@@ -35,7 +35,6 @@ static void testsuite_mailstore_close(void);
  */
 
 static char *testsuite_mailstore_tmp = NULL;
-static struct mail_user *testsuite_mailstore_user = NULL;
 
 static char *testsuite_mailstore_folder = NULL;
 static struct mailbox *testsuite_mailstore_box = NULL;
@@ -46,14 +45,8 @@ static struct mail *testsuite_mailstore_mail = NULL;
  * Initialization
  */
 
-void testsuite_mailstore_init
-(const char *user, const char *home, struct mail_user *service_user)
+void testsuite_mailstore_init(void)
 {	
-	struct mail_namespace_settings ns_set;
-	struct mail_namespace *ns = NULL;
-	struct mail_user *mail_user;
-	const char *errstr;
-
 	testsuite_mailstore_tmp = i_strconcat
 		(testsuite_tmp_dir_get(), "/mailstore", NULL);
 
@@ -62,37 +55,14 @@ void testsuite_mailstore_init
 			testsuite_mailstore_tmp);		
 	}
 
-	mail_user = mail_user_alloc
-		(user, service_user->set_info, service_user->unexpanded_set);
-	mail_user_set_home(mail_user, home);
-
-	if ( mail_user_init(mail_user, &errstr) < 0 )
-		i_fatal("Test user initialization failed: %s", errstr);
-
-	memset(&ns_set, 0, sizeof(ns_set));
-	ns_set.location = t_strconcat("maildir:", testsuite_mailstore_tmp, NULL);
-	ns_set.inbox = TRUE;
-	ns_set.separator = ".";
-	ns_set.subscriptions = TRUE;
-
-	ns = mail_namespaces_init_empty(mail_user);
-	ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
-	ns->set = &ns_set;
-
-	if ( mail_storage_create(ns, NULL, 0, &errstr) < 0 )
-        i_fatal("Test storage creation failed: %s", errstr);
-
-	testsuite_mailstore_user = mail_user;
+	sieve_tool_init_mail_user
+		(sieve_tool, t_strconcat("maildir:", testsuite_mailstore_tmp, NULL));
 }
 
 void testsuite_mailstore_deinit(void)
 {
 	testsuite_mailstore_close();
 
-	/* De-initialize mail user object */
-	if ( testsuite_mailstore_user != NULL )
-		mail_user_unref(&testsuite_mailstore_user);
-
 	if ( unlink_directory(testsuite_mailstore_tmp, TRUE) < 0 ) {
 		i_warning("failed to remove temporary directory '%s': %m.",
 			testsuite_mailstore_tmp);
@@ -109,15 +79,11 @@ void testsuite_mailstore_reset(void)
  * Mailbox Access
  */
 
-struct mail_user *testsuite_mailstore_get_user(void)
-{
-	return testsuite_mailstore_user;
-}
-
 bool testsuite_mailstore_mailbox_create
 (const struct sieve_runtime_env *renv ATTR_UNUSED, const char *folder)
 {
-	struct mail_namespace *ns = testsuite_mailstore_user->namespaces;
+	struct mail_user *mail_user = sieve_tool_get_mail_user(sieve_tool);
+	struct mail_namespace *ns = mail_user->namespaces;
 	struct mailbox *box;
 
 	box = mailbox_alloc(ns->list, folder, 0);
@@ -152,7 +118,8 @@ static struct mail *testsuite_mailstore_open(const char *folder)
 	enum mailbox_flags flags =
 		MAILBOX_FLAG_KEEP_RECENT | MAILBOX_FLAG_SAVEONLY |
 		MAILBOX_FLAG_POST_SESSION;
-	struct mail_namespace *ns = testsuite_mailstore_user->namespaces;
+	struct mail_user *mail_user = sieve_tool_get_mail_user(sieve_tool);
+	struct mail_namespace *ns = mail_user->namespaces;
 	struct mailbox *box;
 	struct mailbox_transaction_context *t;
 
diff --git a/src/testsuite/testsuite-mailstore.h b/src/testsuite/testsuite-mailstore.h
index 132cdd38712bde30f3cf63d719e1716cdf51202d..a4b3b7a1c5d1c6009620f2f8fdc99d44c5db1354 100644
--- a/src/testsuite/testsuite-mailstore.h
+++ b/src/testsuite/testsuite-mailstore.h
@@ -13,16 +13,10 @@
  * Initialization
  */
 
-void testsuite_mailstore_init
-	(const char *user, const char *home, struct mail_user *service_user);
+void testsuite_mailstore_init(void);
 void testsuite_mailstore_deinit(void);
 void testsuite_mailstore_reset(void);
 
-/* 
- * User
- */
-
-struct mail_user *testsuite_mailstore_get_user(void);
 
 /*
  * Mailbox Access
diff --git a/src/testsuite/testsuite-message.c b/src/testsuite/testsuite-message.c
index a4e30abd78fbe9e8af1bb45d3fae9cdcd602e58b..e505aed9a3ae5f76c3f2d6f0a37c391f852c200a 100644
--- a/src/testsuite/testsuite-message.c
+++ b/src/testsuite/testsuite-message.c
@@ -7,12 +7,12 @@
 #include "mail-storage.h"
 #include "master-service.h"
 
-#include "mail-raw.h"
-
 #include "sieve-common.h"
 #include "sieve-message.h"
 #include "sieve-interpreter.h"
 
+#include "sieve-tool.h"
+
 #include "testsuite-common.h"
 #include "testsuite-message.h"
 
@@ -22,8 +22,7 @@
  
 struct sieve_message_data testsuite_msgdata;
 
-static const char *testsuite_user;
-static struct mail_raw *_raw_message;
+static struct mail *testsuite_mail;
 
 static const char *_default_message_data = 
 "From: stephan@rename-it.nl\n"
@@ -38,7 +37,7 @@ static string_t *envelope_auth;
 
 pool_t message_pool;
 
-static void _testsuite_message_set_data(struct mail *mail)
+static void testsuite_message_set_data(struct mail *mail)
 {
 	const char *recipient = NULL, *sender = NULL;
 	
@@ -64,25 +63,22 @@ static void _testsuite_message_set_data(struct mail *mail)
 
 	memset(&testsuite_msgdata, 0, sizeof(testsuite_msgdata));	
 	testsuite_msgdata.mail = mail;
-	testsuite_msgdata.auth_user = testsuite_user;
+	testsuite_msgdata.auth_user = sieve_tool_get_username(sieve_tool);
 	testsuite_msgdata.return_path = sender;
 	testsuite_msgdata.to_address = recipient;
 
 	(void)mail_get_first_header(mail, "Message-ID", &testsuite_msgdata.id);
 }
 
-void testsuite_message_init
-(struct master_service *service, const char *user, struct mail_user *mail_user)
+void testsuite_message_init(void)
 {		
 	message_pool = pool_alloconly_create("testsuite_message", 6096);
 
 	string_t *default_message = str_new(message_pool, 1024);
 	str_append(default_message, _default_message_data);
 
-	testsuite_user = user;
-	mail_raw_init(service, user, mail_user);
-	_raw_message = mail_raw_open_data(default_message);
-	_testsuite_message_set_data(_raw_message->mail);
+	testsuite_mail = sieve_tool_open_data_as_mail(sieve_tool, default_message);
+	testsuite_message_set_data(testsuite_mail);
 
 	envelope_to = str_new(message_pool, 256);
 	envelope_from = str_new(message_pool, 256);
@@ -92,39 +88,17 @@ void testsuite_message_init
 void testsuite_message_set_string
 (const struct sieve_runtime_env *renv, string_t *message)
 {
-	mail_raw_close(_raw_message);
-
-	_raw_message = mail_raw_open_data(message);
-
-	_testsuite_message_set_data(_raw_message->mail);
+	testsuite_mail = sieve_tool_open_data_as_mail(sieve_tool, message);
+	testsuite_message_set_data(testsuite_mail);
 
 	sieve_message_context_flush(renv->msgctx);
-
-	/*{ 
-		const unsigned char *data;
-		struct istream *input;
-		size_t size;
-		int ret;
-
-		if (mail_get_stream(_raw_message->mail, NULL, NULL, &input) < 0)
-        	return;
-
-		while ((ret = i_stream_read_data(input, &data, &size, 0)) > 0) {
-			if (write(1, data, size) == 0)
-				break;
-			i_stream_skip(input, size);
-		}
-    }*/
 }
 
 void testsuite_message_set_file
 (const struct sieve_runtime_env *renv, const char *file_path)
 {
-	mail_raw_close(_raw_message);
-	 
-	_raw_message = mail_raw_open_file(file_path);
-
-	_testsuite_message_set_data(_raw_message->mail);
+	testsuite_mail = sieve_tool_open_file_as_mail(sieve_tool, file_path);
+	testsuite_message_set_data(testsuite_mail);
 
 	sieve_message_context_flush(renv->msgctx);
 }
@@ -132,16 +106,13 @@ void testsuite_message_set_file
 void testsuite_message_set_mail
 (const struct sieve_runtime_env *renv, struct mail *mail)
 {
-	_testsuite_message_set_data(mail);
+	testsuite_message_set_data(mail);
 
 	sieve_message_context_flush(renv->msgctx);
 }
 	
 void testsuite_message_deinit(void)
 {
-	mail_raw_close(_raw_message);
-	mail_raw_deinit();
-
 	pool_unref(&message_pool);
 }
 
diff --git a/src/testsuite/testsuite-message.h b/src/testsuite/testsuite-message.h
index 1ff0abaed57dea75e8b26d97ac69ab2c40bb2dcc..0cad24a142b13ef86dc70057a76ffb26d772649e 100644
--- a/src/testsuite/testsuite-message.h
+++ b/src/testsuite/testsuite-message.h
@@ -8,11 +8,11 @@
 #include "master-service.h"
 
 #include "sieve-common.h"
+#include "sieve-tool.h"
 
 extern struct sieve_message_data testsuite_msgdata;
 
-void testsuite_message_init
-(struct master_service *service, const char *user, struct mail_user *mail_user);
+void testsuite_message_init(void);
 void testsuite_message_deinit(void);
 
 void testsuite_message_set_string
diff --git a/src/testsuite/testsuite-result.c b/src/testsuite/testsuite-result.c
index 3caa2c77b7e64bc4b87dfa5ffb895409bd8427f7..df38ceb5739a167553e756032b5905b8c6a4a2d0 100644
--- a/src/testsuite/testsuite-result.c
+++ b/src/testsuite/testsuite-result.c
@@ -20,9 +20,10 @@ static struct sieve_result *_testsuite_result;
 
 void testsuite_result_init(void)
 {
+	struct sieve_instance *svinst = testsuite_sieve_instance;
+
 	_testsuite_result = sieve_result_create
-		(sieve_instance, &testsuite_msgdata, testsuite_scriptenv, 
-			testsuite_log_ehandler);
+		(svinst, &testsuite_msgdata, testsuite_scriptenv, testsuite_log_ehandler);
 }
 
 void testsuite_result_deinit(void)
@@ -35,13 +36,14 @@ void testsuite_result_deinit(void)
 void testsuite_result_reset
 (const struct sieve_runtime_env *renv)
 {
+	struct sieve_instance *svinst = testsuite_sieve_instance;
+
 	if ( _testsuite_result != NULL ) {
 		sieve_result_unref(&_testsuite_result);
 	}
 
 	_testsuite_result = sieve_result_create
-		(sieve_instance, &testsuite_msgdata, testsuite_scriptenv, 
-		testsuite_log_ehandler);
+		(svinst, &testsuite_msgdata, testsuite_scriptenv, testsuite_log_ehandler);
 	sieve_interpreter_set_result(renv->interp, _testsuite_result);
 }
 
diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c
index ddd1f71683142b7585963c705381a13489a40c82..302734ae1ef9c9fdd5c8c7ef1e391b6eff6c6581 100644
--- a/src/testsuite/testsuite-script.c
+++ b/src/testsuite/testsuite-script.c
@@ -37,6 +37,7 @@ void testsuite_script_deinit(void)
 
 static struct sieve_binary *_testsuite_script_compile(const char *script_path)
 {
+	struct sieve_instance *svinst = testsuite_sieve_instance;
 	struct sieve_binary *sbin;
 	const char *sieve_dir;
 
@@ -53,8 +54,8 @@ static struct sieve_binary *_testsuite_script_compile(const char *script_path)
 	testsuite_setting_set
 		("sieve_global_dir", t_strconcat(sieve_dir, "included-global", NULL));
 	
-	if ( (sbin = sieve_compile
-		(sieve_instance, script_path, NULL, testsuite_log_ehandler)) == NULL )
+	if ( (sbin = sieve_compile(svinst, script_path, NULL, testsuite_log_ehandler)) 
+		== NULL )
 		return NULL;
 
 	return sbin;
@@ -145,6 +146,7 @@ void testsuite_script_set_binary(struct sieve_binary *sbin)
 bool testsuite_script_multiscript
 (const struct sieve_runtime_env *renv, ARRAY_TYPE (const_string) *scriptfiles)
 {
+	struct sieve_instance *svinst = testsuite_sieve_instance;
 	struct sieve_script_env scriptenv;
 	struct sieve_multiscript *mscript;
 	const char *const *scripts;
@@ -169,8 +171,7 @@ bool testsuite_script_multiscript
 
 	/* Start execution */
 
-	mscript = sieve_multiscript_start_execute
-		(sieve_instance, renv->msgdata, &scriptenv);
+	mscript = sieve_multiscript_start_execute(svinst, renv->msgdata, &scriptenv);
 
 	/* Execute scripts before main script */
 
diff --git a/src/testsuite/testsuite-settings.c b/src/testsuite/testsuite-settings.c
index c44ade6ec0dd5fefd0d5ac1ae4886a8bfb043b2e..5ac622db4dd891fc5fb63ffdf4601de21c14e4fa 100644
--- a/src/testsuite/testsuite-settings.c
+++ b/src/testsuite/testsuite-settings.c
@@ -18,10 +18,15 @@ struct testsuite_setting {
 
 static struct hash_table *settings; 
 
+static const char *testsuite_setting_get
+	(void *context, const char *identifier);
+
 void testsuite_settings_init(void)
 {
 	settings = hash_table_create
 		(default_pool, default_pool, 0, str_hash, (hash_cmp_callback_t *)strcmp);
+
+	sieve_tool_set_setting_callback(sieve_tool, testsuite_setting_get, NULL);
 }
 
 void testsuite_settings_deinit(void)
@@ -44,7 +49,7 @@ void testsuite_settings_deinit(void)
 	hash_table_destroy(&settings);
 }
 
-const char *testsuite_setting_get
+static const char *testsuite_setting_get
 (void *context ATTR_UNUSED, const char *identifier)
 {
 	struct testsuite_setting *setting = (struct testsuite_setting *) 
diff --git a/src/testsuite/testsuite-settings.h b/src/testsuite/testsuite-settings.h
index badf95bad80722050c76f5576f476d26b33a3873..c10a95305b4996d5721050afc8ca7ea08704f7e2 100644
--- a/src/testsuite/testsuite-settings.h
+++ b/src/testsuite/testsuite-settings.h
@@ -9,7 +9,6 @@
 void testsuite_settings_init(void);
 void testsuite_settings_deinit(void);
 
-const char *testsuite_setting_get(void *context, const char *identifier);
 void testsuite_setting_set(const char *identifier, const char *value);
 void testsuite_setting_unset(const char *identifier);
 
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index fce289d5ed4d287b80a502351d998105679316ed..a1b23f04b3f482c024ebf87323d1c55974ee9196 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -7,11 +7,7 @@
 #include "env-util.h"
 #include "ostream.h"
 #include "hostpid.h"
-#include "mail-storage.h"
-#include "mail-namespace.h"
-#include "master-service.h"
-#include "master-service-settings.h"
-#include "mail-storage-service.h"
+#include "abspath.h"
 
 #include "sieve.h"
 #include "sieve-extensions.h"
@@ -20,7 +16,6 @@
 #include "sieve-result.h"
 #include "sieve-interpreter.h"
 
-#include "mail-raw.h"
 #include "sieve-tool.h"
 
 #include "testsuite-common.h"
@@ -46,15 +41,6 @@ const struct sieve_script_env *testsuite_scriptenv;
 #define DEFAULT_SENDMAIL_PATH "/usr/lib/sendmail"
 #define DEFAULT_ENVELOPE_SENDER "MAILER-DAEMON"
 
-/*
- * Testsuite Sieve environment
- */
-
-static const struct sieve_environment testsuite_sieve_env = {
-	sieve_tool_get_homedir,
-	testsuite_setting_get
-};
-
 /*
  * Testsuite execution
  */
@@ -92,70 +78,33 @@ static int testsuite_run
 	return ret;
 }
 
-/* IEW.. YUCK.. and so forth.. */
-static const char *_get_cwd(void)
-{
-	static char cwd[PATH_MAX];
-	const char *result;
-
-	result = t_strdup(getcwd(cwd, sizeof(cwd)));
-
-	return result;
-}
-
 int main(int argc, char **argv) 
 {
-	enum mail_storage_service_flags service_flags = 0;
-	struct mail_storage_service_ctx *storage_service;
-	struct mail_storage_service_user *service_user;
-	struct mail_storage_service_input service_input;
-	struct mail_user *mail_user_dovecot;
-	const char *scriptfile, *dumpfile, *extensions; 
-	const char *user, *home, *errstr;
-	ARRAY_TYPE(const_string) plugins;
+	struct sieve_instance *svinst;
+	const char *scriptfile, *dumpfile; 
 	struct sieve_binary *sbin;
 	const char *sieve_dir;
-	bool trace = FALSE, log_stdout = FALSE, debug = FALSE;
+	bool trace = FALSE, log_stdout = FALSE;
 	int ret, c;
 
-	master_service = master_service_init
-		("testsuite", MASTER_SERVICE_FLAG_STANDALONE, &argc, &argv, "d:x:P:tED");
-
-	user = getenv("USER");
-
-	t_array_init(&plugins, 4);
+	sieve_tool = sieve_tool_init
+		("testsuite", &argc, &argv, "d:tEP:", TRUE);
 
 	/* Parse arguments */
-	scriptfile = dumpfile = extensions = NULL;
+	scriptfile = dumpfile = NULL;
 
-	while ((c = master_getopt(master_service)) > 0) {
+	while ((c = sieve_tool_getopt(sieve_tool)) > 0) {
 		switch (c) {
 		case 'd':
 			/* destination address */
 			dumpfile = optarg;
 			break;
-		case 'x':
-			/* destination address */
-			extensions = optarg;
-			break;
-		case 'P':
-			/* Plugin */
-			{
-				const char *plugin;
-
-				plugin = t_strdup(optarg);
-				array_append(&plugins, &plugin, 1);
-			}
-			break;
 		case 't':
 			trace = TRUE;
 			break;
 		case 'E':
 			log_stdout = TRUE;
 			break;
-		case 'D':
-			debug = TRUE;
-			break;
 		default:
 			print_help();
 			i_fatal_status(EX_USAGE,
@@ -177,34 +126,13 @@ int main(int argc, char **argv)
 	}
 
 	/* Initialize mail user */
-	home = _get_cwd();
-	user = sieve_tool_get_user();
-
-	env_put("DOVECONF_ENV=1");
-	env_put(t_strdup_printf("HOME=%s", home));
-	env_put(t_strdup_printf("MAIL=maildir:/tmp/dovecot-test-%s", user));
-
-	master_service_init_finish(master_service);
-
-	memset(&service_input, 0, sizeof(service_input));
-	service_input.module = "testsuite";
-	service_input.service = "testsuite";
-	service_input.username = user;
+	sieve_tool_set_homedir(sieve_tool, t_abspath(""));
 
-	storage_service = mail_storage_service_init
-		(master_service, NULL, service_flags);
-	if ( mail_storage_service_lookup_next(storage_service, &service_input,
-		&service_user, &mail_user_dovecot, &errstr) <= 0 )
-		i_fatal("%s", errstr);
-
-	/* Initialize testsuite */
+	svinst = sieve_tool_init_finish(sieve_tool);
+	
+	testsuite_init(svinst, log_stdout);
 	testsuite_settings_init();
 
-	sieve_tool_init(&testsuite_sieve_env, NULL, debug);
-	sieve_tool_load_plugins(&plugins);
-	sieve_extensions_set_string(sieve_instance, extensions);
-	testsuite_init(sieve_instance, log_stdout);
-
 	printf("Test case: %s:\n\n", scriptfile);
 
 	/* Initialize environment */
@@ -223,27 +151,22 @@ int main(int argc, char **argv)
 		("sieve_global_dir", t_strconcat(sieve_dir, "included-global", NULL));
 
 	/* Compile sieve script */
-	if ( (sbin = sieve_tool_script_compile(scriptfile, NULL)) != NULL ) {
+	if ( (sbin = sieve_tool_script_compile(svinst, scriptfile, NULL)) != NULL ) {
 		struct sieve_error_handler *ehandler;
 		struct sieve_script_env scriptenv;
 
 		/* Dump script */
 		sieve_tool_dump_binary_to(sbin, dumpfile);
 	
-		testsuite_mailstore_init(user, home, mail_user_dovecot);
-
-		if (master_service_set
-			(master_service, "mail_full_filesystem_access=yes") < 0)
-			i_unreached(); 
-
-		testsuite_message_init(master_service, user, mail_user_dovecot);
+		testsuite_mailstore_init();
+		testsuite_message_init();
 
 		memset(&scriptenv, 0, sizeof(scriptenv));
-		scriptenv.user = testsuite_mailstore_get_user();
+		scriptenv.user = sieve_tool_get_mail_user(sieve_tool);
 		scriptenv.default_mailbox = "INBOX";
 		scriptenv.hostname = "testsuite.example.com";
 		scriptenv.postmaster_address = "postmaster@example.com";
-		scriptenv.username = user;
+		scriptenv.username = sieve_tool_get_username(sieve_tool);
 		scriptenv.smtp_open = testsuite_smtp_open;
 		scriptenv.smtp_close = testsuite_smtp_close;
 		scriptenv.trace_stream = ( trace ? o_stream_create_fd(1, 0, FALSE) : NULL );
@@ -285,18 +208,11 @@ int main(int argc, char **argv)
 		testsuite_testcase_fail("failed to compile testcase script");
 	}
 
-	/* De-initialize mail user */
-	if ( mail_user_dovecot != NULL )
-		mail_user_unref(&mail_user_dovecot);
-
 	/* De-initialize testsuite */
 	testsuite_deinit();	
 	testsuite_settings_deinit();
-	sieve_tool_deinit();
 
-	mail_storage_service_user_free(&service_user);
-	mail_storage_service_deinit(&storage_service);
-	master_service_deinit(&master_service);
+	sieve_tool_deinit(&sieve_tool);
 
 	if ( !testsuite_testcase_result() )
 		return EXIT_FAILURE;