diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c
index d6c86b47b1df3a047deab9b4c08ed945c45572e6..8f7875ae6edd186d7fc5539887790c492eed6f9f 100644
--- a/src/lib-sieve/sieve-extensions.c
+++ b/src/lib-sieve/sieve-extensions.c
@@ -1,4 +1,5 @@
 #include "lib.h"
+#include "str.h"
 #include "mempool.h"
 #include "hash.h"
 #include "array.h"
@@ -216,7 +217,54 @@ int sieve_extension_get_id(const struct sieve_extension *extension)
 	return ereg->id;
 }
 
-static void sieve_extensions_deinit_registry() 
+static bool _list_extension(const struct sieve_extension *ext)
+{
+	if ( *ext->name == '@' ) return FALSE;
+
+	if ( ext->validator_load == NULL && ext->generator_load == NULL &&
+		ext->binary_load == NULL && ext->interpreter_load == NULL &&
+		ext->load == NULL && 
+		ext->operations.count == 0 && ext->operands.count == 0 ) {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+const char *sieve_extensions_get_string(void)
+{
+	unsigned int i = 0, ext_count = array_count(&extensions);
+	string_t *extstr = t_str_new(256);
+
+	if ( ext_count > 0 ) {
+		const struct sieve_extension * const *ext =
+			array_idx(&extensions, i);
+
+		while ( !_list_extension(*ext) ) {
+			if ( i < ext_count ) 
+				ext = array_idx(&extensions, i);
+			else
+				break;
+			i++;
+		}
+
+		str_append(extstr, (*ext)->name);
+ 
+		while ( i < ext_count ) {
+			ext = array_idx(&extensions, i);
+
+			if ( _list_extension(*ext) ) {
+				str_append_c(extstr, ' ');
+				str_append(extstr, (*ext)->name);
+			}
+			i++;
+		}
+	}
+
+	return str_c(extstr);
+}
+
+static void sieve_extensions_deinit_registry(void) 
 {
 	struct hash_iterate_context *itx = 
 		hash_iterate_init(extension_index);
diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h
index e952ef1b52151a2b0f27709c54a6cf2147b2af5f..77a3df6428c26a0883de726f2f48ebdfd63a1ec2 100644
--- a/src/lib-sieve/sieve-extensions.h
+++ b/src/lib-sieve/sieve-extensions.h
@@ -38,7 +38,7 @@ struct sieve_extension {
 	ext->field->count;
 
 /* Opcodes and operands */
- 
+
 #define SIEVE_EXT_DEFINE_NO_OPERATIONS SIEVE_EXT_DEFINE_NO_OBJECTS
 #define SIEVE_EXT_DEFINE_OPERATION(OP) SIEVE_EXT_DEFINE_OBJECT(OP)
 #define SIEVE_EXT_DEFINE_OPERATIONS(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS)
@@ -57,7 +57,7 @@ const struct sieve_extension *sieve_extension_acquire(const char *extension);
 
 /* Extensions state */
 
-bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED); 
+bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED);
 const int *sieve_extensions_get_preloaded_ext_ids(void);
 void sieve_extensions_deinit(void);
 
@@ -65,8 +65,10 @@ void sieve_extensions_deinit(void);
 
 int sieve_extension_register(const struct sieve_extension *extension);
 int sieve_extensions_get_count(void);
-const struct sieve_extension *sieve_extension_get_by_id(unsigned int ext_id); 
-int sieve_extension_get_by_name(const char *name, const struct sieve_extension **ext); 
-int sieve_extension_get_id(const struct sieve_extension *extension); 
+const struct sieve_extension *sieve_extension_get_by_id(unsigned int ext_id);
+int sieve_extension_get_by_name(const char *name, const struct sieve_extension **ext);
+int sieve_extension_get_id(const struct sieve_extension *extension);
+
+const char *sieve_extensions_get_string(void);
 
 #endif /* __SIEVE_EXTENSIONS_H */
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 3ab118fa49047e76b2fde787fe3de2ce45505290..c0d269268d165d3fec906585459eca64dcca0e19 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -225,5 +225,5 @@ void sieve_close(struct sieve_binary **sbin)
 
 const char *sieve_get_capabilities(void) 
 {
-	return "fileinto reject envelope encoded-character";	
+	return sieve_extensions_get_string();
 }