Commit 8bf6d372 8bf6d37210f6dc0136007dd9a973a7426cce55fb by Sergey Poznyakoff

sieve: improve moderator extension.

* libmu_sieve/extensions/moderator.c: Implement the :program tag.
Use _sget_ functions to reduce memory requirements.
* sieve/tests/moderator.mbox: New file.
* sieve/tests/moderator.at: New file.
* sieve/tests/Makefile.am (EXTRA_DIST): Add moderator.mbox.
(TESTSUITE_AT): Add moderator.at
* sieve/tests/testsuite.at (MUT_SIEVE_EXT_NAME): New define.
(MUT_SIEVE_EXT_TEST): New macro.
Include moderator.at.
1 parent 6824980f
......@@ -31,6 +31,7 @@
moderator [:keep]
[:address <address: string>]
[:program <sieve-program: string>]
[:source <sieve-file: string>]
The moderator action spawns an inferior Sieve machine and filters the
......@@ -40,9 +41,15 @@
reply can be modified using :address tag. After discarding the message,
moderator marks it as deleted, unless it is given :keep tag.
If :source tag is given, its argument sieve-file specifies the Sieve
source file to be used on the message. Otherwise, moderator will create
a copy of the existing Sieve machine.
If :source tag is given, its argument sieve-file specifies a Sieve
source file to be used on the message. If :program tag is given, its
argument supplies a Sieve program to be used on this message. Only
one of :program or :source may be specified. Supplying them both, or
supplying several instances of the same keyword, is an error. The
behavior of the action in this case is undefined.
If neither :program nor :source is supplied, moderator will create
a copy of the existing Sieve machine and use it on the message.
The action checks the message structure: it will bail out if the message
does not have exactly 3 MIME parts, or if parts 2 and 3 are not of
......@@ -93,6 +100,24 @@ moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags,
if (rc)
mu_sieve_error (mach, _("cannot compile source `%s'"), arg->v.string);
}
else if (mu_sieve_tag_lookup (tags, "program", &arg))
{
struct mu_locus locus;
rc = mu_sieve_machine_inherit (mach, &newmach);
if (rc)
{
mu_sieve_error (mach, _("cannot initialize sieve machine: %s"),
mu_strerror (rc));
return 1;
}
mu_sieve_get_locus (mach, &locus);
rc = mu_sieve_compile_buffer (newmach,
arg->v.string, strlen (arg->v.string),
locus.mu_file, locus.mu_line);
if (rc)
mu_sieve_error (mach, _("cannot compile subprogram"));
}
else
rc = mu_sieve_machine_dup (mach, &newmach);
......@@ -119,15 +144,15 @@ copy_header (mu_sieve_machine_t mach,
mu_header_t to_hdr, char *to, mu_header_t from_hdr, char *from)
{
int rc;
char *value = NULL;
if ((rc = mu_header_aget_value (from_hdr, from, &value)))
const char *value = NULL;
if ((rc = mu_header_sget_value (from_hdr, from, &value)))
{
mu_sieve_error (mach, _("cannot get `%s:' header: %s"),
from, mu_strerror (rc));
return rc;
}
rc = mu_header_set_value (to_hdr, to, value, 0);
free (value);
return rc;
}
......@@ -194,7 +219,7 @@ moderator_message_get_part (mu_sieve_machine_t mach,
int rc;
mu_message_t tmp;
mu_header_t hdr = NULL;
char *value;
const char *value;
if ((rc = mu_message_get_part (msg, index, &tmp)))
{
......@@ -204,13 +229,12 @@ moderator_message_get_part (mu_sieve_machine_t mach,
}
mu_message_get_header (tmp, &hdr);
if (mu_header_aget_value (hdr, MU_HEADER_CONTENT_TYPE, &value) == 0
if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TYPE, &value) == 0
&& memcmp (value, "message/rfc822", 14) == 0)
{
mu_stream_t str;
mu_body_t body;
free (value);
mu_message_get_body (tmp, &body);
mu_body_get_streamref (body, &str);
......@@ -229,7 +253,6 @@ moderator_message_get_part (mu_sieve_machine_t mach,
mu_sieve_error (mach,
_("expected message type message/rfc822, but found %s"),
value);
free (value);
return 1;
}
else
......@@ -333,6 +356,7 @@ static mu_sieve_tag_def_t moderator_tags[] = {
{ "keep", SVT_VOID },
{ "address", SVT_STRING },
{ "source", SVT_STRING },
{ "program", SVT_STRING },
{ NULL }
};
......
......@@ -95,7 +95,7 @@ spamd_send_message (mu_stream_t stream, mu_message_t msg)
rc = mu_message_get_streamref (msg, &mstr);
if (rc)
return rc;
rc = mu_filter_create (&flt, mstr, "rfc822", MU_FILTER_ENCODE,
rc = mu_filter_create (&flt, mstr, "CRLF", MU_FILTER_ENCODE,
MU_STREAM_READ|MU_STREAM_SEEK);
if (rc)
{
......@@ -264,7 +264,7 @@ spamd_test (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
{
mu_sieve_debug (mach, "spamd_test %lu",
(unsigned long) mu_sieve_get_message_num (mach));
(unsigned long) mu_sieve_get_message_num (mach));
}
if (mu_sieve_is_dry_run (mach))
......
......@@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4
EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 moderator.mbox
DISTCLEANFILES = atconfig $(check_SCRIPTS)
MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE)
#SUBDIRS = etc
......@@ -53,6 +53,7 @@ TESTSUITE_AT = \
i-casemap.at\
i-numeric.at\
i-octet.at\
moderator.at\
mul-addr.at\
not.at\
redirect.at\
......
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
#
# GNU Mailutils is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or (at
# your option) any later version.
#
# GNU Mailutils is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
m4_pushdef([MUT_SIEVE_EXT_NAME],[moderator])
MUT_SIEVE_EXT_TEST([program discard],[mod00],
[require "moderator";
moderator :program "discard;";
],
[cp ${abs_top_srcdir}/sieve/tests/moderator.mbox mailbox
chmod +w mailbox
MTA_DIAG=`pwd`/mta.diag
export MTA_DIAG
sieve MUT_SIEVE_CMDLINE dnl
--clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit 1
sed 's/ENVELOPE FROM:.*/ENVELOPE FROM/' ./mta.diag
],
[ENVELOPE FROM
ENVELOPE TO: <bug-foobar-request@example.org>
0: Subject: confirm 7e02c99a82a21a2349291a4f142ee2347bb5fd0b
1: To: bug-foobar-request@example.org
2:
END OF MESSAGE
],
[DISCARD on msg uid 0: marking as deleted
MODERATOR on msg uid 1: discarding message
])
MUT_SIEVE_EXT_TEST([program address discard],[mod01],
[require "moderator";
moderator :program "discard;" :address "<sergiusz@example.org>";
],
[cp ${abs_top_srcdir}/sieve/tests/moderator.mbox mailbox
chmod +w mailbox
MTA_DIAG=`pwd`/mta.diag
export MTA_DIAG
sieve MUT_SIEVE_CMDLINE dnl
--clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit 1
cat ./mta.diag
],
[ENVELOPE FROM: sergiusz@example.org
ENVELOPE TO: <bug-foobar-request@example.org>
0: From: <sergiusz@example.org>
1: Subject: confirm 7e02c99a82a21a2349291a4f142ee2347bb5fd0b
2: To: bug-foobar-request@example.org
3:
END OF MESSAGE
],
[DISCARD on msg uid 0: marking as deleted
MODERATOR on msg uid 1: discarding message
])
MUT_SIEVE_EXT_TEST([program keep],[mod02],
[require "moderator";
moderator :program "keep;";
],
[cp ${abs_top_srcdir}/sieve/tests/moderator.mbox mailbox
chmod +w mailbox
MTA_DIAG=`pwd`/mta.diag
export MTA_DIAG
sieve MUT_SIEVE_CMDLINE dnl
--clearpath -L "${abs_top_builddir}/libmu_sieve/extensions" -f ./mailbox prog || exit $?
test -f ./mta.diag && echo ./mta.diag
exit 0
],
[],
[KEEP on msg uid 0
MODERATOR on msg uid 1: keeping message
])
m4_popdef([MUT_SIEVE_EXT_NAME])
From mailman-bounces@example.org Sat Jul 2 01:36:47 2005
Subject: Bug-foobar post from somebody@example.com requires approval
From: bug-foobar-owner@example.org
To: bug-foobar-owner@example.org
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="===============1223730756=="
Message-ID: <mailman.16340.1120257323.2856.bug-foobar@example.org>
Date: Fri, 01 Jul 2005 18:35:23 -0400
Precedence: bulk
X-BeenThere: bug-foobar@example.org
X-Mailman-Version: 2.1.5
List-Id: Bug reports for GNU foobar <bug-foobar.example.org>
X-List-Administrivia: yes
Sender: mailman-bounces@example.org
Errors-To: mailman-bounces@example.org
X-IMAPbase: 1292609256 2
Status:
X-UID: 1
--===============1223730756==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
As list administrator, your authorization is requested for the
following mailing list posting:
List: Bug-foobar@example.org
From: somebody@example.com
Subject: Problems building foobar
Reason: Post by non-member to a members-only list
At your convenience, visit:
http://lists.example.org/mailman/admindb/bug-foobar
to approve or deny the request.
--===============1223730756==
Content-Type: message/rfc822
MIME-Version: 1.0
Envelope-to: bug-foobar@example.org
Subject: Problems building foobar
Date: Fri, 1 Jul 2005 15:26:59 -0700
Message-ID: <7A2E278D550047489A84AC706B36D595250E75@example.com>
Thread-Topic: Problems building foobar
Thread-Index: AcV+i/85qSfLCmCAToipt+481y99vw==
From: somebody@example.com
To: <bug-foobar@example.org>
Hi,
I'm trying to build foobar under Linux and am getting the following
error. Please help.
blah blah blah
--===============1223730756==
Content-Type: message/rfc822
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: confirm 7e02c99a82a21a2349291a4f142ee2347bb5fd0b
Sender: bug-foobar-request@example.org
From: bug-foobar-request@example.org
If you reply to this message, keeping the Subject: header intact,
Mailman will discard the held message. Do this if the message is
spam. If you reply to this message and include an Approved: header
with the list password in it, the message will be approved for posting
to the list. The Approved: header can also appear in the first line
of the body of the reply.
--===============1223730756==--
......@@ -78,6 +78,27 @@ m4_define([MUT_PREREQ_CAPA],[
sieve --show-config-options | grep '^$1' > /dev/null 2>&1 || AT_SKIP_TEST
])
dnl ------------------------------------------------------------
m4_define([MUT_SIEVE_EXT_NAME])
dnl ------------------------------------------------------------
dnl MUT_SIEVE_EXT_TEST([NAME],[KW = `'], [PROG], [TEST],
dnl [STDOUT = `'],[STDERR = `'])
m4_define([MUT_SIEVE_EXT_TEST],[
AT_SETUP(MUT_SIEVE_EXT_NAME[: $1])
AT_KEYWORDS([MUT_SIEVE_EXT_NAME $2])
AT_CHECK([
MUT_PREREQ_CAPA([HAVE_LIBLTDL])
AT_DATA([prog],[$3])
$4
],
[0],
[$5],[$6])
AT_CLEANUP])
AT_INIT
AT_TESTED([sieve])
......@@ -103,5 +124,7 @@ m4_include([size.at])
m4_include([redirect.at])
m4_include([reject.at])
m4_include([ext.at])
m4_include([moderator.at])
......