diff --git a/doc/man/sievec.1 b/doc/man/sievec.1
index 7fba23274d4a3732d17400f7ceba71a8c602f6e8..51062cc7c947aca2794fe22f434764ddd7a7d925 100644
--- a/doc/man/sievec.1
+++ b/doc/man/sievec.1
@@ -22,29 +22,34 @@ permission to write the compiled binary to disk, forcing it to recompile the scr
 is executed. Using the \fBsievec\fP tool, this can be performed manually by an authorized user to 
 increase performance.
 .PP
-The \fBsievec\fP command has two mandatory arguments: the \fIsieve-script\fP argument specifies 
-the script to be compiled and the \fIoutfile\fR argument specifies where the (binary) output is 
-to be written. This Sieve implementation reconizes files with a \fB.sieve\fP extension as Sieve 
+The \fBsievec\fP command accepts two arguments: the \fIsieve-script\fP argument specifies the 
+script to be compiled and the \fIoutfile\fR argument specifies where the (binary) output is to
+be written. This Sieve implementation reconizes files with a \fB.sieve\fP extension as Sieve 
 scripts and corresponding files with a \fB.svbin\fP extension as the associated compiled binary. 
 This means for example that Dovecot's deliver process will look for a binary file 'dovecot.svbin' 
-when it needs to execute 'dovecot.sieve'. This filename for the binary is chosen automatically
-when the outfile argument is missing. 
+when it needs to execute 'dovecot.sieve'. Such filename is chosen automatically for the binary output
+when the outfile argument is missing.
+.PP
+If the \fIscriptfile\fP  argument is a directory, all files in that directory with a \fI.sieve\fP 
+extension are compiled into a corresponding \fI.svbin\fP binary file. The compilation is not halted 
+upon errors; it attempts to compile as many scripts in the directory as possible. Note that the 
+\fB-d\fP option and the \fIoutfile\fP argument are not allowed when the \fIscriptfile\fP argument 
+is a directory.
 .PP
 The \fBsievec\fP command is also useful to verify Sieve scripts before using. Additionally, with 
 the \fB-d\fP option it can output a textual (and thus human-readable) dump of the generated Sieve
 code to the specified file in stead of the binary. The output is then identical to what the 
-.BR sieved (1)
-command produces for a stored binary file. This output is mainly useful to find bugs in the 
-compiler that yield corrupt binaries.
+\fBsieved\fP(1) command produces for a stored binary file. This output is mainly useful to find 
+bugs in the compiler that yield corrupt binaries.
 .SH OPTIONS
 .TP 
 \fB-d\fP 
 Don't write the binary to \fIoutfile\fP, but write a textual dump of the binary in 
 stead. In this context, the \fIoutfile\fP value '-' has special meaning: it causes the the textual 
 dump to be written to \fBstdout\fP. The \fIoutfile\fP argument may also be omitted, which has 
-the same effect as '-'. The output is identical to what the 
-.BR sieved (1) 
-command produces for a compiled Sieve binary file. 
+the same effect as '-'. The output is identical to what the \fBsieved\fP(1) command produces for 
+a compiled Sieve binary file. Note that this option is not allowed when the \fIscriptfile\fP argument
+is a directory.
 .TP
 \fB-x\fP "\fIextension extension ...\fP"
 Set the available extensions. The \fIextensions\fP parameter is a space-separated list of the 
diff --git a/src/lib-sieve-tool/sieve-tool.c b/src/lib-sieve-tool/sieve-tool.c
index 63ee463d5bed928b3f2ca2c85d603a3ece7bc8f5..4e261f7b804dc086f32f9222840cf9c0dbc73610 100644
--- a/src/lib-sieve-tool/sieve-tool.c
+++ b/src/lib-sieve-tool/sieve-tool.c
@@ -122,7 +122,8 @@ void sieve_tool_get_envelope_data
  * Sieve script handling
  */
 
-struct sieve_binary *sieve_tool_script_compile(const char *filename)
+struct sieve_binary *sieve_tool_script_compile
+(const char *filename, const char *name)
 {
 	struct sieve_error_handler *ehandler;
 	struct sieve_binary *sbin;
@@ -130,10 +131,8 @@ struct sieve_binary *sieve_tool_script_compile(const char *filename)
 	ehandler = sieve_stderr_ehandler_create(0);
 	sieve_error_handler_accept_infolog(ehandler, TRUE);
 
-	if ( (sbin = sieve_compile(filename, ehandler)) == NULL ) {
-		sieve_error_handler_unref(&ehandler);
-		i_fatal("failed to compile sieve script\n");
-	}
+	if ( (sbin = sieve_compile(filename, name, ehandler)) == NULL )
+		i_error("failed to compile sieve script '%s'\n", filename);
 
 	sieve_error_handler_unref(&ehandler);
 		
diff --git a/src/lib-sieve-tool/sieve-tool.h b/src/lib-sieve-tool/sieve-tool.h
index eeffce7acf7295b0f6772efbb2a2fc6ec4ee7a4f..fbcef92696beb07a1c1634636d58704566d7a08d 100644
--- a/src/lib-sieve-tool/sieve-tool.h
+++ b/src/lib-sieve-tool/sieve-tool.h
@@ -26,7 +26,8 @@ void sieve_tool_get_envelope_data
  * Sieve script handling
  */
 
-struct sieve_binary *sieve_tool_script_compile(const char *filename);
+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);
 
diff --git a/src/lib-sieve/sieve-script-private.h b/src/lib-sieve/sieve-script-private.h
index 69f572fd3aca80e9e5bb08a4d439777f46215760..6da33627aece09d6e7dc3af22f8b65dd9c81ce61 100644
--- a/src/lib-sieve/sieve-script-private.h
+++ b/src/lib-sieve/sieve-script-private.h
@@ -24,8 +24,9 @@ struct sieve_script {
 	const char *name;
 	const char *basename;
 	const char *filename;
-	const char *dirpath;
 	const char *path;
+	const char *dirpath;
+	const char *binpath;
 
 	/* Stream */
 	int fd; /* FIXME: we could use the stream's autoclose facility */
diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c
index 5e56d049898ca3496650fd1da5668ef621d9ee88..86e7ea907cf1f7cf2bb146719e87935ab18bd0ed 100644
--- a/src/lib-sieve/sieve-script.c
+++ b/src/lib-sieve/sieve-script.c
@@ -36,18 +36,27 @@ static inline const char *_sieve_scriptfile_get_basename(const char *filename)
 	return t_strdup_until(filename, ext);	
 }
 
-static inline const char *_sieve_scriptfile_from_name(const char *name)
+bool sieve_script_file_has_extension(const char *filename)
 {
- 	const char *ext;
+	const char *ext;
 
  	/* See if it ends in .sieve already */
-	ext = strrchr(name, '.');
-	if ( ext == NULL || ext == name || strncmp(ext,".sieve",6) != 0 )
+	ext = strrchr(filename, '.');
+	if ( ext == NULL || ext == filename || strncmp(ext,".sieve",6) != 0 )
+		return FALSE;
+
+	return TRUE;
+}
+
+static inline const char *_sieve_scriptfile_from_name(const char *name)
+{
+	if ( !sieve_script_file_has_extension(name) )
 		return t_strconcat(name, ".sieve", NULL);
 
 	return name;
 }
 
+
 /* 
  * Script object 
  */
@@ -60,7 +69,7 @@ struct sieve_script *sieve_script_init
 	pool_t pool;
 	struct stat st;
 	struct stat lnk_st;
-	const char *filename, *dirpath, *basename;
+	const char *filename, *dirpath, *basename, *binpath;
 
 	if ( exists_r != NULL )
 		*exists_r = TRUE;
@@ -77,10 +86,11 @@ struct sieve_script *sieve_script_init
 			dirpath = t_strdup_until(path, filename);
 			filename++;
 		}
-		
-		if ( name == NULL || *name == '\0' ) {
-			basename = _sieve_scriptfile_get_basename(filename);
-		} else {
+
+		basename = _sieve_scriptfile_get_basename(filename);
+		binpath = t_strconcat(dirpath, "/", basename, ".svbin", NULL);
+				
+		if ( name != NULL && *name != '\0' ) {
 			basename = name;
 		}
 			
@@ -145,6 +155,7 @@ struct sieve_script *sieve_script_init
 			script->path = p_strdup(pool, path);
 			script->filename = p_strdup(pool, filename);
 			script->dirpath = p_strdup(pool, dirpath);
+			script->binpath = p_strdup(pool, binpath);
 			script->basename = p_strdup(pool, basename);
 
 			if ( name != NULL )
@@ -177,7 +188,7 @@ struct sieve_script *sieve_script_create_in_directory
 		path = t_strconcat(dirpath, "/",
 			_sieve_scriptfile_from_name(name), NULL);
 
-    return sieve_script_init(NULL, path, name, ehandler, exists_r);
+	return sieve_script_init(NULL, path, name, ehandler, exists_r);
 }
 
 void sieve_script_ref(struct sieve_script *script)
@@ -228,7 +239,7 @@ const char *sieve_script_dirpath(const struct sieve_script *script)
 
 const char *sieve_script_binpath(const struct sieve_script *script)
 {
-	return t_strconcat(script->dirpath, "/", script->basename, ".svbin", NULL);
+	return script->binpath;
 }
 
 /* 
diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h
index 6ed6511448114c7d8faf6cc32643584642e53768..e668ff1fffe1e7e841c389036c73eb15e89ed919 100644
--- a/src/lib-sieve/sieve-script.h
+++ b/src/lib-sieve/sieve-script.h
@@ -23,6 +23,12 @@ struct sieve_script *sieve_script_create_in_directory
 void sieve_script_ref(struct sieve_script *script);
 void sieve_script_unref(struct sieve_script **script);
 
+/*
+ * Filename filter
+ */
+ 
+bool sieve_script_file_has_extension(const char *filename);
+
 /*
  * Accessors
  */
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 4eec615413b62f7269ffaf432ed1e59b477ef4c5..b8c59a86c3e1abb9042abb29df9a29e803a12c43 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -145,12 +145,14 @@ struct sieve_binary *sieve_compile_script
 }
 
 struct sieve_binary *sieve_compile
-(const char *script_path, struct sieve_error_handler *ehandler)
+(const char *script_path, const char *script_name, 
+	struct sieve_error_handler *ehandler)
 {
 	struct sieve_script *script;
 	struct sieve_binary *sbin;
 
-	if ( (script = sieve_script_create(script_path, NULL, ehandler, NULL)) == NULL )
+	if ( (script = sieve_script_create
+		(script_path, script_name, ehandler, NULL)) == NULL )
 		return NULL;
 	
 	sbin = sieve_compile_script(script, ehandler);
diff --git a/src/lib-sieve/sieve.h b/src/lib-sieve/sieve.h
index 8294d2420fdd1078b59f5036859e4a5b44af9d1a..54fb1a80aeeb5db907797656516c197e7253844b 100644
--- a/src/lib-sieve/sieve.h
+++ b/src/lib-sieve/sieve.h
@@ -52,7 +52,8 @@ struct sieve_binary *sieve_compile_script
  *   Compiles the script into a binary.
  */
 struct sieve_binary *sieve_compile
-	(const char *scriptpath, struct sieve_error_handler *ehandler);
+	(const char *script_path, const char *script_name, 
+		struct sieve_error_handler *ehandler);
 
 /* 
  * Reading/writing Sieve binaries
diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c
index 9a88212e915b17ea49b13b5bc44721d93dae2b40..4055c23d80e8048a6f32c9caa40a2ec172f640a9 100644
--- a/src/plugins/lda-sieve/lda-sieve-plugin.c
+++ b/src/plugins/lda-sieve/lda-sieve-plugin.c
@@ -205,7 +205,7 @@ static int lda_sieve_run
 	
 		sieve_error_handler_copy_masterlog(ehandler, FALSE);
 	
-		if ( (sbin=sieve_compile(script_path, ehandler)) == NULL ) {
+		if ( (sbin=sieve_compile(script_path, NULL, ehandler)) == NULL ) {
 			sieve_sys_error
 					("failed to compile script %s "
 						"(view logfile %s for more information); "
diff --git a/src/sieve-tools/sieve-test.c b/src/sieve-tools/sieve-test.c
index 9b42473ada825dca32c69e8f10fdcec90f856be1..e3fefff7ee8ca5d66f0578f3def4dc874d7b257d 100644
--- a/src/sieve-tools/sieve-test.c
+++ b/src/sieve-tools/sieve-test.c
@@ -202,197 +202,199 @@ int main(int argc, char **argv)
 	
 	/* Compile main sieve script */
 	if ( force_compile ) {
-		main_sbin = sieve_tool_script_compile(scriptfile);
+		main_sbin = sieve_tool_script_compile(scriptfile, NULL);
 		(void) sieve_save(main_sbin, NULL);
 	} else {
 		main_sbin = sieve_tool_script_open(scriptfile);
 	}
 
-	/* Dump script */
-	sieve_tool_dump_binary_to(main_sbin, dumpfile);
+	if ( main_sbin != NULL ) {
+		/* Dump script */
+		sieve_tool_dump_binary_to(main_sbin, dumpfile);
 	
-	user = sieve_tool_get_user();
-	home = getenv("HOME");
-
-	/* Initialize mail storages */
-	mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL);
-	mail_storage_init();
-	mail_storage_register_all();
-	mailbox_list_register_all();
+		user = sieve_tool_get_user();
+		home = getenv("HOME");
+
+		/* Initialize mail storages */
+		mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL);
+		mail_storage_init();
+		mail_storage_register_all();
+		mailbox_list_register_all();
 	
-	/* Obtain mail namespaces from -l argument */
-	if ( mailloc != NULL ) {
-		env_put(t_strdup_printf("NAMESPACE_1=%s", mailloc));
-		env_put("NAMESPACE_1_INBOX=1");
-		env_put("NAMESPACE_1_LIST=1");
-		env_put("NAMESPACE_1_SEP=.");
-		env_put("NAMESPACE_1_SUBSCRIPTIONS=1");
-
-		mail_user = mail_user_init(user);
-		mail_user_set_home(mail_user, home);
-		if (mail_namespaces_init(mail_user) < 0)
-			i_fatal("Namespace initialization failed");	
-
-		ns = mail_user->namespaces;
-	}
+		/* Obtain mail namespaces from -l argument */
+		if ( mailloc != NULL ) {
+			env_put(t_strdup_printf("NAMESPACE_1=%s", mailloc));
+			env_put("NAMESPACE_1_INBOX=1");
+			env_put("NAMESPACE_1_LIST=1");
+			env_put("NAMESPACE_1_SEP=.");
+			env_put("NAMESPACE_1_SUBSCRIPTIONS=1");
+
+			mail_user = mail_user_init(user);
+			mail_user_set_home(mail_user, home);
+			if (mail_namespaces_init(mail_user) < 0)
+				i_fatal("Namespace initialization failed");	
+
+			ns = mail_user->namespaces;
+		}
 
-	/* Initialize raw mail object */
-	mail_raw_init(user);
-	mailr = mail_raw_open_file(mailfile);
+		/* Initialize raw mail object */
+		mail_raw_init(user);
+		mailr = mail_raw_open_file(mailfile);
 
-	sieve_tool_get_envelope_data(mailr->mail, &recipient, &sender);
+		sieve_tool_get_envelope_data(mailr->mail, &recipient, &sender);
 
-	if ( mailbox == NULL )
-		mailbox = "INBOX";
+		if ( mailbox == NULL )
+			mailbox = "INBOX";
 
-	/* Collect necessary message data */
-	memset(&msgdata, 0, sizeof(msgdata));
-	msgdata.mail = mailr->mail;
-	msgdata.return_path = sender;
-	msgdata.to_address = recipient;
-	msgdata.auth_user = user;
-	(void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id);
+		/* Collect necessary message data */
+		memset(&msgdata, 0, sizeof(msgdata));
+		msgdata.mail = mailr->mail;
+		msgdata.return_path = sender;
+		msgdata.to_address = recipient;
+		msgdata.auth_user = user;
+		(void)mail_get_first_header(mailr->mail, "Message-ID", &msgdata.id);
 
-	/* Create stream for test and trace output */
-	if ( !execute || trace )
-		teststream = o_stream_create_fd(1, 0, FALSE);	
+		/* Create stream for test and trace output */
+		if ( !execute || trace )
+			teststream = o_stream_create_fd(1, 0, FALSE);	
 		
-	/* Compose script environment */
-	memset(&scriptenv, 0, sizeof(scriptenv));
-	scriptenv.default_mailbox = "INBOX";
-	scriptenv.namespaces = ns;
-	scriptenv.username = user;
-	scriptenv.hostname = "host.example.com";
-	scriptenv.postmaster_address = "postmaster@example.com";
-	scriptenv.smtp_open = sieve_smtp_open;
-	scriptenv.smtp_close = sieve_smtp_close;
-	scriptenv.duplicate_mark = duplicate_mark;
-	scriptenv.duplicate_check = duplicate_check;
-	scriptenv.trace_stream = ( trace ? teststream : NULL );
-	scriptenv.exec_status = &estatus;
+		/* Compose script environment */
+		memset(&scriptenv, 0, sizeof(scriptenv));
+		scriptenv.default_mailbox = "INBOX";
+		scriptenv.namespaces = ns;
+		scriptenv.username = user;
+		scriptenv.hostname = "host.example.com";
+		scriptenv.postmaster_address = "postmaster@example.com";
+		scriptenv.smtp_open = sieve_smtp_open;
+		scriptenv.smtp_close = sieve_smtp_close;
+		scriptenv.duplicate_mark = duplicate_mark;
+		scriptenv.duplicate_check = duplicate_check;
+		scriptenv.trace_stream = ( trace ? teststream : NULL );
+		scriptenv.exec_status = &estatus;
 	
-	/* Create error handler */
-	ehandler = sieve_stderr_ehandler_create(0);	
-	sieve_error_handler_accept_infolog(ehandler, TRUE);
+		/* Create error handler */
+		ehandler = sieve_stderr_ehandler_create(0);	
+		sieve_error_handler_accept_infolog(ehandler, TRUE);
 
-	/* Run the test */
+		/* Run the test */
 	
-	if ( array_count(&scriptfiles) == 0 ) {
-		/* Single script */
-		sbin = main_sbin;
-		main_sbin = NULL;
+		if ( array_count(&scriptfiles) == 0 ) {
+			/* Single script */
+			sbin = main_sbin;
+			main_sbin = NULL;
 	
-		/* Execute/Test script */
-		if ( execute )
-			ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler);
-		else
-			ret = sieve_test(sbin, &msgdata, &scriptenv, ehandler, teststream);				
-	} else {
-		/* Multiple scripts */
-		const char *const *sfiles;
-		unsigned int i, count;
-		struct sieve_multiscript *mscript = sieve_multiscript_start
-			(&msgdata, &scriptenv, ehandler);
-		int result = 1; 
+			/* Execute/Test script */
+			if ( execute )
+				ret = sieve_execute(sbin, &msgdata, &scriptenv, ehandler);
+			else
+				ret = sieve_test(sbin, &msgdata, &scriptenv, ehandler, teststream);				
+		} else {
+			/* Multiple scripts */
+			const char *const *sfiles;
+			unsigned int i, count;
+			struct sieve_multiscript *mscript = sieve_multiscript_start
+				(&msgdata, &scriptenv, ehandler);
+			int result = 1; 
 		
-		/* Execute scripts sequentially */
-		sfiles = array_get(&scriptfiles, &count); 
-		for ( i = 0; i < count && result > 0; i++ ) {
-			if ( teststream != NULL ) 
-				o_stream_send_str(teststream, 
-					t_strdup_printf("\n## Executing script: %s\n", sfiles[i]));
+			/* Execute scripts sequentially */
+			sfiles = array_get(&scriptfiles, &count); 
+			for ( i = 0; i < count && result > 0; i++ ) {
+				if ( teststream != NULL ) 
+					o_stream_send_str(teststream, 
+						t_strdup_printf("\n## Executing script: %s\n", sfiles[i]));
 			
-			/* Close previous script */
-			if ( sbin != NULL )						
-				sieve_close(&sbin);
+				/* Close previous script */
+				if ( sbin != NULL )						
+					sieve_close(&sbin);
 		
-			/* Compile sieve script */
-			if ( force_compile ) {
-				sbin = sieve_tool_script_compile(sfiles[i]);
-				(void) sieve_save(sbin, NULL);
-			} else {
-				sbin = sieve_tool_script_open(sfiles[i]);
-			}
+				/* Compile sieve script */
+				if ( force_compile ) {
+					sbin = sieve_tool_script_compile(sfiles[i], sfiles[i]);
+					(void) sieve_save(sbin, NULL);
+				} else {
+					sbin = sieve_tool_script_open(sfiles[i]);
+				}
 			
-			if ( sbin == NULL ) {
-				result = -1;
-				break;
-			}
+				if ( sbin == NULL ) {
+					result = -1;
+					break;
+				}
 			
-			/* Execute/Test script */
-			if ( execute )
-				result = sieve_multiscript_execute(mscript, sbin, FALSE);
-			else
-				result = sieve_multiscript_test(mscript, sbin, FALSE, teststream);
-		}
+				/* Execute/Test script */
+				if ( execute )
+					result = sieve_multiscript_execute(mscript, sbin, FALSE);
+				else
+					result = sieve_multiscript_test(mscript, sbin, FALSE, teststream);
+			}
 		
-		/* Execute/Test main script */
-		switch ( result )	{
-		case TRUE:
-			if ( teststream != NULL ) 
-				o_stream_send_str(teststream, 
-					t_strdup_printf("## Executing script: %s\n", scriptfile));
+			/* Execute/Test main script */
+			switch ( result )	{
+			case TRUE:
+				if ( teststream != NULL ) 
+					o_stream_send_str(teststream, 
+						t_strdup_printf("## Executing script: %s\n", scriptfile));
 				
-			/* Close previous script */
-			if ( sbin != NULL )						
-				sieve_close(&sbin);	
+				/* Close previous script */
+				if ( sbin != NULL )						
+					sieve_close(&sbin);	
 				
-			sbin = main_sbin;
-			main_sbin = NULL;
+				sbin = main_sbin;
+				main_sbin = NULL;
 			
-			if ( execute )
-				(void)sieve_multiscript_execute(mscript, sbin, TRUE);
-			else 
-				(void)sieve_multiscript_test(mscript, sbin, TRUE, teststream);
+				if ( execute )
+					(void)sieve_multiscript_execute(mscript, sbin, TRUE);
+				else 
+					(void)sieve_multiscript_test(mscript, sbin, TRUE, teststream);
 				
-		case FALSE:	
-			ret = sieve_multiscript_finish(&mscript);
-			break;
+			case FALSE:	
+				ret = sieve_multiscript_finish(&mscript);
+				break;
 		
-		default:
-			ret = SIEVE_EXEC_FAILURE;
+			default:
+				ret = SIEVE_EXEC_FAILURE;
+			}
 		}
-	}
 	
-	/* Run */
-	switch ( ret ) {
-	case SIEVE_EXEC_OK:
-		i_info("final result: success");
-		break;
-	case SIEVE_EXEC_BIN_CORRUPT:
-		i_info("corrupt binary deleted.");
-		(void) unlink(sieve_binary_path(sbin));
-	case SIEVE_EXEC_FAILURE:
-		i_info("final result: failed; resolved with successful implicit keep");
-		break;
-	case SIEVE_EXEC_KEEP_FAILED:
-		i_info("final result: utter failure");
-		break;
-	default:
-		i_info("final result: unrecognized return value?!");	
-	}
+		/* Run */
+		switch ( ret ) {
+		case SIEVE_EXEC_OK:
+			i_info("final result: success");
+			break;
+		case SIEVE_EXEC_BIN_CORRUPT:
+			i_info("corrupt binary deleted.");
+			(void) unlink(sieve_binary_path(sbin));
+		case SIEVE_EXEC_FAILURE:
+			i_info("final result: failed; resolved with successful implicit keep");
+			break;
+		case SIEVE_EXEC_KEEP_FAILED:
+			i_info("final result: utter failure");
+			break;
+		default:
+			i_info("final result: unrecognized return value?!");	
+		}
 
-	if ( teststream != NULL )
-		o_stream_destroy(&teststream);
+		if ( teststream != NULL )
+			o_stream_destroy(&teststream);
 
-	/* Cleanup remaining binaries */
-	sieve_close(&sbin);
-	if ( main_sbin != NULL ) sieve_close(&main_sbin);
-	
-	/* Cleanup error handler */
-	sieve_error_handler_unref(&ehandler);
+		/* Cleanup remaining binaries */
+		sieve_close(&sbin);
+		if ( main_sbin != NULL ) sieve_close(&main_sbin);
+		
+		/* Cleanup error handler */
+		sieve_error_handler_unref(&ehandler);
 
-	/* De-initialize raw mail object */
-	mail_raw_close(mailr);
-	mail_raw_deinit();
+		/* De-initialize raw mail object */
+		mail_raw_close(mailr);
+		mail_raw_deinit();
 
-	/* De-initialize mail user object */
-	if ( mail_user != NULL )
-		mail_user_unref(&mail_user);
+		/* De-initialize mail user object */
+		if ( mail_user != NULL )
+			mail_user_unref(&mail_user);
 
-	/* De-initialize mail storages */
-	mail_storage_deinit();
-	mail_users_deinit();
+		/* De-initialize mail storages */
+		mail_storage_deinit();
+		mail_users_deinit();
+	}
 
 	sieve_tool_deinit();
 	
diff --git a/src/sieve-tools/sievec.c b/src/sieve-tools/sievec.c
index 6200f3713556dc4a7de0dba76defa92fca8f1450..3e407b9563c888cd59b0a0a816bfbba9ee3c9215 100644
--- a/src/sieve-tools/sievec.c
+++ b/src/sieve-tools/sievec.c
@@ -4,6 +4,7 @@
 #include "lib.h"
 
 #include "sieve.h"
+#include "sieve-script.h"
 #include "sieve-tool.h"
 
 #include <stdio.h>
@@ -13,6 +14,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <dirent.h>
 
 /*
  * Print help
@@ -31,10 +33,13 @@ static void print_help(void)
 
 int main(int argc, char **argv) {
 	int i;
+	struct stat st;
 	struct sieve_binary *sbin;
 	bool dump = FALSE;
 	const char *scriptfile, *outfile, *extensions;
 		
+	sieve_tool_init();	
+		
 	scriptfile = outfile = extensions = NULL;
 	for (i = 1; i < argc; i++) {
 		if (strcmp(argv[i], "-d") == 0) {
@@ -64,22 +69,76 @@ int main(int argc, char **argv) {
 	if ( outfile == NULL && dump )
 		outfile = "-";
 
-	sieve_tool_init();
-
 	if ( extensions != NULL ) {
 		sieve_set_extensions(extensions);
 	}
 
-	sbin = sieve_tool_script_compile(scriptfile);
+	if ( stat(scriptfile, &st) == 0 && S_ISDIR(st.st_mode) ) {
+		/* Script directory */
+		DIR *dirp;
+		struct dirent *dp;
+		
+		/* Sanity checks on some of the arguments */
+		
+		if ( dump )
+			i_fatal("the -d option is not allowed when scriptfile is a directory."); 
+		
+		if ( outfile != NULL )
+			i_fatal("the outfile argument is not allowed when scriptfile is a "
+				"directory."); 
+		
+		/* Open the directory */
+		if ( (dirp = opendir(scriptfile)) == NULL )
+			i_fatal("opendir(%s) failed: %m", scriptfile);
+			
+		/* Compile each sieve file */
+		for (;;) {
+		
+			errno = 0;
+			if ( (dp = readdir(dirp)) == NULL ) {
+				if ( errno != 0 ) 
+					i_fatal("readdir(%s) failed: %m", scriptfile);
+				break;
+			}
+											
+			if ( sieve_script_file_has_extension(dp->d_name) ) {
+				const char *file;
+				
+				if ( scriptfile[strlen(scriptfile)-1] == '/' )
+					file = t_strconcat(scriptfile, dp->d_name, NULL);
+				else
+					file = t_strconcat(scriptfile, "/", dp->d_name, NULL);
+
+				sbin = sieve_tool_script_compile(file, dp->d_name);
 
-	if ( sbin != NULL ) {
-		if ( dump ) 
-			sieve_tool_dump_binary_to(sbin, outfile);
-		else {
-			sieve_save(sbin, outfile);
+				if ( sbin != NULL ) {
+					sieve_save(sbin, NULL);
+		
+					sieve_close(&sbin);
+				}
+			}
 		}
+   
+   	/* Close the directory */
+		if ( closedir(dirp) < 0 ) 
+			i_fatal("closedir(%s) failed: %m", scriptfile);
+ 	
+	} else {
+		/* Script file (i.e. not a directory)
+		 * 
+		 *   NOTE: For consistency, stat errors are handled here as well 
+		 */	
+		sbin = sieve_tool_script_compile(scriptfile, NULL);
+
+		if ( sbin != NULL ) {
+			if ( dump ) 
+				sieve_tool_dump_binary_to(sbin, outfile);
+			else {
+				sieve_save(sbin, outfile);
+			}
 		
-		sieve_close(&sbin);
+			sieve_close(&sbin);
+		}
 	}
 		
 	sieve_tool_deinit();
diff --git a/src/testsuite/testsuite-script.c b/src/testsuite/testsuite-script.c
index 6573c154b494e4ffc66c55e30c0ebb2b2d8041cc..342807d69ece837772b8efe88eac4dd381b76d0f 100644
--- a/src/testsuite/testsuite-script.c
+++ b/src/testsuite/testsuite-script.c
@@ -52,7 +52,7 @@ bool testsuite_script_compile(const char *script_path)
 	env_put(t_strconcat("SIEVE_DIR=", sieve_dir, "included", NULL));
 	env_put(t_strconcat("SIEVE_GLOBAL_DIR=", sieve_dir, "included-global", NULL));
 
-	if ( (sbin = sieve_compile(script_path, testsuite_log_ehandler)) == NULL )
+	if ( (sbin = sieve_compile(script_path, NULL, testsuite_log_ehandler)) == NULL )
 		return FALSE;
 
 	if ( _testsuite_compiled_script != NULL ) {
diff --git a/src/testsuite/testsuite.c b/src/testsuite/testsuite.c
index ea2b80dcf1b971fa3d9891956d164212c2c86d21..1923b6eb4726c2281100d3a03ca248b0c0ce8521 100644
--- a/src/testsuite/testsuite.c
+++ b/src/testsuite/testsuite.c
@@ -121,45 +121,47 @@ int main(int argc, char **argv)
 	env_put(t_strconcat("SIEVE_GLOBAL_DIR=", sieve_dir, "included-global", NULL));
 	
 	/* Compile sieve script */
-	sbin = sieve_tool_script_compile(scriptfile);
+	if ( (sbin = sieve_tool_script_compile(scriptfile, NULL)) != NULL ) {
 
-	/* Dump script */
-	sieve_tool_dump_binary_to(sbin, dumpfile);
+		/* Dump script */
+		sieve_tool_dump_binary_to(sbin, dumpfile);
 	
-	/* Initialize mail storages */
-	mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL);
-	mail_storage_init();
-	mail_storage_register_all();
-	mailbox_list_register_all();
-
-	/* Initialize message environment */
-	user = sieve_tool_get_user();
-	testsuite_message_init(user);
-
-	memset(&scriptenv, 0, sizeof(scriptenv));
-	scriptenv.default_mailbox = "INBOX";
-	scriptenv.username = user;
-	scriptenv.trace_stream = ( trace ? o_stream_create_fd(1, 0, FALSE) : NULL );
-
-	/* Run the test */
-	ehandler = sieve_stderr_ehandler_create(0);
-	ret = sieve_execute(sbin, &testsuite_msgdata, &scriptenv, ehandler);
-
-	switch ( ret ) {
-	case SIEVE_EXEC_OK:
-		break;
-	case SIEVE_EXEC_FAILURE:
-	case SIEVE_EXEC_KEEP_FAILED:
-		testsuite_testcase_fail("execution aborted");
-		break;
-	case SIEVE_EXEC_BIN_CORRUPT:
-        testsuite_testcase_fail("binary corrupt");
-		break;
-	default:
-		testsuite_testcase_fail("unknown execution exit code");
+		/* Initialize mail storages */
+		mail_users_init(getenv("AUTH_SOCKET_PATH"), getenv("DEBUG") != NULL);
+		mail_storage_init();
+		mail_storage_register_all();
+		mailbox_list_register_all();
+
+		/* Initialize message environment */
+		user = sieve_tool_get_user();
+		testsuite_message_init(user);
+
+		memset(&scriptenv, 0, sizeof(scriptenv));
+		scriptenv.default_mailbox = "INBOX";
+		scriptenv.username = user;
+		scriptenv.trace_stream = ( trace ? o_stream_create_fd(1, 0, FALSE) : NULL );
+
+		/* Run the test */
+		ehandler = sieve_stderr_ehandler_create(0);
+		ret = sieve_execute(sbin, &testsuite_msgdata, &scriptenv, ehandler);
+
+		switch ( ret ) {
+		case SIEVE_EXEC_OK:
+			break;
+		case SIEVE_EXEC_FAILURE:
+		case SIEVE_EXEC_KEEP_FAILED:
+			testsuite_testcase_fail("execution aborted");
+			break;
+		case SIEVE_EXEC_BIN_CORRUPT:
+    	    testsuite_testcase_fail("binary corrupt");
+			break;
+		default:
+			testsuite_testcase_fail("unknown execution exit code");
+		}
+
+		sieve_close(&sbin);
 	}
 
-	sieve_close(&sbin);
 	sieve_error_handler_unref(&ehandler);
 
 	if ( scriptenv.trace_stream != NULL )