diff --git a/Makefile.am b/Makefile.am
index b953e43ceb240a1d3885c05b457b8a6efff75d5d..06b7be87494914419c4777c9d307c4b67760df5f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -26,7 +26,6 @@ test_cases = \
 	tests/match-types/is.svtest \
 	tests/match-types/contains.svtest \
 	tests/match-types/matches.svtest \
-	tests/address-parts/subaddress.svtest \
 	tests/extensions/encoded-character.svtest \
 	tests/extensions/envelope.svtest \
 	tests/extensions/variables/basic.svtest \
@@ -47,6 +46,8 @@ test_cases = \
 	tests/extensions/relational/basic.svtest \
 	tests/extensions/relational/rfc.svtest \
 	tests/extensions/relational/errors.svtest \
+	tests/extensions/subaddress/basic.svtest \
+	tests/extensions/subaddress/rfc.svtest \
 	tests/compile/compile.svtest \
 	tests/compile/examples.svtest \
 	tests/compile/errors.svtest
diff --git a/sieve/examples/subaddress.rfc5233.sieve b/sieve/examples/subaddress.rfc5233.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..9e0177c7cec88cbc9d287390cc13fffea1f6b8fe
--- /dev/null
+++ b/sieve/examples/subaddress.rfc5233.sieve
@@ -0,0 +1,23 @@
+require ["envelope", "subaddress", "fileinto"];
+
+# In this example the same user account receives mail for both
+# "ken@example.com" and "postmaster@example.com"
+
+# File all messages to postmaster into a single mailbox,
+# ignoring the :detail part.
+if envelope :user "to" "postmaster" {
+	fileinto "inbox.postmaster";
+	stop;
+}
+
+# File mailing list messages (subscribed as "ken+mta-filters").
+if envelope :detail "to" "mta-filters" {
+	fileinto "inbox.ietf-mta-filters";
+}
+
+# Redirect all mail sent to "ken+foo".
+if envelope :detail "to" "foo" {
+	redirect "ken@example.net";
+}
+
+
diff --git a/tests/compile/examples.svtest b/tests/compile/examples.svtest
index 21d0742a856a89dccd5825e9dd78b215ae4c3093..c52605b2118fdad9b724be71478cc1beba7b4ff2 100644
--- a/tests/compile/examples.svtest
+++ b/tests/compile/examples.svtest
@@ -50,8 +50,14 @@ test "Sanjay example" {
 	}
 }
 
-test "Relational extension (RFC5231) example" {
+test "Relational (RFC5231) example" {
 	if not test_compile "../../sieve/examples/relational.rfc5231.sieve" {
 		test_fail "could not compile";
 	}
 }
+
+test "Subaddress (RFC5233) example" {
+	if not test_compile "../../sieve/examples/subaddress.rfc5233.sieve" {
+		test_fail "could not compile";
+	}
+}
diff --git a/tests/address-parts/subaddress.svtest b/tests/extensions/subaddress/basic.svtest
similarity index 100%
rename from tests/address-parts/subaddress.svtest
rename to tests/extensions/subaddress/basic.svtest
diff --git a/tests/extensions/subaddress/rfc.svtest b/tests/extensions/subaddress/rfc.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..58d3261105220bc293d7c7e3ce1d1af60ea494b4
--- /dev/null
+++ b/tests/extensions/subaddress/rfc.svtest
@@ -0,0 +1,59 @@
+require "vnd.dovecot.testsuite";
+
+require "subaddress";
+
+test_set "message" text:
+From: stephan+@rename-it.nl
+To: timo+spam@iki.fi
+CC: nico@example.com
+Subject: fetch my spam
+
+Mouhahahaha... Spam!
+.
+;
+
+
+/*
+ * The ":user" argument specifies the user sub-part of the local-part of
+ * an address.  If the address is not encoded to contain a detail sub-
+ * part, then ":user" specifies the entire left side of the address
+ * (equivalent to ":localpart").
+ */
+
+test "User sub-part" {
+	if not address :user "cc" "nico" {
+		test_fail "wrong :user part extracted (1)";
+	}
+
+	if not address :user "to" "timo" {
+		test_fail "wrong :user part extracted (2)";
+	}
+
+	if not address :user "from" "stephan" {
+		test_fail "wrong :user part extracted (3)";
+	}
+}
+
+/* The ":detail" argument specifies the detail sub-part of the local-
+ * part of an address.  If the address is not encoded to contain a
+ * detail sub-part, then the address fails to match any of the specified
+ * keys.  If a zero-length string is encoded as the detail sub-part,
+ * then ":detail" resolves to the empty value ("").
+ */
+
+test "Detail sub-part" {
+	if not address :detail "to" "spam" {
+		test_fail "wrong :detail part extracted";
+	}	
+
+	if anyof (
+		address :detail :matches "cc" ["*", "?"],
+		address :detail :contains "cc" "",
+		address :detail :is "cc" "" ) {
+		test_fail ":detail inappropriately matched missing detail sub-part";
+	}
+
+	if not address :detail "from" "" {
+		test_fail "wrong empty :detail part extracted";
+	}		
+}