diff --git a/src/lib-sieve/sieve-address.c b/src/lib-sieve/sieve-address.c
index 94c94400ca054876165532e198aa28d021f2a703..23277fca53c9949aaf94acf4a1cbd735a7e18ac9 100644
--- a/src/lib-sieve/sieve-address.c
+++ b/src/lib-sieve/sieve-address.c
@@ -265,6 +265,20 @@ static inline void sieve_address_error
  *          MERGE!
  */
 
+static int check_local_part(struct sieve_message_address_parser *ctx)
+{
+	const unsigned char *p, *pend;
+
+	p = str_data(ctx->local_part);
+	pend = p + str_len(ctx->local_part);
+	while (p < pend) {
+		if (*p < 0x20 || *p > 0x7e)
+			return -1;
+		p++;
+	}
+	return 0;
+}
+
 static int parse_local_part(struct sieve_message_address_parser *ctx)
 {
 	int ret;
@@ -302,7 +316,7 @@ static int parse_local_part(struct sieve_message_address_parser *ctx)
 		} while (ret > 0 && *ctx->parser.data == '.');
 	}
 
-	if (ret < 0) {
+	if (ret < 0 || check_local_part(ctx) < 0) {
 		sieve_address_error(ctx, "invalid local part");
 		return -1;
 	}
diff --git a/tests/compile/errors.svtest b/tests/compile/errors.svtest
index 64065079e2c876f9c6903050b94b9ef61e1ee070..a5aa212dc5f1c727f54d47505f61854a422b579a 100644
--- a/tests/compile/errors.svtest
+++ b/tests/compile/errors.svtest
@@ -307,7 +307,7 @@ test "Outgoing address errors (FIXME: count only)" {
 		test_fail "compile should have failed.";
 	}
 
-	if not test_error :count "eq" :comparator "i;ascii-numeric" "15" {
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "16" {
 		test_fail "wrong number of errors reported";
 	}
 }
diff --git a/tests/compile/errors/out-address.sieve b/tests/compile/errors/out-address.sieve
index 7880e0ecaca5b38140035dfbfb6e3652f3a7801d..3e39599c8ca2d0c91213b1df885c897a14990ea0 100644
--- a/tests/compile/errors/out-address.sieve
+++ b/tests/compile/errors/out-address.sieve
@@ -15,6 +15,7 @@ redirect "Error <stephan";
 redirect "Error <stephan@";
 redirect "stephan@example.org,tss@example.net";
 redirect "stephan@example.org,%&^&!!~";
+redirect "rüdiger@example.com";
 
 vacation :from "Error" "Ik ben er niet.";