From 7e18cd0bd19e1767a9f4651b7c00ab19085bfb79 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 11 Oct 2012 20:26:03 +0200
Subject: [PATCH] lib-sieve: Further improved handling of quota errors. Added
 means to log user errors/warnings as info in master log. Previous change was
 inadequate because an error was still logged.

---
 src/lib-sieve/sieve-actions.c            | 12 ++--
 src/lib-sieve/sieve-error-private.h      |  3 +-
 src/lib-sieve/sieve-error.c              | 76 +++++++++++++++++++++---
 src/lib-sieve/sieve-error.h              | 17 ++++++
 src/lib-sieve/sieve-result.c             | 21 ++++++-
 src/lib-sieve/sieve-result.h             |  6 ++
 src/plugins/lda-sieve/lda-sieve-plugin.c | 18 +++++-
 7 files changed, 135 insertions(+), 18 deletions(-)

diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index cfa443591..f90bf36ab 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -604,13 +604,15 @@ static void act_store_log_status
 				(mailbox_get_storage(trans->box), &error_code);
 		}
 
-		if ( error_code != MAIL_ERROR_NOTFOUND && error_code != MAIL_ERROR_PARAMS &&
-			error_code != MAIL_ERROR_NOSPACE)
-		{
-			sieve_result_global_error(aenv, "failed to store into mailbox %s: %s",
+		if ( error_code == MAIL_ERROR_NOTFOUND ||
+			error_code == MAIL_ERROR_PARAMS ) {
+			sieve_result_error(aenv, "failed to store into mailbox %s: %s",
 				mailbox_name, errstr);
+		} else if ( error_code == MAIL_ERROR_NOSPACE ) {
+			sieve_result_global_log_error
+				(aenv, "failed to store into mailbox %s: %s", mailbox_name, errstr);
 		} else {
-			sieve_result_error(aenv, "failed to store into mailbox %s: %s",
+			sieve_result_global_error(aenv, "failed to store into mailbox %s: %s",
 				mailbox_name, errstr);
 		}
 
diff --git a/src/lib-sieve/sieve-error-private.h b/src/lib-sieve/sieve-error-private.h
index 7a30cbcae..50d03a732 100644
--- a/src/lib-sieve/sieve-error-private.h
+++ b/src/lib-sieve/sieve-error-private.h
@@ -11,7 +11,8 @@
  */
 
 enum sieve_error_flags {
-	SIEVE_ERROR_FLAG_GLOBAL = (1 << 0)
+	SIEVE_ERROR_FLAG_GLOBAL = (1 << 0),
+	SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO = (1 << 1),
 };
 
 /*
diff --git a/src/lib-sieve/sieve-error.c b/src/lib-sieve/sieve-error.c
index b14bef8d7..30c2a2f57 100644
--- a/src/lib-sieve/sieve-error.c
+++ b/src/lib-sieve/sieve-error.c
@@ -84,11 +84,17 @@ void sieve_direct_verror
 
 		VA_COPY(args_copy, args);
 
-		svinst->system_ehandler->verror
-			(svinst->system_ehandler, 0, location, fmt, args_copy);
+		if ( (flags & SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO) != 0 ) {
+			svinst->system_ehandler->vinfo
+				(svinst->system_ehandler, 0, location, fmt, args_copy);
+		} else {
+			svinst->system_ehandler->verror
+				(svinst->system_ehandler, 0, location, fmt, args_copy);
+		}
 	}
 
-	if ( ehandler == NULL ) return;
+	if ( ehandler == NULL )
+		return;
 
 	if ( ehandler->parent != NULL || sieve_errors_more_allowed(ehandler) ) {
 		if ( ehandler->verror != NULL )
@@ -111,11 +117,17 @@ void sieve_direct_vwarning
 
 		VA_COPY(args_copy, args);
 
-		svinst->system_ehandler->vwarning
-			(svinst->system_ehandler, 0, location, fmt, args_copy);
+		if ( (flags & SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO) != 0 ) {
+			svinst->system_ehandler->vinfo
+				(svinst->system_ehandler, 0, location, fmt, args_copy);
+		} else {
+			svinst->system_ehandler->vwarning
+				(svinst->system_ehandler, 0, location, fmt, args_copy);
+		}
 	}
 
-	if ( ehandler == NULL ) return;
+	if ( ehandler == NULL )
+		return;
 
 	if ( ehandler->vwarning != NULL )
 		ehandler->vwarning(ehandler, flags, location, fmt, args);
@@ -140,7 +152,8 @@ void sieve_direct_vinfo
 			(svinst->system_ehandler, 0, location, fmt, args_copy);
 	}
 
-	if ( ehandler == NULL ) return;
+	if ( ehandler == NULL )
+		return;
 
 	if ( ehandler->parent != NULL || ehandler->log_info ) {
 		if ( ehandler->vinfo != NULL )
@@ -164,7 +177,8 @@ void sieve_direct_vdebug
 			(svinst->system_ehandler, 0, location, fmt, args_copy);
 	}
 
-	if ( ehandler == NULL ) return;
+	if ( ehandler == NULL )
+		return;
 
 	if ( ehandler->parent != NULL || ehandler->log_debug ) {
 		if ( ehandler->vdebug != NULL )
@@ -300,6 +314,24 @@ void sieve_global_vinfo
 		(svinst, ehandler, SIEVE_ERROR_FLAG_GLOBAL, location, fmt, args);
 }
 
+void sieve_global_info_verror
+(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+	const char *location, const char *fmt, va_list args)
+{
+	sieve_direct_verror(svinst, ehandler,
+		(SIEVE_ERROR_FLAG_GLOBAL | SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO),
+		location, fmt, args);
+}
+
+void sieve_global_info_vwarning
+(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+	const char *location, const char *fmt, va_list args)
+{
+	sieve_direct_vwarning(svinst, ehandler,
+		(SIEVE_ERROR_FLAG_GLOBAL | SIEVE_ERROR_FLAG_GLOBAL_MAX_INFO),
+		location, fmt, args);
+}
+
 void sieve_global_error
 (struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
 	const char *location, const char *fmt, ...)
@@ -342,6 +374,34 @@ void sieve_global_info
 	va_end(args);
 }
 
+void sieve_global_info_error
+(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+	const char *location, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+
+	T_BEGIN {
+		sieve_global_info_verror(svinst, ehandler, location, fmt, args);
+	} T_END;
+
+	va_end(args);
+}
+
+void sieve_global_info_warning
+(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+	const char *location, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+
+	T_BEGIN {
+		sieve_global_info_vwarning(svinst, ehandler, location, fmt, args);
+	} T_END;
+
+	va_end(args);
+}
+
 /*
  * Default (user) error functions
  */
diff --git a/src/lib-sieve/sieve-error.h b/src/lib-sieve/sieve-error.h
index cafd9347c..3fc36dc8d 100644
--- a/src/lib-sieve/sieve-error.h
+++ b/src/lib-sieve/sieve-error.h
@@ -30,6 +30,11 @@ typedef void (*sieve_error_func_t)
 	(struct sieve_error_handler *ehandler, const char *location,
 		const char *fmt, ...) ATTR_FORMAT(3, 4);
 
+typedef void (*sieve_sys_error_vfunc_t)
+	(struct sieve_instance *svinst, const char *fmt, va_list args);
+typedef void (*sieve_sys_error_func_t)
+	(struct sieve_instance *svinst, const char *fmt, ...) ATTR_FORMAT(2, 3);
+
 /*
  * System errors
  */
@@ -70,6 +75,12 @@ void sieve_global_vwarning
 void sieve_global_vinfo
 	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
 		const char *location, const char *fmt, va_list args);
+void sieve_global_info_verror
+	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+		const char *location, const char *fmt, va_list args);
+void sieve_global_info_vwarning
+	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+		const char *location, const char *fmt, va_list args);
 
 void sieve_global_error
 	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
@@ -80,6 +91,12 @@ void sieve_global_warning
 void sieve_global_info
 	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
 		const char *location, const char *fmt, ...) ATTR_FORMAT(4, 5);
+void sieve_global_info_error
+	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+		const char *location, const char *fmt, ...) ATTR_FORMAT(4, 5);
+void sieve_global_info_warning
+	(struct sieve_instance *svinst, struct sieve_error_handler *ehandler,
+		const char *location, const char *fmt, ...) ATTR_FORMAT(4, 5);
 
 /*
  * Main (user) error functions
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index b3ca760fd..2f9fc9241 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -272,7 +272,6 @@ void sieve_result_global_warning
 	va_end(args);
 }
 
-
 void sieve_result_log
 (const struct sieve_action_exec_env *aenv, const char *fmt, ...)
 {
@@ -293,6 +292,26 @@ void sieve_result_global_log
 	va_end(args);
 }
 
+void sieve_result_global_log_error
+(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	sieve_global_info_verror(aenv->svinst, aenv->ehandler, NULL, fmt, args);
+	va_end(args);
+}
+
+void sieve_result_global_log_warning
+(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	sieve_global_info_vwarning(aenv->svinst, aenv->ehandler, NULL, fmt, args);
+	va_end(args);
+}
+
 /*
  * Result composition
  */
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index 0533f5da3..04ceaa126 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -103,6 +103,12 @@ void sieve_result_log
 (const struct sieve_action_exec_env *aenv, const char *fmt, ...)
 	ATTR_FORMAT(2, 3);
 void sieve_result_global_log
+(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
+	ATTR_FORMAT(2, 3);
+void sieve_result_global_log_error
+(const struct sieve_action_exec_env *aenv, const char *fmt, ...)
+	ATTR_FORMAT(2, 3);
+void sieve_result_global_log_warning
 (const struct sieve_action_exec_env *aenv, const char *fmt, ...)
 	ATTR_FORMAT(2, 3);
 
diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c
index 128e125d9..a2ebc7a8e 100644
--- a/src/plugins/lda-sieve/lda-sieve-plugin.c
+++ b/src/plugins/lda-sieve/lda-sieve-plugin.c
@@ -353,17 +353,29 @@ static int lda_sieve_handle_exec_status
 (struct lda_sieve_run_context *srctx, struct sieve_script *script, int status)
 {
 	struct sieve_instance *svinst = srctx->svinst;
+	struct sieve_exec_status *estatus = srctx->scriptenv->exec_status;
 	const char *userlog_notice = "";
+	sieve_sys_error_func_t error_func = sieve_sys_error;
 	int ret;
 
+	if ( estatus != NULL && estatus->last_storage != NULL ) {
+		enum mail_error mail_error;
+
+		mail_storage_get_last_error(estatus->last_storage, &mail_error);
+
+		/* Don't bother administrator too much with benign errors */
+		if ( mail_error == MAIL_ERROR_NOSPACE )
+			error_func = sieve_sys_info;
+	}
+
 	if ( script == srctx->user_script && srctx->userlog != NULL ) {
 		userlog_notice = t_strdup_printf
-			(" (user logfile %s may reveal additional details)", srctx->userlog);
+			(" (user logfile %s should reveal additional details)", srctx->userlog);
 	}
 
 	switch ( status ) {
 	case SIEVE_EXEC_FAILURE:
-		sieve_sys_error(svinst,
+		error_func(svinst,
 			"execution of script %s failed, but implicit keep was successful%s",
 			sieve_script_location(script), userlog_notice);
 		ret = 1;
@@ -376,7 +388,7 @@ static int lda_sieve_handle_exec_status
 		ret = -1;
 		break;
 	case SIEVE_EXEC_KEEP_FAILED:
-		sieve_sys_error(svinst,
+		error_func(svinst,
 			"script %s failed with unsuccessful implicit keep%s",
 			sieve_script_location(script), userlog_notice);
 		ret = -1;
-- 
GitLab