diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | doc/mailfromd.texi | 98 | ||||
-rw-r--r-- | src/main.c | 398 | ||||
-rw-r--r-- | tests/atlocal.in | 2 |
4 files changed, 439 insertions, 66 deletions
@@ -2,2 +2,9 @@ | |||
2 | 2 | ||
3 | * src/main.c: Implement MU configuration statements. | ||
4 | * tests/atlocal.in (MFOPTS): Ignore site-wide and per-user | ||
5 | configuration files. | ||
6 | * doc/mailfromd.texi: Document sieve interface. | ||
7 | |||
8 | 2007-11-22 Sergey Poznyakoff <gray@gnu.org.ua> | ||
9 | |||
3 | * doc/mailfromd.texi: Update | 10 | * doc/mailfromd.texi: Update |
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi index 731c4ae1..95c6741f 100644 --- a/doc/mailfromd.texi +++ b/doc/mailfromd.texi | |||
@@ -223,2 +223,3 @@ Built-in and Library Functions | |||
223 | * System functions:: | 223 | * System functions:: |
224 | * Sieve Interface:: | ||
224 | * Interfaces to Third-Party Programs:: | 225 | * Interfaces to Third-Party Programs:: |
@@ -987,3 +988,2 @@ the corresponding section below. | |||
987 | @cindex Upgrading from 4.1 to 4.2 | 988 | @cindex Upgrading from 4.1 to 4.2 |
988 | @UNREVISED{} | ||
989 | Upgrading to this version does not require any special efforts. You | 989 | Upgrading to this version does not require any special efforts. You |
@@ -5260,2 +5260,3 @@ in version @value{VERSION}. | |||
5260 | * System functions:: | 5260 | * System functions:: |
5261 | * Sieve Interface:: | ||
5261 | * Interfaces to Third-Party Programs:: | 5262 | * Interfaces to Third-Party Programs:: |
@@ -6479,4 +6480,97 @@ the return status of the command otherwise. | |||
6479 | @end deftypefn | 6480 | @end deftypefn |
6480 | |||
6481 | 6481 | ||
6482 | @node Sieve Interface | ||
6483 | @subsubsection Sieve Interface | ||
6484 | @cindex Sieve | ||
6485 | @UNREVISED{} | ||
6486 | @samp{Sieve} is a powerful mail filtering language, defined in | ||
6487 | @acronym{RFC} 3028. @command{Mailfromd} supports an extended form | ||
6488 | of this language. For description of the language and available | ||
6489 | extensions, @xref{Sieve Language, Sieve Language, Sieve Language, | ||
6490 | mailutils, GNU Mailutils Manual}. | ||
6491 | |||
6492 | @deftypefn {Built-in Function} boolean sieve (string @var{script} @ | ||
6493 | [, number @var{flags}]) | ||
6494 | Compile the Sieve source file @var{script} and execute it over the | ||
6495 | collected message. This function can be used only in @code{eom} | ||
6496 | handler. | ||
6497 | |||
6498 | @findex sieve.mfh | ||
6499 | Optional @var{flags} define additional debugging and verbosity | ||
6500 | settings. It is a bit-mask field, consisting of a bitwise @code{or} | ||
6501 | of one or more of the following flags, defined in @file{sieve.mfh}: | ||
6502 | |||
6503 | @table @code | ||
6504 | @item MF_SIEVE_LOG | ||
6505 | Log every executed @samp{Sieve} action. | ||
6506 | |||
6507 | @item MF_SIEVE_DEBUG_TRACE | ||
6508 | Trace execution of @samp{Sieve} tests. | ||
6509 | |||
6510 | @item MF_SIEVE_DEBUG_INSTR | ||
6511 | Log every instruction, executed in the compiled @samp{Sieve} code. | ||
6512 | This produces huge amounts of output and is rarely useful, unless you | ||
6513 | suspect some bug in @samp{Sieve} implementation and wish to trace it. | ||
6514 | |||
6515 | @item MF_SIEVE_DEBUG_MAILUTILS | ||
6516 | Log debugging information about the underlying Mailutils calls. | ||
6517 | |||
6518 | @item MF_SIEVE_DEBUG_PROT | ||
6519 | Trace networking protocols. | ||
6520 | @end table | ||
6521 | |||
6522 | For example, @code{MF_SIEVE_LOG|MF_SIEVE_DEBUG_TRACE} enables logging | ||
6523 | @samp{Sieve} actions and tests. | ||
6524 | |||
6525 | The @code{sieve} function returns @code{true} if the message was | ||
6526 | accepted by the @var{script} program, and @code{false} otherwise. | ||
6527 | Here, the word @dfn{accepted} means that some form of @samp{KEEP} | ||
6528 | action (@pxref{Actions, keep, Actions, mailutils, GNU Mailutils | ||
6529 | Manual}) was executed over the message. | ||
6530 | @end deftypefn | ||
6531 | |||
6532 | The following example discards each message not accepted by the | ||
6533 | @samp{Sieve} program @file{/etc/mail/filter.siv}: | ||
6534 | |||
6535 | @smallexample | ||
6536 | #include_once <sieve.mfh> | ||
6537 | group eom | ||
6538 | do | ||
6539 | if not sieve("/etc/mail/filter.siv", MF_SIEVE_LOG) | ||
6540 | discard | ||
6541 | fi | ||
6542 | done | ||
6543 | @end smallexample | ||
6544 | |||
6545 | The example below illustrates how one can adjust logging flags | ||
6546 | depending on the current debugging level: | ||
6547 | |||
6548 | @smallexample | ||
6549 | #include_once <sieve.mfh> | ||
6550 | prog eom | ||
6551 | do | ||
6552 | number flags 0 | ||
6553 | number level debug_level("bi_sieve") | ||
6554 | if %level >= 1 | ||
6555 | set flags %flags | MF_SIEVE_LOG | ||
6556 | fi | ||
6557 | if %level >= 2 | ||
6558 | set flags %flags | MF_SIEVE_DEBUG_TRACE | ||
6559 | fi | ||
6560 | if %level > 9 | ||
6561 | set flags %flags | MF_SIEVE_DEBUG_INSTR | ||
6562 | fi | ||
6563 | if %level > 19 | ||
6564 | set flags %flags | MF_SIEVE_DEBUG_MAILUTILS | ||
6565 | fi | ||
6566 | if %level > 20 | ||
6567 | set flags %flags | MF_SIEVE_DEBUG_PROT | ||
6568 | fi | ||
6569 | |||
6570 | if not sieve("/etc/mail/filter.siv", %flags) | ||
6571 | discard | ||
6572 | fi | ||
6573 | done | ||
6574 | @end smallexample | ||
6575 | |||
6482 | @node Interfaces to Third-Party Programs | 6576 | @node Interfaces to Third-Party Programs |
@@ -39,2 +39,6 @@ | |||
39 | # include <mailutils/argp.h> | 39 | # include <mailutils/argp.h> |
40 | typedef struct { | ||
41 | char *file; | ||
42 | int line; | ||
43 | } mu_cfg_locus_t; | ||
40 | #else | 44 | #else |
@@ -239,2 +243,17 @@ log_status(sfsistat status, SMFICTX *ctx) | |||
239 | 243 | ||
244 | static void | ||
245 | mf_error_on_locus(mu_cfg_locus_t *locus, const char *fmt, ...) | ||
246 | { | ||
247 | va_list ap; | ||
248 | |||
249 | va_start(ap, fmt); | ||
250 | if (locus) { | ||
251 | char *newfmt = NULL; | ||
252 | asprintf(&newfmt, "%s:%d: %s", locus->file, locus->line, fmt); | ||
253 | mu_verror(newfmt, ap); | ||
254 | } else | ||
255 | mu_verror(fmt, ap); | ||
256 | va_end(ap); | ||
257 | } | ||
258 | |||
240 | 259 | ||
@@ -252,4 +271,4 @@ compare_string(const void *item, const void *value) | |||
252 | DOMAIN_LIST */ | 271 | DOMAIN_LIST */ |
253 | void | 272 | int |
254 | read_domain_file(char *name) | 273 | read_domain_file(mu_cfg_locus_t *locus, char *name) |
255 | { | 274 | { |
@@ -261,5 +280,5 @@ read_domain_file(char *name) | |||
261 | if (!fp) { | 280 | if (!fp) { |
262 | mu_error(_("Cannot open file `%s': %s"), | 281 | mf_error_on_locus(locus, _("Cannot open file `%s': %s"), |
263 | name, mu_strerror(errno)); | 282 | name, mu_strerror(errno)); |
264 | return; | 283 | return 1; |
265 | } | 284 | } |
@@ -289,2 +308,3 @@ read_domain_file(char *name) | |||
289 | fclose(fp); | 308 | fclose(fp); |
309 | return 0; | ||
290 | } | 310 | } |
@@ -329,2 +349,120 @@ host_in_relayed_domain_p(char *client) | |||
329 | 349 | ||
350 | /* ************************************************************************ | ||
351 | Configuration directives and options. | ||
352 | |||
353 | This is rather complicated. Mailfromd can take its configurable values | ||
354 | from the following locations (in that order): | ||
355 | |||
356 | 1. From the mailutils configuration file suite, $sysconfdir/mailutils.rc | ||
357 | and/or any files included herein; | ||
358 | 2. From #pragma statements in the filter script file, | ||
359 | $sysconfdir/mailfromd.rc; | ||
360 | 3. From command line options; | ||
361 | |||
362 | Versions prior to 4.2.90 supported only [2] and [3]. Generally speaking, | ||
363 | [2] was needed because Mailutils versions prior to 1.2.90 lacked proper | ||
364 | configuration file support. With the advent of it, [2] became obsolete | ||
365 | and will probably be removed in some point in the future. | ||
366 | |||
367 | For the time being, however, I need to support all flavors of options, | ||
368 | because it is reasonable to assume that many of the installers still have | ||
369 | MU 1.2 or prior, with which [1] is not available. | ||
370 | |||
371 | Technically speaking, [1] is supported by mu_app_init, whenever compiled | ||
372 | with newer Mailutils, [2] is supported by the "option handling" code below, | ||
373 | and [3] is handled by argp machinery (called either from mu_app_init, for | ||
374 | MU >=1.2.90, or from mu_argp_parse, for older Mailutils versions). | ||
375 | |||
376 | There are some functions common to [1] and [2], these are defined in this | ||
377 | section. | ||
378 | ************************************************************************ */ | ||
379 | |||
380 | static int | ||
381 | gid_comp(const void *item, const void *data) | ||
382 | { | ||
383 | return (gid_t) item != (gid_t) data; | ||
384 | } | ||
385 | |||
386 | static int | ||
387 | mf_option_group(mu_cfg_locus_t *locus, char *arg) | ||
388 | { | ||
389 | struct group *group = getgrnam(arg); | ||
390 | if (group) { | ||
391 | if (!retain_groups) { | ||
392 | int rc = mu_list_create(&retain_groups); | ||
393 | if (rc) { | ||
394 | mf_error_on_locus(locus, | ||
395 | _("Cannot create list: %s"), | ||
396 | mu_strerror(rc)); | ||
397 | return 1; | ||
398 | } | ||
399 | mu_list_set_comparator(retain_groups, gid_comp); | ||
400 | } | ||
401 | mu_list_append(retain_groups, (void*)group->gr_gid); | ||
402 | } else { | ||
403 | mf_error_on_locus(locus, _("Unknown group: %s"), arg); | ||
404 | return 1; | ||