diff --git a/sieve/tests/address-part.sieve b/sieve/tests/address-part.sieve
index cd25bf9851686ccb4480dfab383ef313fb082b79..fbe58b6b5bae85af03065f7778835d16ce60ba2b 100644
--- a/sieve/tests/address-part.sieve
+++ b/sieve/tests/address-part.sieve
@@ -1,4 +1,4 @@
-if address :comparator "i;ascii-casemap" :localpart "from" "STEPHAN" {
+if address :comparator "i;octet" :domain "from" "STEPHAN" {
 	discard;
 
 	if address :domain :comparator "i;octet" "from" "drunksnipers.com" {
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 547d5f35cc37f43bf85183256dacf1c5a00c6c3f..f0f7dabb628cde61a0cbc982011f278323ad658a 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -2,8 +2,10 @@
 
 #include "lib.h"
 #include "compat.h"
+#include "mempool.h"
 #include "hash.h"
 #include "array.h"
+#include "message-address.h"
 
 #include "sieve-extensions.h"
 #include "sieve-code.h"
@@ -256,6 +258,44 @@ static bool tag_address_part_generate
 	return TRUE;
 }
 
+/*
+ * Address Matching
+ */
+ 
+bool sieve_address_stringlist_match
+	(struct sieve_address_part *addrp, struct sieve_coded_stringlist *key_list,
+		struct sieve_comparator *cmp,	const char *data)
+{
+	bool matched = FALSE;
+	const struct message_address *addr;
+	
+	t_push();
+	
+	addr = message_address_parse
+		(unsafe_data_stack_pool, (const unsigned char *) data, 
+			strlen(data), 256, FALSE);
+	
+	while (!matched && addr != NULL) {
+		if (addr->domain != NULL) {
+			/* mailbox@domain */
+			const char *part;
+			
+			i_assert(addr->mailbox != NULL);
+			
+			part = addrp->extract_from(addr);
+			
+			if ( sieve_stringlist_match(key_list, part, cmp) )
+				matched = TRUE;				
+		} 
+
+		addr = addr->next;
+	}
+	
+	t_pop();
+	
+	return matched;
+}
+
 /* 
  * Core address-part modifiers
  */
@@ -267,25 +307,46 @@ const struct sieve_argument address_domain_tag =
 const struct sieve_argument address_all_tag = 
 	{ "all", tag_address_part_validate, tag_address_part_generate };
 
+static const char *addrp_all_extract_from
+	(const struct message_address *address)
+{
+	return t_strconcat(address->mailbox, "@", address->domain, NULL);
+}
+
+static const char *addrp_domain_extract_from
+	(const struct message_address *address)
+{
+	return address->domain;
+}
+
+static const char *addrp_localpart_extract_from
+	(const struct message_address *address)
+{
+	return address->mailbox;
+}
+
 const struct sieve_address_part all_address_part = {
 	"all",
 	&address_all_tag,
 	SIEVE_ADDRESS_PART_ALL,
-	NULL
+	NULL,
+	addrp_all_extract_from
 };
 
 const struct sieve_address_part local_address_part = {
 	"localpart",
 	&address_localpart_tag,
 	SIEVE_ADDRESS_PART_LOCAL,
-	NULL
+	NULL,
+	addrp_localpart_extract_from
 };
 
 const struct sieve_address_part domain_address_part = {
 	"domain",
 	&address_domain_tag,
 	SIEVE_ADDRESS_PART_DOMAIN,
-	NULL
+	NULL,
+	addrp_domain_extract_from
 };
 
 const struct sieve_address_part *sieve_core_address_parts[] = {
diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h
index 233edf1e19c10b7e3a095bd9592c80f75b35ad76..ebc560e0c7d15ad2928922355947cfa1aa65e6e4 100644
--- a/src/lib-sieve/sieve-address-parts.h
+++ b/src/lib-sieve/sieve-address-parts.h
@@ -1,6 +1,10 @@
 #ifndef __SIEVE_ADDRESS_PARTS_H
 #define __SIEVE_ADDRESS_PARTS_H
 
+#include "message-address.h"
+
+#include "sieve-common.h"
+
 enum sieve_address_part_code {
 	SIEVE_ADDRESS_PART_ALL,
 	SIEVE_ADDRESS_PART_LOCAL,
@@ -14,6 +18,8 @@ struct sieve_address_part {
 	
 	enum sieve_address_part_code code;
 	const struct sieve_extension *extension;
+
+	const char *(*extract_from)(const struct message_address *address);
 };
 
 void sieve_address_parts_link_tags
@@ -38,6 +44,8 @@ const struct sieve_address_part *sieve_opr_address_part_read
 bool sieve_opr_address_part_dump
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
-void sieve_address_parts_init_registry(struct sieve_interpreter *interp);
+bool sieve_address_stringlist_match
+	(struct sieve_address_part *addrp, struct sieve_coded_stringlist *key_list,
+		struct sieve_comparator *cmp, const char *data);
 
 #endif /* __SIEVE_ADDRESS_PARTS_H */
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index 486e9fa9625ab54ffb3112987fb7b6d64d137edc..5e828aece8690547737602c70d5cacb3db9064cd 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -188,7 +188,7 @@ static bool tst_address_opcode_execute
 			
 			int i;
 			for ( i = 0; !matched && headers[i] != NULL; i++ ) {
-				if ( sieve_stringlist_match(key_list, headers[i], cmp) )
+				if ( sieve_address_stringlist_match(addrp, key_list, cmp, headers[i]) )
 					matched = TRUE;				
 			} 
 		}