Skip to content
Snippets Groups Projects
Commit 600afb87 authored by Stephan Bosch's avatar Stephan Bosch
Browse files

Sieve-filter: implemented basic filtering with source mailbox actions.

parent e56cdec7
No related branches found
No related tags found
No related merge requests found
......@@ -14,6 +14,7 @@ implements.
.RI [ options ]
.I script\-file
.I source\-mailbox
.RI [ source\-action ]
.SH DESCRIPTION
.PP
The \fBsieve\-filter\fP command is part of the Pigeonhole Project
......@@ -88,34 +89,6 @@ Sieve actions such as redirect, reject, vacation and notify, but using this
option outgoing messages can be fed to the \fBstdin\fP of an external shell
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 \-R\ 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:
.RS 7
.TP
\fBkeep\fP (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.
.TP
\fBflag\fP
Flag processed messages as \\DELETED.
.TP
\fBmove\fP [\fIfolder\fP]
Move processed messages to the indicated \fIfolder\fP.
.TP
\fBexpunge\fP
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
.TP
.BI \-s\ script\-file
Specify additional scripts to be executed before the main script. Multiple
......@@ -157,6 +130,35 @@ into a new binary.
.TP
.I source\-mailbox
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:
.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.
.TP
.BI move\ folder
Move processed messages to the indicated \fIfolder\fP.
.TP
.B delete
Flag processed messages as \\DELETED.
.TP
.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
.\"------------------------------------------------------------------------
.SH EXAMPLES
......
......@@ -35,33 +35,33 @@
static void print_help(void)
{
printf(
"Usage: sieve-filter [-m <mailbox>] [-x <extensions>] [-s <script-file>] [-c]\n"
" <script-file> <src-mail-store> [<dest-mail-store>]\n"
"Usage: sieve-filter [-c <config-file>] [-C] [-D] [-e]\n"
" [-m <default-mailbox>] [-P <plugin>]\n"
" [-r <recipient-address>] [-s <script-file>]\n"
" [-t <trace-file>] [-T <trace-option>] [-x <extensions>]\n"
" <script-file> <mail-file>\n"
"Usage: sieve-filter [-c <config-file>] [-C] [-D] [-e] [-m <default-mailbox>]\n"
" [-P <plugin>] [-q <output-mailbox>] [-Q <mail-command>]\n"
" [-s <script-file>] [-u <user>] [-W] [-x <extensions>]\n"
" <script-file> <source-mailbox> <source-action>\n"
);
}
enum source_action_type {
SOURCE_ACTION_KEEP, /* Always keep messages in source folder */
SOURCE_ACTION_DELETE, /* Flag discarded messages as \DELETED */
SOURCE_ACTION_TRASH_FOLDER, /* Move discarded messages to Trash folder */
SOURCE_ACTION_EXPUNGE /* Expunge discarded messages */
enum sieve_filter_source_action {
SIEVE_FILTER_SACT_KEEP, /* Always keep messages in source folder */
SIEVE_FILTER_SACT_MOVE, /* Move discarded messages to Trash folder */
SIEVE_FILTER_SACT_DELETE, /* Flag discarded messages as \DELETED */
SIEVE_FILTER_SACT_EXPUNGE /* Expunge discarded messages */
};
struct source_action {
enum source_action_type type;
const char *trash_folder;
struct sieve_filter_context {
enum sieve_filter_source_action source_action;
const char *move_mailbox;
struct sieve_script_env *senv;
struct sieve_binary *main_sbin;
struct sieve_error_handler *ehandler;
};
static int filter_message
(struct mail *mail, struct sieve_binary *main_sbin,
struct sieve_script_env *senv, struct sieve_error_handler *ehandler,
struct source_action source_action)
(struct sieve_filter_context *sfctx, struct mail *mail)
{
struct sieve_error_handler *ehandler = sfctx->ehandler;
struct sieve_exec_status estatus;
struct sieve_binary *sbin;
struct sieve_message_data msgdata;
......@@ -72,7 +72,7 @@ static int filter_message
/* Initialize execution status */
memset(&estatus, 0, sizeof(estatus));
senv->exec_status = &estatus;
sfctx->senv->exec_status = &estatus;
/* Collect necessary message data */
memset(&msgdata, 0, sizeof(msgdata));
......@@ -80,37 +80,35 @@ static int filter_message
msgdata.return_path = sender;
msgdata.orig_envelope_to = recipient;
msgdata.final_envelope_to = recipient;
msgdata.auth_user = senv->username;
msgdata.auth_user = sfctx->senv->username;
(void)mail_get_first_header(mail, "Message-ID", &msgdata.id);
/* Single script */
sbin = main_sbin;
main_sbin = NULL;
sbin = sfctx->main_sbin;
/* Execute script */
ret = sieve_execute(sbin, &msgdata, senv, ehandler, NULL);
ret = sieve_execute(sbin, &msgdata, sfctx->senv, ehandler, NULL);
/* Handle message in source folder */
if ( ret > 0 && !estatus.keep_original ) {
switch ( source_action.type ) {
switch ( sfctx->source_action ) {
/* Leave it there */
case SOURCE_ACTION_KEEP:
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 SOURCE_ACTION_DELETE:
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;
/* Move message to Trash folder */
case SOURCE_ACTION_TRASH_FOLDER:
sieve_info(ehandler, NULL,
"message in source folder moved to folder '%s'",
source_action.trash_folder);
break;
/* Expunge the message immediately */
case SOURCE_ACTION_EXPUNGE:
sieve_info(ehandler, NULL, "message removed from source folder");
case SIEVE_FILTER_SACT_EXPUNGE:
sieve_info(ehandler, NULL, "message expunged from source mailbox");
mail_expunge(mail);
break;
/* Unknown */
......@@ -118,6 +116,8 @@ static int filter_message
i_unreached();
break;
}
} else {
sieve_info(ehandler, NULL, "message left in source mailbox");
}
return ret;
......@@ -139,10 +139,9 @@ static void mail_search_build_add_flags
}
static int filter_mailbox
(struct mailbox *src_box, struct sieve_binary *main_sbin,
struct sieve_script_env *senv, struct sieve_error_handler *ehandler,
struct source_action source_action)
(struct sieve_filter_context *sfctx, struct mailbox *src_box)
{
struct sieve_error_handler *ehandler = sfctx->ehandler;
struct mail_search_args *search_args;
struct mailbox_transaction_context *t;
struct mail_search_context *search_ctx;
......@@ -189,7 +188,7 @@ static int filter_mailbox
sieve_info(ehandler, NULL,
"filtering: [%s; %"PRIuUOFF_T" bytes] %s", date, size, subject);
ret = filter_message(mail, main_sbin, senv, ehandler, source_action);
ret = filter_message(sfctx, mail);
}
mail_free(&mail);
......@@ -235,8 +234,9 @@ int main(int argc, char **argv)
{
struct sieve_instance *svinst;
ARRAY_TYPE (const_string) scriptfiles;
const char *scriptfile, *src_mailbox, *dst_mailbox;
struct source_action source_action = { SOURCE_ACTION_KEEP, "Trash" };
const char *scriptfile, *src_mailbox, *dst_mailbox, *move_mailbox;
struct sieve_filter_context sfctx;
enum sieve_filter_source_action source_action = SIEVE_FILTER_SACT_KEEP;
struct mail_user *mail_user;
struct sieve_binary *main_sbin;
struct sieve_script_env scriptenv;
......@@ -249,13 +249,15 @@ int main(int argc, char **argv)
enum mail_error error;
int c;
sieve_tool = sieve_tool_init("sieve-filter", &argc, &argv, "m:s:x:P:CD", FALSE);
sieve_tool = sieve_tool_init("sieve-filter", &argc, &argv,
"R:m:s:x:P:CD", FALSE);
t_array_init(&scriptfiles, 16);
/* Parse arguments */
scriptfile = NULL;
src_mailbox = dst_mailbox = "INBOX";
move_mailbox = "Trash";
force_compile = FALSE;
while ((c = sieve_tool_getopt(sieve_tool)) > 0) {
switch (c) {
......@@ -305,6 +307,26 @@ int main(int argc, char **argv)
print_help();
i_fatal_status(EX_USAGE, "Missing <source-mailbox> argument");
}
if ( optind < argc ) {
const char *srcact = argv[optind++];
if ( strcmp(srcact, "keep") == 0 ) {
source_action = SIEVE_FILTER_SACT_KEEP;
} else if ( strcmp(srcact, "move") == 0 ) {
source_action = SIEVE_FILTER_SACT_MOVE;
if ( optind < argc ) {
move_mailbox = t_strdup(argv[optind++]);
}
} else if ( strcmp(srcact, "flag") == 0 ) {
source_action = SIEVE_FILTER_SACT_DELETE;
} else if ( strcmp(srcact, "expunge") == 0 ) {
source_action = SIEVE_FILTER_SACT_EXPUNGE;
} else {
print_help();
i_fatal_status(EX_USAGE, "Invalid <source-action> argument");
}
}
if ( optind != argc ) {
print_help();
......@@ -359,9 +381,16 @@ int main(int argc, char **argv)
scriptenv.smtp_open = NULL;
scriptenv.smtp_close = NULL;
/* Compose filter context */
memset(&sfctx, 0, sizeof(sfctx));
sfctx.senv = &scriptenv;
sfctx.source_action = source_action;
sfctx.move_mailbox = move_mailbox;
sfctx.main_sbin = main_sbin;
sfctx.ehandler = ehandler;
/* Apply Sieve filter to all messages found */
(void) filter_mailbox
(src_box, main_sbin, &scriptenv, ehandler, source_action);
(void) filter_mailbox(&sfctx, src_box);
/* Close the mailbox */
if ( src_box != NULL )
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment

Consent

On this website, we use the web analytics service Matomo to analyze and review the use of our website. Through the collected statistics, we can improve our offerings and make them more appealing for you. Here, you can decide whether to allow us to process your data and set corresponding cookies for these purposes, in addition to technically necessary cookies. Further information on data protection—especially regarding "cookies" and "Matomo"—can be found in our privacy policy. You can withdraw your consent at any time.