diff --git a/src/lib-sieve-tool/mail-raw.c b/src/lib-sieve-tool/mail-raw.c
index 9aebd8ad57a7ed395e1ebbefa2535df68ed9f8b7..da2d8eba0a9df5fc25caca2f97ce2265576da0c6 100644
--- a/src/lib-sieve-tool/mail-raw.c
+++ b/src/lib-sieve-tool/mail-raw.c
@@ -1,11 +1,6 @@
 /* Copyright (c) 2002-2010 Pigeonhole authors, see the included COPYING file
  */
 
-/* FIXME: This file was gratefully stolen from dovecot/src/deliver/deliver.c and 
- * altered to suit our needs. So, this contains lots and lots of duplicated 
- * code. 
- */
-
 #include "lib.h"
 #include "istream.h"
 #include "istream-seekable.h"
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index eb87a687572f4f7818a272eb651cbab0ddac6605..e9c97a6d04144bba9539afb9a98fdeeadb52be5b 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -120,14 +120,14 @@ static bool cmd_redirect_validate
 		(validator, cmd, arg, "address", 1, SAAT_STRING) ) {
 		return FALSE;
 	}
-	
+
 	if ( !sieve_validator_argument_activate(validator, cmd, arg, FALSE) )
 		return FALSE;
 
-	/* We can only assess the validity of the outgoing address when it is 
-	 * a string literal. For runtime-generated strings this needs to be 
-	 * done at runtime (FIXME!)
-     */
+	/* We can only assess the validity of the outgoing address when it is
+	 * a string literal. For runtime-generated strings this needs to be
+	 * done at runtime.
+	 */
 	if ( sieve_argument_is_string_literal(arg) ) {
 		string_t *address = sieve_ast_argument_str(arg);
 		const char *error;
@@ -136,9 +136,9 @@ static bool cmd_redirect_validate
 		T_BEGIN {
 			/* Verify and normalize the address to 'local_part@domain' */
 			norm_address = sieve_address_normalize(address, &error);
-		
+
 			if ( norm_address == NULL ) {
-				sieve_argument_validate_error(validator, arg, 
+				sieve_argument_validate_error(validator, arg,
 					"specified redirect address '%s' is invalid: %s",
 					str_sanitize(str_c(address),128), error);
 			} else {
@@ -148,7 +148,7 @@ static bool cmd_redirect_validate
 		} T_END;
 
 		return ( norm_address != NULL );
-	}		
+	}
 
 	return TRUE;
 }
@@ -193,6 +193,8 @@ static int cmd_redirect_operation_execute
 	struct sieve_side_effects_list *slist = NULL;
 	struct act_redirect_context *act;
 	string_t *redirect;
+	bool literal_address;
+	const char *norm_address;
 	pool_t pool;
 	int ret;
 
@@ -205,28 +207,42 @@ static int cmd_redirect_operation_execute
 		return ret;
 
 	/* Read the address */
-	if ( (ret=sieve_opr_string_read(renv, address, "address", &redirect)) <= 0 )
+	if ( (ret=sieve_opr_string_read_ex(renv, address, "address", &redirect, 
+		&literal_address)) <= 0 )
 		return ret;
 
 	/*
 	 * Perform operation
 	 */
 
-	/* FIXME: perform address normalization if the string is not a string literal
-	 */
+	if ( !literal_address ) {
+		const char *error;
+
+		/* Verify and normalize the address to 'local_part@domain' */
+		norm_address = sieve_address_normalize(redirect, &error);
+
+		if ( norm_address == NULL ) {
+			sieve_runtime_error(renv, NULL,
+				"specified redirect address '%s' is invalid: %s",
+				str_sanitize(str_c(redirect),128), error);
+			return SIEVE_EXEC_FAILURE;
+		}
+	} else {
+		norm_address = str_c(redirect);
+	}
 
 	if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_ACTIONS) ) {
 		sieve_runtime_trace(renv, 0, "redirect action");
 		sieve_runtime_trace_descend(renv);
 		sieve_runtime_trace(renv, 0, "forward message to address `%s'",
-			str_sanitize(str_c(redirect), 80));
+			str_sanitize(norm_address, 80));
 	}
 
 	/* Add redirect action to the result */
 
 	pool = sieve_result_pool(renv->result);
 	act = p_new(pool, struct act_redirect_context, 1);
-	act->to_address = p_strdup(pool, str_c(redirect));
+	act->to_address = p_strdup(pool, norm_address);
 
 	if ( sieve_result_add_action
 		(renv, NULL, &act_redirect, slist, (void *) act,
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index c2eca71c8b14dd906954a4e67b203d2f6f74b4d7..05731b03c012ea17b7d18e2803190c7f7f59c240 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -183,14 +183,14 @@ static bool tag_address_part_validate
 (struct sieve_validator *valdtr ATTR_UNUSED, struct sieve_ast_argument **arg, 
 	struct sieve_command *cmd ATTR_UNUSED)
 {
-	/* FIXME: Currenly trivial, but might need to allow for further validation for
+	/* NOTE: Currenly trivial, but might need to allow for further validation for
 	 * future extensions.
 	 */
-	 
-	/* Syntax:   
+
+	/* Syntax:
 	 *   ":localpart" / ":domain" / ":all" (subject to extension)
-   */
-	
+   	 */
+
 	/* Skip tag */
 	*arg = sieve_ast_argument_next(*arg);
 
diff --git a/src/managesieve/cmd-putscript.c b/src/managesieve/cmd-putscript.c
index f441c054599a01f619e727602eadf98927384a3d..10d4f31a19ae7a1dc9f936f5c43c2f9a6140fe6e 100644
--- a/src/managesieve/cmd-putscript.c
+++ b/src/managesieve/cmd-putscript.c
@@ -283,7 +283,7 @@ static bool cmd_putscript_continue_parsing(struct client_command_context *cmd)
 		ctx->script_size = MANAGESIEVE_ARG_LITERAL_SIZE(args);
 		nonsync = TRUE;
 	} else {
-		/* FIXME */
+		/* FIXME: allow quoted strings */
 		client_send_no(client, 
 			"This MANAGESIEVE implementation currently does not allow "
 			"quoted strings to be used for script contents.");