dovecot-2.0-pigeonhole: Sieve filter tool: finished basic functi...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Sun Feb 13 11:27:18 EET 2011


details:   http://hg.rename-it.nl/dovecot-2.0-pigeonhole/rev/a23274a90b80
changeset: 1475:a23274a90b80
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sun Feb 13 10:27:11 2011 +0100
description:
Sieve filter tool: finished basic functionality.

diffstat:

 TODO                           |    3 +-
 doc/man/sieve-filter.1.in      |   65 ++++++---
 src/sieve-tools/sieve-filter.c |  301 ++++++++++++++++++++++++++++++++----------
 src/sieve-tools/sieve-test.c   |    4 +
 4 files changed, 278 insertions(+), 95 deletions(-)

diffs (truncated from 675 to 300 lines):

diff -r 36dddc51f9a5 -r a23274a90b80 TODO
--- a/TODO	Fri Feb 11 09:24:12 2011 +0100
+++ b/TODO	Sun Feb 13 10:27:11 2011 +0100
@@ -2,8 +2,6 @@
 
 * Build a sieve tool to filter an entire existing mailbox through a Sieve 
   script.
-* Finish the ereject extension
-	- Make reject/ereject use the LDA reject interface when available
 
 Next (in order of descending priority/precedence):
 
@@ -24,6 +22,7 @@
 * Implement index extension
 * Update include extension to latest draft (v05 currently):
 	- Implement required ManageSieve behavior (pending IETF discussion)
+* Finish the ereject extension
 * Vacation extension improvements:
 	- Implement configurable sender exclusion list.
 	- Implement mechanism for implicitly including an account's aliases in the
diff -r 36dddc51f9a5 -r a23274a90b80 doc/man/sieve-filter.1.in
--- a/doc/man/sieve-filter.1.in	Fri Feb 11 09:24:12 2011 +0100
+++ b/doc/man/sieve-filter.1.in	Sun Feb 13 10:27:11 2011 +0100
@@ -26,7 +26,7 @@
 already stored in a mailbox, for instance when a bug in a Sieve script caused
 many messages to be delivered incorrectly. Using the sieve\-filter tool it is
 possible to apply a Sieve script on all messages in a particular mailbox, making
-it possible to delete messages, to store them in a different folder and to
+it possible to delete messages, to store them in a different mailbox and to
 change the assigned IMAP flags and keywords. Attempts to send messages to the
 outside world are ignored by default for obvious reasons, but, using the proper
 command line options, it is possible to capture outgoing mail as well. 
@@ -35,7 +35,10 @@
 in which it only prints what would be performed, without actually doing
 anything. Use the \fB\-e\fP option to activate true script execution. Also, the
 source mailbox is opened read\-only by default, so that the source mailbox 
-remains unchanged. Use the \fB\-W\fP to allow changes in the source mailbox. 
+remains unchanged. Use the \fB\-W\fP option to allow changes in the source mailbox.
+And even with the \fB\-W\fP option enabled, messages in the source mailbox are
+only potentially modified and not (re)moved, unless a \fIsource\-action\fP
+argument other than \fBkeep\fP is specified.
 .SS CAUTION
 Although this is a very useful tool, it can also be very destructive when used
 improperly. A small bug in your Sieve script in combination with the wrong
@@ -73,17 +76,28 @@
 requested actions.
 .TP
 .BI \-m\  default\-mailbox
-The mailbox where the keep action stores messages. This is \(dqINBOX\(dq
-by default.
+The mailbox where the (implicit) \fBkeep\fP Sieve action stores messages. This is
+equal to the source mailbox by default. 
 .TP
-.BI \-q\  output\-mailbox
+.B \-M
+Enable move mode. This will cause all messages that were succesfully stored
+somewhere else to be expunged from the source mailbox, regardless of what the 
+\fIsource\-action\fP is (refer to Arguments section below). However, if the
+Sieve filter decides to keep the message in the source mailbox, it is left
+there and not affected by this option. 
+.IP
+Note that some Sieve actions, such as \fBredirect\fP, don't store the message
+anywhere and are thus \- with respect to the fate of the message in the source
+mailbox \- treated as if a \fBdiscard\fP action were executed. 
+.TP
+.BI \-q\  output\-mailbox\  \fR[not\ implemented\ yet]\fP
 Store outgoing e\-mail into the indicated \fIoutput\-mailbox\fP. By default,
 the sieve\-filter command ignores Sieve actions such as redirect, reject,
 vacation and notify, but using this option outgoing messages can be appended to
 the indicated mailbox. This option has no effect in simulation mode. Flags of
 redirected messages are not preserved. 
 .TP
-.BI \-Q\  mail\-command
+.BI \-Q\  mail\-command\  \fR[not\ implemented\ yet]\fP
 Send outgoing e\-mail (e.g. as produced by redirect, reject and vacation)
 through the specified program. By default, the sieve\-filter command ignores
 Sieve actions such as redirect, reject, vacation and notify, but using this
@@ -91,7 +105,7 @@
 command. This option has no effect in simulation mode. Unless you really know
 what you are doing, \fBDO NOT USE THIS TO FEED MAIL TO SENDMAIL!\fP.
 .TP
-.BI \-s\  script\-file
+.BI \-s\  script\-file\  \fR[not\ implemented\ yet]\fP
 Specify additional scripts to be executed before the main script. Multiple
 \fB\-s\fP arguments are allowed and the specified scripts are executed
 sequentially in the order specified at the command
@@ -133,21 +147,18 @@
 The name of the source mailbox.
 .TP 
 .I source\-action
-Specifies what needs to be done with messages in the source mailbox once
-processed by the Sieve script. By default, the sieve\-filter command does not
-remove the messages from the source mailbox. In particular this means that the
-keep and fileinto actions will cause the messages to be copied. To alter this
-behavior, the \fIsource\-action\fP parameter of the \fB\-R\fP option accepts
-one of the following values:
+Specifies what is done with messages in the source mailbox once processed by the
+Sieve script. The \fIsource\-action\fP parameter accepts one of the following values:
 .RS 7
 .TP 
 .BR keep\  (default)
-Keep processed messages in source folder. If \fB\-W\fR is specified and the
-source mailbox is the destination of a keep or fileinto action, flags may be
-changed by the Sieve script, but messages are never duplicated there. 
+Keep processed messages in source mailbox. When the filter decides to store the message
+in the source mailbox, it is never duplicated there. However, in that case, the
+IMAP flags of the original message can be modified by the Sieve interpreter. 
 .TP 
-.BI move\  folder
-Move processed messages to the indicated \fIfolder\fP.
+.BI move\  mailbox
+Move processed messages to the indicated \fImailbox\fP. This is for instance useful
+to move messages to a Trash mailbox. 
 .TP 
 .B delete
 Flag processed messages as \\DELETED.
@@ -155,9 +166,21 @@
 .B expunge
 Expunge processed messages, meaning that these are removed irreversibly when the
 tool finishes filtering.
-.PP
-Note that the chosen \fIsource\-action\fP only has an effect on the source
-mailbox when the \fB\-W\fP option is specified as well.
+.RE
+.IP
+The \fBsource\-action\fP is normally applied to all messages in the source mailbox,
+but there are a few exceptions:
+.RS 7
+.IP \(bu
+When the \fB\-W\fP option is not specified, the source mailbox is immutable and
+the specified \fIsource\-action\fP has no effect.
+.IP \(bu
+When the \fB-M\fR option (move mode) is active, all messages that were
+successfully moved to another mailbox are expunged irrespective of the specified 
+\fIsource\-action\fP. 
+.IP \(bu
+If the filter decides to keep the message in the source mailbox, it is left there
+and not affected by the \fIsource\-action\fP.
 .RE
 
 .\"------------------------------------------------------------------------
diff -r 36dddc51f9a5 -r a23274a90b80 src/sieve-tools/sieve-filter.c
--- a/src/sieve-tools/sieve-filter.c	Fri Feb 11 09:24:12 2011 +0100
+++ b/src/sieve-tools/sieve-filter.c	Sun Feb 13 10:27:11 2011 +0100
@@ -6,6 +6,7 @@
 #include "ioloop.h"
 #include "env-util.h"
 #include "str.h"
+#include "str-sanitize.h"
 #include "ostream.h"
 #include "array.h"
 #include "mail-namespace.h"
@@ -49,30 +50,46 @@
 	SIEVE_FILTER_SACT_EXPUNGE        /* Expunge discarded messages */
 };
 
-struct sieve_filter_context {
+struct sieve_filter_data {
 	enum sieve_filter_source_action source_action;
-	const char *move_mailbox;
+	struct mailbox *move_mailbox;
 
 	struct sieve_script_env *senv;
 	struct sieve_binary *main_sbin;
 	struct sieve_error_handler *ehandler;
+
+	unsigned int execute:1;
+	unsigned int source_write:1;
+	unsigned int move_mode:1;
+};
+
+struct sieve_filter_context {
+	const struct sieve_filter_data *data;
+
+	struct mailbox_transaction_context *move_trans;
+
+	struct ostream *teststream;
 };
 
 static int filter_message
 (struct sieve_filter_context *sfctx, struct mail *mail)
 {
-	struct sieve_error_handler *ehandler = sfctx->ehandler; 
+	struct sieve_error_handler *ehandler = sfctx->data->ehandler; 
+	struct sieve_script_env *senv = sfctx->data->senv;
 	struct sieve_exec_status estatus;
 	struct sieve_binary *sbin;
 	struct sieve_message_data msgdata;
 	const char *recipient, *sender;
+	bool execute = sfctx->data->execute;
+	bool source_write = sfctx->data->source_write;
+	bool move_mode = sfctx->data->move_mode;
 	int ret;
 
 	sieve_tool_get_envelope_data(mail, &recipient, &sender);
 
 	/* Initialize execution status */
 	memset(&estatus, 0, sizeof(estatus));
-	sfctx->senv->exec_status = &estatus;
+	senv->exec_status = &estatus;
 
 	/* Collect necessary message data */
 	memset(&msgdata, 0, sizeof(msgdata));
@@ -80,44 +97,91 @@
 	msgdata.return_path = sender;
 	msgdata.orig_envelope_to = recipient;
 	msgdata.final_envelope_to = recipient;
-	msgdata.auth_user = sfctx->senv->username;
+	msgdata.auth_user = senv->username;
 	(void)mail_get_first_header(mail, "Message-ID", &msgdata.id);
 
 	/* Single script */
-	sbin = sfctx->main_sbin;
+	sbin = sfctx->data->main_sbin;
 
 	/* Execute script */
-	ret = sieve_execute(sbin, &msgdata, sfctx->senv, ehandler, NULL);
+	if ( execute ) {
+		ret = sieve_execute(sbin, &msgdata, senv, ehandler, NULL);
+	} else {
+		ret = sieve_test
+			(sbin, &msgdata, senv, ehandler, sfctx->teststream, NULL);
+	}
 
 	/* Handle message in source folder */
-	if ( ret > 0 && !estatus.keep_original ) {
-		switch ( sfctx->source_action ) {
-		/* Leave it there */
-		case SIEVE_FILTER_SACT_KEEP:
-			sieve_info(ehandler, NULL, "message left in source mailbox");
-			break;
-		/* Move message to Trash folder */
-		case SIEVE_FILTER_SACT_MOVE:			
-			sieve_info(ehandler, NULL, 
-				"message in source mailbox moved to mailbox '%s'", sfctx->move_mailbox);
-			break;
-		/* Flag message as \DELETED */
-		case SIEVE_FILTER_SACT_DELETE:					
-			sieve_info(ehandler, NULL, "message flagged as deleted in source mailbox");
-			mail_update_flags(mail, MODIFY_ADD, MAIL_DELETED);
-			break;
-		/* Expunge the message immediately */
-		case SIEVE_FILTER_SACT_EXPUNGE:
-			sieve_info(ehandler, NULL, "message expunged from source mailbox");
-			mail_expunge(mail);
-			break;
-		/* Unknown */
-		default:
-			i_unreached();
-			break;
+	if ( ret > 0 ) {
+		struct mailbox *move_box = sfctx->data->move_mailbox;
+		enum sieve_filter_source_action source_action =
+			sfctx->data->source_action;
+
+		if ( !source_write ) {
+			/* Do nothing */
+
+		} else if ( estatus.keep_original  ) {
+			sieve_info(ehandler, NULL, "message kept in source mailbox");
+
+		} else if ( move_mode && estatus.message_saved ) {
+			sieve_info(ehandler, NULL,
+				"message expunged from source mailbox upon successful move");
+
+			if ( execute )
+				mail_expunge(mail);
+
+		} else {
+			switch ( source_action ) {
+			/* Leave it there */
+			case SIEVE_FILTER_SACT_KEEP:
+				sieve_info(ehandler, NULL, "message left in source mailbox");
+				break;
+			/* Move message to indicated folder */
+			case SIEVE_FILTER_SACT_MOVE:			
+				sieve_info(ehandler, NULL, 
+					"message in source mailbox moved to mailbox '%s'",
+					mailbox_get_name(move_box));
+
+				if ( execute && move_box != NULL ) {
+					struct mailbox_transaction_context *t = sfctx->move_trans;
+					struct mail_save_context *save_ctx;
+	
+				    save_ctx = mailbox_save_alloc(t);
+
+					if ( mailbox_copy(&save_ctx, mail) < 0 ) {
+						enum mail_error error;
+						const char *errstr;
+	
+						errstr = mail_storage_get_last_error
+							(mailbox_get_storage(move_box), &error);
+
+						sieve_error(ehandler, NULL,
+							"failed to move message to mailbox %s: %s",
+							mailbox_get_name(move_box), errstr);
+						return -1;
+				    }
+			
+					mail_expunge(mail);


More information about the dovecot-cvs mailing list