diff --git a/src/managesieve/main.c b/src/managesieve/main.c
index 43e89ce074fb6945bb8ee5b029b4ea14edcf6a89..b244f007027d9fc4762b60b3c11d21bd6de2e029 100644
--- a/src/managesieve/main.c
+++ b/src/managesieve/main.c
@@ -12,6 +12,7 @@
 #include "base64.h"
 #include "process-title.h"
 #include "restrict-access.h"
+#include "time-util.h"
 #include "settings.h"
 #include "master-interface.h"
 #include "master-service-settings.h"
@@ -21,6 +22,7 @@
 #include "mail-user.h"
 #include "mail-storage-service.h"
 
+#include "managesieve-quote.h"
 #include "managesieve-common.h"
 #include "managesieve-commands.h"
 #include "managesieve-capabilities.h"
@@ -142,7 +144,7 @@ static void client_logged_in(struct client *client)
 static int
 client_create_from_input(const struct mail_storage_service_input *input,
 			 int fd_in, int fd_out, const buffer_t *input_buf,
-			 const char **error_r)
+			 const char **client_error_r, const char **error_r)
 {
 	struct mail_storage_service_input service_input;
 	struct mail_user *mail_user;
@@ -150,6 +152,9 @@ client_create_from_input(const struct mail_storage_service_input *input,
 	struct managesieve_settings *set;
 	struct event *event;
 
+	*client_error_r = NULL;
+	*error_r = NULL;
+
 	event = event_create(NULL);
 	event_add_category(event, &event_category_managesieve);
 	event_add_fields(event, (const struct event_add_field []){
@@ -177,7 +182,8 @@ client_create_from_input(const struct mail_storage_service_input *input,
 		verbose_proctitle = TRUE;
 
 	if (client_create(fd_in, fd_out, input->session_id,
-			  event, mail_user, set, &client, error_r) < 0) {
+			  event, mail_user, set,
+			  &client, client_error_r, error_r) < 0) {
 		settings_free(set);
 		mail_user_unref(&mail_user);
 		event_unref(&event);
@@ -196,7 +202,7 @@ client_create_from_input(const struct mail_storage_service_input *input,
 static void main_stdio_run(const char *username)
 {
 	struct mail_storage_service_input input;
-	const char *value, *error, *input_base64;
+	const char *value, *client_error, *error, *input_base64;
 	buffer_t *input_buf;
 
 	i_zero(&input);
@@ -216,7 +222,7 @@ static void main_stdio_run(const char *username)
 		     NULL : t_base64_decode_str(input_base64));
 
 	if (client_create_from_input(&input, STDIN_FILENO, STDOUT_FILENO,
-				     input_buf, &error) < 0)
+				     input_buf, &client_error, &error) < 0)
 		i_fatal("%s", error);
 }
 
@@ -224,10 +230,9 @@ static void
 login_request_finished(const struct login_server_request *request,
 		       const char *username, const char *const *extra_fields)
 {
-#define MSG_BYE_INTERNAL_ERROR "BYE \""CRITICAL_MSG"\"\r\n"
 	struct mail_storage_service_input input;
 	enum login_request_flags flags = request->auth_req.flags;
-	const char *error;
+	const char *client_error, *error;
 	buffer_t input_buf;
 
 	i_zero(&input);
@@ -245,11 +250,21 @@ login_request_finished(const struct login_server_request *request,
 	buffer_create_from_const_data(&input_buf, request->data,
 				      request->auth_req.data_size);
 	if (client_create_from_input(&input, request->fd, request->fd,
-				     &input_buf, &error) < 0) {
+				     &input_buf, &client_error, &error) < 0) {
+		string_t *byemsg;
 		int fd = request->fd;
 
-		if (write(fd, MSG_BYE_INTERNAL_ERROR,
-			  strlen(MSG_BYE_INTERNAL_ERROR)) < 0) {
+		if (client_error == NULL) {
+			client_error = t_strflocaltime(CRITICAL_MSG_STAMP,
+						       ioloop_time);
+		}
+
+		byemsg = t_str_new(256);
+		str_append(byemsg, "BYE ");
+		managesieve_quote_append_string(byemsg, client_error, FALSE);
+		str_append(byemsg, "\r\n");
+
+		if (write(fd, str_data(byemsg), str_len(byemsg)) < 0) {
 			if (errno != EAGAIN && errno != EPIPE)
 				i_error("write(client) failed: %m");
 		}
diff --git a/src/managesieve/managesieve-client.c b/src/managesieve/managesieve-client.c
index 3a23226fbeb23bab2305c1004b6341979c36bb38..ec7b8de16c11949c025f9ac5a08674c8d7d2e598 100644
--- a/src/managesieve/managesieve-client.c
+++ b/src/managesieve/managesieve-client.c
@@ -61,50 +61,50 @@ static void client_idle_timeout(struct client *client)
 	}
 }
 
-static struct sieve_storage *
-client_get_storage(struct sieve_instance *svinst, struct event *event,
-		   struct mail_user *user, int fd_out)
+static int
+client_get_storage(struct sieve_instance *svinst, struct mail_user *user,
+		   struct sieve_storage **storage_r,
+		   const char **client_error_r, const char **error_r)
 {
 	struct sieve_storage *storage;
 	enum sieve_error error_code;
-	const char *errormsg, *byemsg;
 
-	/* Open personal script storage */
+	*storage_r = NULL;
 
+	/* Open personal script storage */
 	if (sieve_storage_create_personal(svinst, user,
 					  SIEVE_STORAGE_FLAG_READWRITE,
 					  &storage, &error_code) < 0) {
 		switch (error_code) {
 		case SIEVE_ERROR_NOT_POSSIBLE:
-			byemsg = "BYE \"Sieve processing is disabled for this user.\"\r\n";
-			errormsg = "Failed to open Sieve storage: "
+			*client_error_r =
+				"Sieve processing is disabled for this user";
+			*error_r = "Failed to open Sieve storage: "
 				"Sieve is disabled for this user";
 			break;
 		case SIEVE_ERROR_NOT_FOUND:
-			byemsg = "BYE \"This user cannot manage personal Sieve scripts.\"\r\n";
-			errormsg = "Failed to open Sieve storage: "
-				"Personal script storage disabled or not found.";
+			*client_error_r =
+				"This user cannot manage personal Sieve scripts";
+			*error_r = "Failed to open Sieve storage: "
+				"Personal script storage disabled or not found";
 			break;
 		default:
-			byemsg = t_strflocaltime(
-				"BYE \""CRITICAL_MSG_STAMP"\"\r\n", ioloop_time);
-			errormsg = "Failed to open Sieve storage.";
-		}
-
-		if (write(fd_out, byemsg, strlen(byemsg)) < 0) {
-			if (errno != EAGAIN && errno != EPIPE)
-				e_error(event, "write(client) failed: %m");
+			*client_error_r = t_strflocaltime(CRITICAL_MSG_STAMP,
+							  ioloop_time);
+			*error_r = "Failed to open Sieve storage.";
 		}
-		i_fatal("%s", errormsg);
+		return -1;
 	}
 
-	return storage;
+	*storage_r = storage;
+	return 0;
 }
 
 int client_create(int fd_in, int fd_out, const char *session_id,
 		  struct event *event, struct mail_user *user,
 		  const struct managesieve_settings *set,
-		  struct client **client_r, const char **error_r)
+		  struct client **client_r, const char **client_error_r,
+		  const char **error_r)
 {
 	struct client *client;
 	struct sieve_environment svenv;
@@ -112,6 +112,8 @@ int client_create(int fd_in, int fd_out, const char *session_id,
 	struct sieve_storage *storage;
 	pool_t pool;
 
+	*client_error_r = NULL;
+	*error_r = NULL;
 	*client_r = NULL;
 	*error_r = NULL;
 
@@ -132,7 +134,9 @@ int client_create(int fd_in, int fd_out, const char *session_id,
 
 	/* Get Sieve storage */
 
-	storage = client_get_storage(svinst, event, user, fd_out);
+	if (client_get_storage(svinst, user, &storage,
+			       client_error_r, error_r) < 0)
+		return -1;
 
 	/* always use nonblocking I/O */
 	net_set_nonblock(fd_in, TRUE);
diff --git a/src/managesieve/managesieve-client.h b/src/managesieve/managesieve-client.h
index c06ccb50fd59480fb560e84994ee75e1bc716b63..03f13c2f14905ab3b4c4330165beb61951e40e89 100644
--- a/src/managesieve/managesieve-client.h
+++ b/src/managesieve/managesieve-client.h
@@ -94,7 +94,8 @@ extern unsigned int managesieve_client_count;
 int client_create(int fd_in, int fd_out, const char *session_id,
 		  struct event *event, struct mail_user *user,
 		  const struct managesieve_settings *set,
-		  struct client **client_r, const char **error_r);
+		  struct client **client_r, const char **client_error_r,
+		  const char **error_r);
 void client_create_finish(struct client *client);
 void client_destroy(struct client *client, const char *reason);