1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2009 */
6 /* See the file NOTICE for conditions of use and distribution. */
9 /* Code for mail filtering functions. */
14 /* Command arguments and left/right points in conditions can contain different
15 types of data, depending on the particular command or condition. Originally,
16 (void *) was used as "any old type", with casts, but this gives trouble and
17 warnings in some environments. So now it is done "properly", with a union. We
18 need to declare the structures first because some of them are recursive. */
21 struct condition_block;
24 struct string_item *a;
26 struct condition_block *c;
32 /* Local structures used in this module */
34 typedef struct filter_cmd {
35 struct filter_cmd *next;
39 union argtypes args[1];
42 typedef struct condition_block {
43 struct condition_block *parent;
50 /* Miscellaneous other declarations */
52 static uschar **error_pointer;
53 static uschar *log_filename;
54 static int filter_options;
55 static int line_number;
56 static int expect_endif;
57 static int had_else_endif;
60 static int output_indent;
61 static BOOL filter_delivered;
62 static BOOL finish_obeyed;
63 static BOOL seen_force;
64 static BOOL seen_value;
65 static BOOL noerror_force;
67 enum { had_neither, had_else, had_elif, had_endif };
69 static BOOL read_command_list(uschar **, filter_cmd ***, BOOL);
72 /* The string arguments for the mail command. The header line ones (that are
73 permitted to include \n followed by white space) first, and then the body text
74 one (it can have \n anywhere). Then the file names and once_repeat, which may
77 static const char *mailargs[] = { /* "to" must be first, and */
78 "to", /* "cc" and "bcc" must follow */
84 "extra_headers", /* miscellaneous added header lines */
92 /* The count of string arguments */
94 #define MAILARGS_STRING_COUNT (sizeof(mailargs)/sizeof(uschar *))
96 /* The count of string arguments that are actually passed over as strings
97 (once_repeat is converted to an int). */
99 #define mailargs_string_passed (MAILARGS_STRING_COUNT - 1)
101 /* This defines the offsets for the arguments; first the string ones, and
102 then the non-string ones. The order must be as above. */
104 enum { mailarg_index_to,
108 mailarg_index_reply_to,
109 mailarg_index_subject,
110 mailarg_index_headers, /* misc headers must be last */
111 mailarg_index_text, /* text is first after headers */
112 mailarg_index_file, /* between text and expand are filenames */
115 mailarg_index_once_repeat, /* a time string */
116 mailarg_index_expand, /* first non-string argument */
117 mailarg_index_return,
118 mailargs_total /* total number of arguments */
121 /* Offsets in the data structure for the string arguments (note that
122 once_repeat isn't a string argument at this point.) */
124 static int reply_offsets[] = { /* must be in same order as above */
125 offsetof(reply_item, to),
126 offsetof(reply_item, cc),
127 offsetof(reply_item, bcc),
128 offsetof(reply_item, from),
129 offsetof(reply_item, reply_to),
130 offsetof(reply_item, subject),
131 offsetof(reply_item, headers),
132 offsetof(reply_item, text),
133 offsetof(reply_item, file),
134 offsetof(reply_item, logfile),
135 offsetof(reply_item, oncelog),
138 /* Condition identities and names, with negated versions for some
141 enum { cond_and, cond_or, cond_personal, cond_begins, cond_BEGINS,
142 cond_ends, cond_ENDS, cond_is, cond_IS, cond_matches,
143 cond_MATCHES, cond_contains, cond_CONTAINS, cond_delivered,
144 cond_above, cond_below, cond_errormsg, cond_firsttime,
145 cond_manualthaw, cond_foranyaddress };
147 static const char *cond_names[] = {
148 "and", "or", "personal",
149 "begins", "BEGINS", "ends", "ENDS",
150 "is", "IS", "matches", "MATCHES", "contains",
151 "CONTAINS", "delivered", "above", "below", "error_message",
152 "first_delivery", "manually_thawed", "foranyaddress" };
154 static const char *cond_not_names[] = {
155 "", "", "not personal",
156 "does not begin", "does not BEGIN",
157 "does not end", "does not END",
158 "is not", "IS not", "does not match",
159 "does not MATCH", "does not contain", "does not CONTAIN",
160 "not delivered", "not above", "not below", "not error_message",
161 "not first_delivery", "not manually_thawed", "not foranyaddress" };
163 /* Tables of binary condition words and their corresponding types. Not easy
164 to amalgamate with the above because of the different variants. */
166 static const char *cond_words[] = {
188 static int cond_word_count = (sizeof(cond_words)/sizeof(uschar *));
190 static int cond_types[] = { cond_BEGINS, cond_BEGINS, cond_CONTAINS,
191 cond_CONTAINS, cond_ENDS, cond_ENDS, cond_IS, cond_MATCHES, cond_MATCHES,
192 cond_above, cond_begins, cond_begins, cond_below, cond_contains,
193 cond_contains, cond_ends, cond_ends, cond_is, cond_matches, cond_matches };
195 /* Command identities: must be kept in step with the list of command words
196 and the list of expanded argument counts which follow. */
198 enum { add_command, defer_command, deliver_command, elif_command, else_command,
199 endif_command, finish_command, fail_command, freeze_command,
200 headers_command, if_command, logfile_command, logwrite_command,
201 mail_command, noerror_command, pipe_command, save_command, seen_command,
202 testprint_command, unseen_command, vacation_command };
204 static const char *command_list[] = {
205 "add", "defer", "deliver", "elif", "else", "endif", "finish",
206 "fail", "freeze", "headers", "if", "logfile", "logwrite", "mail",
207 "noerror", "pipe", "save", "seen", "testprint", "unseen", "vacation"
210 static int command_list_count = sizeof(command_list)/sizeof(uschar *);
212 /* This table contains the number of expanded arguments in the bottom 4 bits.
213 If the top bit is set, it means that the default for the command is "seen". */
215 static uschar command_exparg_count[] = {
229 MAILARGS_STRING_COUNT, /* mail */
236 MAILARGS_STRING_COUNT /* vacation */
241 /*************************************************
242 * Find next significant uschar *
243 *************************************************/
245 /* Function to skip over white space and, optionally, comments.
248 ptr pointer to next character
249 comment_allowed if TRUE, comments (# to \n) are skipped
251 Returns: pointer to next non-whitespace character
255 nextsigchar(uschar *ptr, BOOL comment_allowed)
259 while (isspace(*ptr))
261 if (*ptr == '\n') line_number++;
264 if (comment_allowed && *ptr == '#')
266 while (*(++ptr) != '\n' && *ptr != 0);
276 /*************************************************
278 *************************************************/
280 /* The terminator is white space unless bracket is TRUE, in which
281 case ( and ) terminate.
284 ptr pointer to next character
285 buffer where to put the word
287 bracket if TRUE, terminate on ( and ) as well as space
289 Returns: pointer to the next significant character after the word
293 nextword(uschar *ptr, uschar *buffer, int size, BOOL bracket)
296 while (*ptr != 0 && !isspace(*ptr) &&
297 (!bracket || (*ptr != '(' && *ptr != ')')))
299 if (bp - buffer < size - 1) *bp++ = *ptr++; else
301 *error_pointer = string_sprintf("word is too long in line %d of "
302 "filter file (max = %d chars)", line_number, size);
307 return nextsigchar(ptr, TRUE);
312 /*************************************************
314 *************************************************/
316 /* Might be a word, or might be a quoted string; in the latter case
320 ptr pointer to next character
321 buffer where to put the item
323 bracket if TRUE, terminate non-quoted on ( and ) as well as space
325 Returns: the next significant character after the item
329 nextitem(uschar *ptr, uschar *buffer, int size, BOOL bracket)
332 if (*ptr != '\"') return nextword(ptr, buffer, size, bracket);
334 while (*(++ptr) != 0 && *ptr != '\"' && *ptr != '\n')
336 if (bp - buffer >= size - 1)
338 *error_pointer = string_sprintf("string is too long in line %d of "
339 "filter file (max = %d chars)", line_number, size);
343 if (*ptr != '\\') *bp++ = *ptr; else
345 if (isspace(ptr[1])) /* \<whitespace>NL<whitespace> ignored */
348 while (*p != '\n' && isspace(*p)) p++;
353 while (ptr[1] != '\n' && isspace(ptr[1])) ptr++;
358 *bp++ = string_interpret_escape(&ptr);
362 if (*ptr == '\"') ptr++;
363 else if (*error_pointer == NULL)
364 *error_pointer = string_sprintf("quote missing at end of string "
365 "in line %d", line_number);
368 return nextsigchar(ptr, TRUE);
374 /*************************************************
375 * Convert a string + K|M to a number *
376 *************************************************/
380 s points to text string
381 OK set TRUE if a valid number was read
383 Returns: the number, or 0 on error (with *OK FALSE)
387 get_number(uschar *s, BOOL *ok)
391 if (sscanf(CS s, "%i%n", &value, &count) != 1) return 0;
392 if (tolower(s[count]) == 'k') { value *= 1024; count++; }
393 if (tolower(s[count]) == 'm') { value *= 1024*1024; count++; }
394 while (isspace((s[count]))) count++;
395 if (s[count] != 0) return 0;
402 /*************************************************
403 * Read one condition *
404 *************************************************/
406 /* A complete condition must be terminated by "then"; bracketed internal
407 conditions must be terminated by a closing bracket. They are read by calling
408 this function recursively.
411 ptr points to start of condition
412 condition_block where to hang the created condition block
413 toplevel TRUE when called at the top level
415 Returns: points to next character after "then"
419 read_condition(uschar *ptr, condition_block **cond, BOOL toplevel)
423 condition_block *current_parent = NULL;
424 condition_block **current = cond;
428 /* Loop to read next condition */
434 /* reaching the end of the input is an error. */
438 *error_pointer = string_sprintf("\"then\" missing at end of filter file");
442 /* Opening bracket at the start of a condition introduces a nested
443 condition, which must be terminated by a closing bracket. */
447 ptr = read_condition(nextsigchar(ptr+1, TRUE), &c, FALSE);
448 if (*error_pointer != NULL) break;
451 *error_pointer = string_sprintf("expected \")\" in line %d of "
452 "filter file", line_number);
457 c->testfor = !c->testfor;
460 ptr = nextsigchar(ptr+1, TRUE);
464 /* Closing bracket at the start of a condition is an error. Give an
465 explicit message, as otherwise "unknown condition" would be confusing. */
467 else if (*ptr == ')')
469 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
470 "filter file", line_number);
474 /* Otherwise we expect a word or a string. */
478 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
479 if (*error_pointer != NULL) break;
481 /* "Then" at the start of a condition is an error */
483 if (Ustrcmp(buffer, "then") == 0)
485 *error_pointer = string_sprintf("unexpected \"then\" near line %d of "
486 "filter file", line_number);
490 /* "Not" at the start of a condition negates the testing condition. */
492 if (Ustrcmp(buffer, "not") == 0)
498 /* Build a condition block from the specific word. */
500 c = store_get(sizeof(condition_block));
501 c->left.u = c->right.u = NULL;
502 c->testfor = testfor;
505 /* Check for conditions that start with a keyword */
507 if (Ustrcmp(buffer, "delivered") == 0) c->type = cond_delivered;
508 else if (Ustrcmp(buffer, "error_message") == 0) c->type = cond_errormsg;
509 else if (Ustrcmp(buffer, "first_delivery") == 0) c->type = cond_firsttime;
510 else if (Ustrcmp(buffer, "manually_thawed") == 0) c->type = cond_manualthaw;
512 /* Personal can be followed by any number of aliases */
514 else if (Ustrcmp(buffer, "personal") == 0)
516 c->type = cond_personal;
520 uschar *saveptr = ptr;
521 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
522 if (*error_pointer != NULL) break;
523 if (Ustrcmp(buffer, "alias") != 0)
528 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
529 if (*error_pointer != NULL) break;
530 aa = store_get(sizeof(string_item));
531 aa->text = string_copy(buffer);
532 aa->next = c->left.a;
537 /* Foranyaddress must be followed by a string and a condition enclosed
538 in parentheses, which is handled as a subcondition. */
540 else if (Ustrcmp(buffer, "foranyaddress") == 0)
542 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
543 if (*error_pointer != NULL) break;
546 *error_pointer = string_sprintf("\"(\" expected after \"foranyaddress\" "
547 "near line %d of filter file", line_number);
551 c->type = cond_foranyaddress;
552 c->left.u = string_copy(buffer);
554 ptr = read_condition(nextsigchar(ptr+1, TRUE), &(c->right.c), FALSE);
555 if (*error_pointer != NULL) break;
558 *error_pointer = string_sprintf("expected \")\" in line %d of "
559 "filter file", line_number);
564 c->testfor = !c->testfor;
567 ptr = nextsigchar(ptr+1, TRUE);
570 /* If it's not a word we recognize, then it must be the lefthand
571 operand of one of the comparison words. */
576 uschar *isptr = NULL;
578 c->left.u = string_copy(buffer);
579 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
580 if (*error_pointer != NULL) break;
582 /* Handle "does|is [not]", preserving the pointer after "is" in
583 case it isn't that, but the form "is <string>". */
585 if (strcmpic(buffer, US"does") == 0 || strcmpic(buffer, US"is") == 0)
587 if (buffer[0] == 'i') { c->type = cond_is; isptr = ptr; }
588 if (buffer[0] == 'I') { c->type = cond_IS; isptr = ptr; }
590 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
591 if (*error_pointer != NULL) break;
592 if (strcmpic(buffer, US"not") == 0)
594 c->testfor = !c->testfor;
595 if (isptr != NULL) isptr = ptr;
596 ptr = nextword(ptr, buffer, sizeof(buffer), TRUE);
597 if (*error_pointer != NULL) break;
601 for (i = 0; i < cond_word_count; i++)
603 if (Ustrcmp(buffer, cond_words[i]) == 0)
605 c->type = cond_types[i];
610 /* If an unknown word follows "is" or "is not"
611 it's actually the argument. Reset to read it. */
613 if (i >= cond_word_count)
621 *error_pointer = string_sprintf("unrecognized condition word \"%s\" "
622 "near line %d of filter file", buffer, line_number);
627 /* Get the RH argument. */
629 ptr = nextitem(ptr, buffer, sizeof(buffer), TRUE);
630 if (*error_pointer != NULL) break;
631 c->right.u = string_copy(buffer);
635 /* We have read some new condition and set it up in the condition block
636 c; point the current pointer at it, and then deal with what follows. */
640 /* Closing bracket terminates if this is a lower-level condition. Otherwise
646 *error_pointer = string_sprintf("unexpected \")\" in line %d of "
647 "filter file", line_number);
651 /* Opening bracket following a condition is an error; give an explicit
652 message to make it clearer what is wrong. */
654 else if (*ptr == '(')
656 *error_pointer = string_sprintf("unexpected \"(\" in line %d of "
657 "filter file", line_number);
661 /* Otherwise the next thing must be one of the words "and", "or" or "then" */
665 uschar *saveptr = ptr;
666 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
667 if (*error_pointer != NULL) break;
669 /* "Then" terminates a toplevel condition; otherwise a closing bracket
670 has been omitted. Put a string terminator at the start of "then" so
671 that reflecting the condition can be done when testing. */
673 if (Ustrcmp(buffer, "then") == 0)
675 if (toplevel) *saveptr = 0;
676 else *error_pointer = string_sprintf("missing \")\" at end of "
677 "condition near line %d of filter file", line_number);
681 /* "And" causes a new condition block to replace the one we have
682 just read, which becomes the left sub-condition. The current pointer
683 is reset to the pointer for the right sub-condition. We have to keep
684 track of the tree of sequential "ands", so as to traverse back up it
685 if an "or" is met. */
687 else if (Ustrcmp(buffer, "and") == 0)
689 condition_block *andc = store_get(sizeof(condition_block));
690 andc->parent = current_parent;
691 andc->type = cond_and;
692 andc->testfor = TRUE;
694 andc->right.u = NULL; /* insurance */
696 current = &(andc->right.c);
697 current_parent = andc;
700 /* "Or" is similar, but has to be done a bit more carefully to
701 ensure that "and" is more binding. If there's a parent set, we
702 are following a sequence of "and"s and must track back to their
705 else if (Ustrcmp(buffer, "or") == 0)
707 condition_block *orc = store_get(sizeof(condition_block));
708 condition_block *or_parent = NULL;
710 if (current_parent != NULL)
712 while (current_parent->parent != NULL &&
713 current_parent->parent->type == cond_and)
714 current_parent = current_parent->parent;
716 /* If the parent has a parent, it must be an "or" parent. */
718 if (current_parent->parent != NULL)
719 or_parent = current_parent->parent;
722 orc->parent = or_parent;
723 if (or_parent == NULL) *cond = orc; else
724 or_parent->right.c = orc;
727 orc->left.c = (current_parent == NULL)? c : current_parent;
728 orc->right.c = NULL; /* insurance */
729 current = &(orc->right.c);
730 current_parent = orc;
733 /* Otherwise there is a disaster */
737 *error_pointer = string_sprintf("\"and\" or \"or\" or \"%s\" "
738 "expected near line %d of filter file, but found \"%s\"",
739 toplevel? "then" : ")", line_number, buffer);
745 return nextsigchar(ptr, TRUE);
750 /*************************************************
751 * Ouput the current indent *
752 *************************************************/
758 for (i = 0; i < output_indent; i++) debug_printf(" ");
763 /*************************************************
764 * Condition printer: for debugging *
765 *************************************************/
769 c the block at the top of the tree
770 toplevel TRUE at toplevel - stops overall brackets
776 print_condition(condition_block *c, BOOL toplevel)
778 const char *name = (c->testfor)? cond_names[c->type] : cond_not_names[c->type];
785 case cond_manualthaw:
786 debug_printf("%s", name);
801 debug_printf("%s %s %s", c->left.u, name, c->right.u);
805 if (!c->testfor) debug_printf("not (");
806 print_condition(c->left.c, FALSE);
807 debug_printf(" %s ", cond_names[c->type]);
808 print_condition(c->right.c, FALSE);
809 if (!c->testfor) debug_printf(")");
813 if (!c->testfor) debug_printf("not (");
814 else if (!toplevel) debug_printf("(");
815 print_condition(c->left.c, FALSE);
816 debug_printf(" %s ", cond_names[c->type]);
817 print_condition(c->right.c, FALSE);
818 if (!toplevel || !c->testfor) debug_printf(")");
821 case cond_foranyaddress:
822 debug_printf("%s %s (", name, c->left.u);
823 print_condition(c->right.c, FALSE);
832 /*************************************************
833 * Read one filtering command *
834 *************************************************/
838 pptr points to pointer to first character of command; the pointer
839 is updated to point after the last character read
840 lastcmdptr points to pointer to pointer to last command; used for hanging
841 on the newly read command
843 Returns: TRUE if command successfully read, else FALSE
847 read_command(uschar **pptr, filter_cmd ***lastcmdptr)
849 int command, i, cmd_bit;
850 filter_cmd *new, **newlastcmdptr;
852 BOOL was_seen_or_unseen = FALSE;
853 BOOL was_noerror = FALSE;
859 /* Read the next word and find which command it is. Command words are normally
860 terminated by white space, but there are two exceptions, which are the "if" and
861 "elif" commands. We must allow for them to be terminated by an opening bracket,
862 as brackets are allowed in conditions and users will expect not to require
865 if (Ustrncmp(ptr, "if(", 3) == 0)
867 Ustrcpy(buffer, "if");
870 else if (Ustrncmp(ptr, "elif(", 5) == 0)
872 Ustrcpy(buffer, "elif");
877 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
878 if (*error_pointer != NULL) return FALSE;
881 for (command = 0; command < command_list_count; command++)
882 if (Ustrcmp(buffer, command_list[command]) == 0) break;
884 /* Handle the individual commands */
888 /* Add takes two arguments, separated by the word "to". Headers has two
889 arguments, but the first must be "add", "remove", or "charset", and it gets
890 stored in the second argument slot. Neither may be preceded by seen, unseen
894 case headers_command:
895 if (seen_force || noerror_force)
897 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
898 "found before an \"%s\" command near line %d",
899 command_list[command], line_number);
904 /* Logwrite, logfile, pipe, and testprint all take a single argument, save
905 and logfile can have an option second argument for the mode, and deliver can
906 have "errors_to <address>" in a system filter, or in a user filter if the
907 address is the current one. */
909 case deliver_command:
910 case logfile_command:
911 case logwrite_command:
914 case testprint_command:
916 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
918 *error_pointer = string_sprintf("\"%s\" requires an argument "
919 "near line %d of filter file", command_list[command], line_number);
921 if (*error_pointer != NULL) yield = FALSE; else
923 union argtypes argument, second_argument;
925 argument.u = second_argument.u = NULL;
927 if (command == add_command)
929 argument.u = string_copy(buffer);
930 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
931 if (*buffer == 0 || Ustrcmp(buffer, "to") != 0)
932 *error_pointer = string_sprintf("\"to\" expected in \"add\" command "
933 "near line %d of filter file", line_number);
936 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
938 *error_pointer = string_sprintf("value missing after \"to\" "
939 "near line %d of filter file", line_number);
940 else second_argument.u = string_copy(buffer);
944 else if (command == headers_command)
946 if (Ustrcmp(buffer, "add") == 0)
947 second_argument.b = TRUE;
949 if (Ustrcmp(buffer, "remove") == 0) second_argument.b = FALSE;
951 if (Ustrcmp(buffer, "charset") == 0)
952 second_argument.b = TRUE_UNSET;
955 *error_pointer = string_sprintf("\"add\", \"remove\", or \"charset\" "
956 "expected after \"headers\" near line %d of filter file",
961 if (!system_filtering && second_argument.b != TRUE_UNSET)
963 *error_pointer = string_sprintf("header addition and removal is "
964 "available only in system filters: near line %d of filter file",
972 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
974 *error_pointer = string_sprintf("value missing after \"add\", "
975 "\"remove\", or \"charset\" near line %d of filter file",
977 else argument.u = string_copy(buffer);
981 /* The argument for the logwrite command must end in a newline, and the save
982 and logfile commands can have an optional mode argument. The deliver
983 command can have an optional "errors_to <address>" for a system filter,
984 or for a user filter if the address is the user's address. Accept the
985 syntax here - the check is later. */
989 if (command == logwrite_command)
991 int len = Ustrlen(buffer);
992 if (len == 0 || buffer[len-1] != '\n') Ustrcat(buffer, "\n");
995 argument.u = string_copy(buffer);
997 if (command == save_command || command == logfile_command)
1001 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1002 second_argument.i = (int)Ustrtol(buffer, NULL, 8);
1004 else second_argument.i = -1;
1007 else if (command == deliver_command)
1009 uschar *save_ptr = ptr;
1010 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1011 if (Ustrcmp(buffer, "errors_to") == 0)
1013 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1014 second_argument.u = string_copy(buffer);
1016 else ptr = save_ptr;
1020 /* Set up the command block. Seen defaults TRUE for delivery commands,
1021 FALSE for logging commands, and it doesn't matter for testprint, as
1022 that doesn't change the "delivered" status. */
1024 if (*error_pointer != NULL) yield = FALSE; else
1026 new = store_get(sizeof(filter_cmd) + sizeof(union argtypes));
1029 *lastcmdptr = &(new->next);
1030 new->command = command;
1031 new->seen = seen_force? seen_value : command_exparg_count[command] >= 128;
1032 new->noerror = noerror_force;
1033 new->args[0] = argument;
1034 new->args[1] = second_argument;
1040 /* Elif, else and endif just set a flag if expected. */
1045 if (seen_force || noerror_force)
1047 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1048 "near line %d is not followed by a command", line_number);
1052 if (expect_endif > 0)
1053 had_else_endif = (command == elif_command)? had_elif :
1054 (command == else_command)? had_else : had_endif;
1057 *error_pointer = string_sprintf("unexpected \"%s\" command near "
1058 "line %d of filter file", buffer, line_number);
1064 /* Defer, freeze, and fail are available only if permitted. */
1067 cmd_bit = RDO_DEFER;
1068 goto DEFER_FREEZE_FAIL;
1072 goto DEFER_FREEZE_FAIL;
1074 case freeze_command:
1075 cmd_bit = RDO_FREEZE;
1078 if ((filter_options & cmd_bit) == 0)
1080 *error_pointer = string_sprintf("filtering command \"%s\" is disabled: "
1081 "near line %d of filter file", buffer, line_number);
1086 /* A text message can be provided after the "text" keyword, or
1087 as a string in quotes. */
1090 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1091 if (*saveptr != '\"' && (*buffer == 0 || Ustrcmp(buffer, "text") != 0))
1098 if (*saveptr != '\"')
1099 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1100 fmsg = string_copy(buffer);
1103 /* Drop through and treat as "finish", but never set "seen". */
1107 /* Finish has no arguments; fmsg defaults to NULL */
1109 case finish_command:
1110 new = store_get(sizeof(filter_cmd));
1113 *lastcmdptr = &(new->next);
1114 new->command = command;
1115 new->seen = seen_force? seen_value : FALSE;
1116 new->args[0].u = fmsg;
1120 /* Seen, unseen, and noerror are not allowed before if, which takes a
1121 condition argument and then and else sub-commands. */
1124 if (seen_force || noerror_force)
1126 *error_pointer = string_sprintf("\"seen\", \"unseen\", or \"noerror\" "
1127 "found before an \"if\" command near line %d",
1132 /* Set up the command block for if */
1134 new = store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1137 *lastcmdptr = &(new->next);
1138 new->command = command;
1140 new->args[0].u = NULL;
1141 new->args[1].u = new->args[2].u = NULL;
1142 new->args[3].u = ptr;
1144 /* Read the condition */
1146 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1147 if (*error_pointer != NULL) { yield = FALSE; break; }
1149 /* Read the commands to be obeyed if the condition is true */
1151 newlastcmdptr = &(new->args[1].f);
1152 if (!read_command_list(&ptr, &newlastcmdptr, TRUE)) yield = FALSE;
1154 /* If commands were successfully read, handle the various possible
1155 terminators. There may be a number of successive "elif" sections. */
1159 while (had_else_endif == had_elif)
1161 filter_cmd *newnew =
1162 store_get(sizeof(filter_cmd) + 4 * sizeof(union argtypes));
1163 new->args[2].f = newnew;
1166 new->command = command;
1168 new->args[0].u = NULL;
1169 new->args[1].u = new->args[2].u = NULL;
1170 new->args[3].u = ptr;
1172 ptr = read_condition(ptr, &(new->args[0].c), TRUE);
1173 if (*error_pointer != NULL) { yield = FALSE; break; }
1174 newlastcmdptr = &(new->args[1].f);
1175 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1179 if (yield == FALSE) break;
1181 /* Handle termination by "else", possibly following one or more
1182 "elsif" sections. */
1184 if (had_else_endif == had_else)
1186 newlastcmdptr = &(new->args[2].f);
1187 if (!read_command_list(&ptr, &newlastcmdptr, TRUE))
1189 else if (had_else_endif != had_endif)
1191 *error_pointer = string_sprintf("\"endif\" missing near line %d of "
1192 "filter file", line_number);
1197 /* Otherwise the terminator was "endif" - this is checked by
1198 read_command_list(). The pointer is already set to NULL. */
1201 /* Reset the terminator flag. */
1203 had_else_endif = had_neither;
1207 /* The mail & vacation commands have a whole slew of keyworded arguments.
1208 The final argument values are the file expand and return message booleans,
1209 whose offsets are defined in mailarg_index_{expand,return}. Although they
1210 are logically booleans, because they are stored in a uschar * value, we use
1211 NULL and not FALSE, to keep 64-bit compilers happy. */
1214 case vacation_command:
1215 new = store_get(sizeof(filter_cmd) + mailargs_total * sizeof(union argtypes));
1217 new->command = command;
1218 new->seen = seen_force? seen_value : FALSE;
1219 new->noerror = noerror_force;
1220 for (i = 0; i < mailargs_total; i++) new->args[i].u = NULL;
1222 /* Read keyword/value pairs until we hit one that isn't. The data
1223 must contain only printing chars plus tab, though the "text" value
1224 can also contain newlines. The "file" keyword can be preceded by the
1225 word "expand", and "return message" has no data. */
1229 uschar *saveptr = ptr;
1230 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1231 if (*error_pointer != NULL)
1237 /* Ensure "return" is followed by "message"; that's a complete option */
1239 if (Ustrcmp(buffer, "return") == 0)
1241 new->args[mailarg_index_return].u = US""; /* not NULL => TRUE */
1242 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1243 if (Ustrcmp(buffer, "message") != 0)
1245 *error_pointer = string_sprintf("\"return\" not followed by \"message\" "
1246 " near line %d of filter file", line_number);
1253 /* Ensure "expand" is followed by "file", then fall through to process the
1256 if (Ustrcmp(buffer, "expand") == 0)
1258 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1259 ptr = nextword(ptr, buffer, sizeof(buffer), FALSE);
1260 if (Ustrcmp(buffer, "file") != 0)
1262 *error_pointer = string_sprintf("\"expand\" not followed by \"file\" "
1263 " near line %d of filter file", line_number);
1269 /* Scan for the keyword */
1271 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
1272 if (Ustrcmp(buffer, mailargs[i]) == 0) break;
1274 /* Not found keyword; assume end of this command */
1276 if (i >= MAILARGS_STRING_COUNT)
1282 /* Found keyword, read the data item */
1284 ptr = nextitem(ptr, buffer, sizeof(buffer), FALSE);
1285 if (*error_pointer != NULL)
1290 else new->args[i].u = string_copy(buffer);
1293 /* If this is the vacation command, apply some default settings to
1294 some of the arguments. */
1296 if (command == vacation_command)
1298 if (new->args[mailarg_index_file].u == NULL)
1300 new->args[mailarg_index_file].u = string_copy(US".vacation.msg");
1301 new->args[mailarg_index_expand].u = US""; /* not NULL => TRUE */
1303 if (new->args[mailarg_index_log].u == NULL)
1304 new->args[mailarg_index_log].u = string_copy(US".vacation.log");
1305 if (new->args[mailarg_index_once].u == NULL)
1306 new->args[mailarg_index_once].u = string_copy(US".vacation");
1307 if (new->args[mailarg_index_once_repeat].u == NULL)
1308 new->args[mailarg_index_once_repeat].u = string_copy(US"7d");
1309 if (new->args[mailarg_index_subject].u == NULL)
1310 new->args[mailarg_index_subject].u = string_copy(US"On vacation");
1313 /* Join the address on to the chain of generated addresses */
1316 *lastcmdptr = &(new->next);
1320 /* Seen and unseen just set flags */
1323 case unseen_command:
1326 *error_pointer = string_sprintf("\"seen\" or \"unseen\" "
1327 "near line %d is not followed by a command", line_number);
1332 *error_pointer = string_sprintf("\"seen\" or \"unseen\" repeated "
1333 "near line %d", line_number);
1336 seen_value = (command == seen_command);
1338 was_seen_or_unseen = TRUE;
1342 /* So does noerror */
1344 case noerror_command:
1347 *error_pointer = string_sprintf("\"noerror\" "
1348 "near line %d is not followed by a command", line_number);
1351 noerror_force = TRUE;
1359 *error_pointer = string_sprintf("unknown filtering command \"%s\" "
1360 "near line %d of filter file", buffer, line_number);
1365 if (!was_seen_or_unseen && !was_noerror)
1368 noerror_force = FALSE;
1377 /*************************************************
1378 * Read a list of commands *
1379 *************************************************/
1381 /* If condional is TRUE, the list must be terminated
1382 by the words "else" or "endif".
1385 pptr points to pointer to next character; the pointer is updated
1386 lastcmdptr points to pointer to pointer to previously-read command; used
1387 for hanging on the new command
1388 conditional TRUE if this command is the subject of a condition
1390 Returns: TRUE on success
1394 read_command_list(uschar **pptr, filter_cmd ***lastcmdptr, BOOL conditional)
1396 if (conditional) expect_endif++;
1397 had_else_endif = had_neither;
1398 while (**pptr != 0 && had_else_endif == had_neither)
1400 if (!read_command(pptr, lastcmdptr)) return FALSE;
1401 *pptr = nextsigchar(*pptr, TRUE);
1406 if (had_else_endif == had_neither)
1408 *error_pointer = US"\"endif\" missing at end of filter file";
1418 /*************************************************
1419 * Test a condition *
1420 *************************************************/
1424 c points to the condition block; c->testfor indicated whether
1425 it's a positive or negative condition
1426 toplevel TRUE if called from "if" directly; FALSE otherwise
1428 Returns: TRUE if the condition is met
1432 test_condition(condition_block *c, BOOL toplevel)
1436 uschar *exp[2], *p, *pp;
1437 const uschar *regcomp_error = NULL;
1438 int regcomp_error_offset;
1442 if (c == NULL) return TRUE; /* does this ever occur? */
1447 yield = test_condition(c->left.c, FALSE) &&
1448 *error_pointer == NULL &&
1449 test_condition(c->right.c, FALSE);
1453 yield = test_condition(c->left.c, FALSE) ||
1454 (*error_pointer == NULL &&
1455 test_condition(c->right.c, FALSE));
1458 /* The personal test is meaningless in a system filter. The tests are now in
1459 a separate function (so Sieve can use them). However, an Exim filter does not
1460 scan Cc: (hence the FALSE argument). */
1463 yield = system_filtering? FALSE : filter_personal(c->left.a, FALSE);
1466 case cond_delivered:
1467 yield = filter_delivered;
1470 /* Only TRUE if a message is actually being processed; FALSE for address
1471 testing and verification. */
1474 yield = message_id[0] != 0 &&
1475 (sender_address == NULL || sender_address[0] == 0);
1478 /* Only FALSE if a message is actually being processed; TRUE for address
1479 and filter testing and verification. */
1481 case cond_firsttime:
1482 yield = filter_test != FTEST_NONE || message_id[0] == 0 || deliver_firsttime;
1485 /* Only TRUE if a message is actually being processed; FALSE for address
1486 testing and verification. */
1488 case cond_manualthaw:
1489 yield = message_id[0] != 0 && deliver_manual_thaw;
1492 /* The foranyaddress condition loops through a list of addresses */
1494 case cond_foranyaddress:
1496 pp = expand_string(p);
1499 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1500 "filter file: %s", p, expand_string_message);
1505 parse_allow_group = TRUE; /* Allow group syntax */
1510 int start, end, domain;
1513 p = parse_find_address_end(pp, FALSE);
1517 filter_thisaddress =
1518 parse_extract_address(pp, &error, &start, &end, &domain, FALSE);
1521 if (filter_thisaddress != NULL)
1523 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1524 (debug_selector & D_filter) != 0)
1527 debug_printf("Extracted address %s\n", filter_thisaddress);
1529 yield = test_condition(c->right.c, FALSE);
1533 if (saveend == 0) break;
1537 parse_allow_group = FALSE; /* Reset group syntax flags */
1538 parse_found_group = FALSE;
1541 /* All other conditions have left and right values that need expanding;
1542 on error, it doesn't matter what value is returned. */
1546 for (i = 0; i < 2; i++)
1548 exp[i] = expand_string(p);
1551 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1552 "filter file: %s", p, expand_string_message);
1558 /* Inner switch for the different cases */
1563 yield = strcmpic(exp[0], exp[1]) == 0;
1567 yield = Ustrcmp(exp[0], exp[1]) == 0;
1571 yield = strstric(exp[0], exp[1], FALSE) != NULL;
1575 yield = Ustrstr(exp[0], exp[1]) != NULL;
1579 yield = strncmpic(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1583 yield = Ustrncmp(exp[0], exp[1], Ustrlen(exp[1])) == 0;
1589 int len = Ustrlen(exp[1]);
1590 uschar *s = exp[0] + Ustrlen(exp[0]) - len;
1591 yield = (s < exp[0])? FALSE :
1592 ((c->type == cond_ends)? strcmpic(s, exp[1]) : Ustrcmp(s, exp[1])) == 0;
1598 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1599 (debug_selector & D_filter) != 0)
1601 debug_printf("Match expanded arguments:\n");
1602 debug_printf(" Subject = %s\n", exp[0]);
1603 debug_printf(" Pattern = %s\n", exp[1]);
1606 re = pcre_compile(CS exp[1],
1607 PCRE_COPT | ((c->type == cond_matches)? PCRE_CASELESS : 0),
1608 (const char **)®comp_error, ®comp_error_offset, NULL);
1612 *error_pointer = string_sprintf("error while compiling "
1613 "regular expression \"%s\": %s at offset %d",
1614 exp[1], regcomp_error, regcomp_error_offset);
1618 yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1);
1621 /* For above and below, convert the strings to numbers */
1625 for (i = 0; i < 2; i++)
1627 val[i] = get_number(exp[i], &yield);
1630 *error_pointer = string_sprintf("malformed numerical string \"%s\"",
1635 yield = (c->type == cond_above)? (val[0] > val[1]) : (val[0] < val[1]);
1641 if ((filter_test != FTEST_NONE && debug_selector != 0) ||
1642 (debug_selector & D_filter) != 0)
1645 debug_printf("%sondition is %s: ",
1646 toplevel? "C" : "Sub-c",
1647 (yield == c->testfor)? "true" : "false");
1648 print_condition(c, TRUE);
1652 return yield == c->testfor;
1657 /*************************************************
1658 * Interpret chain of commands *
1659 *************************************************/
1661 /* In testing state, just say what would be done rather than doing it. The
1662 testprint command just expands and outputs its argument in testing state, and
1663 does nothing otherwise.
1666 commands points to chain of commands to interpret
1667 generated where to hang newly-generated addresses
1669 Returns: FF_DELIVERED success, a significant action was taken
1670 FF_NOTDELIVERED success, no significant action
1671 FF_DEFER defer requested
1672 FF_FAIL fail requested
1673 FF_FREEZE freeze requested
1674 FF_ERROR there was a problem
1678 interpret_commands(filter_cmd *commands, address_item **generated)
1683 BOOL condition_value;
1685 while (commands != NULL)
1688 uschar *fmsg, *ff_name;
1689 uschar *expargs[MAILARGS_STRING_COUNT];
1693 /* Expand the relevant number of arguments for the command that are
1696 for (i = 0; i < (command_exparg_count[commands->command] & 15); i++)
1698 uschar *ss = commands->args[i].u;
1705 expargs[i] = expand_string(ss);
1706 if (expargs[i] == NULL)
1708 *error_pointer = string_sprintf("failed to expand \"%s\" in "
1709 "%s command: %s", ss, command_list[commands->command],
1710 expand_string_message);
1716 /* Now switch for each command, setting the "delivered" flag if any of them
1719 if (commands->seen) filter_delivered = TRUE;
1721 switch(commands->command)
1724 for (i = 0; i < 2; i++)
1726 uschar *ss = expargs[i];
1729 if (i == 1 && (*ss++ != 'n' || ss[1] != 0))
1731 *error_pointer = string_sprintf("unknown variable \"%s\" in \"add\" "
1732 "command", expargs[i]);
1736 /* Allow for "--" at the start of the value (from -$n0) for example */
1737 if (i == 0) while (ss[0] == '-' && ss[1] == '-') ss += 2;
1739 n[i] = (int)Ustrtol(ss, &end, 0);
1742 *error_pointer = string_sprintf("malformed number \"%s\" in \"add\" "
1748 filter_n[n[1]] += n[0];
1749 if (filter_test != FTEST_NONE) printf("Add %d to n%d\n", n[0], n[1]);
1752 /* A deliver command's argument must be a valid address. Its optional
1753 second argument (system filter only) must also be a valid address. */
1755 case deliver_command:
1756 for (i = 0; i < 2; i++)
1761 int start, end, domain;
1763 uschar *ss = parse_extract_address(s, &error, &start, &end, &domain,
1766 expargs[i] = ((filter_options & RDO_REWRITE) != 0)?
1767 rewrite_address(ss, TRUE, FALSE, global_rewrite_rules,
1768 rewrite_existflags) :
1769 rewrite_address_qualify(ss, TRUE);
1772 *error_pointer = string_sprintf("malformed address \"%s\" in "
1773 "filter file: %s", s, error);
1779 /* Stick the errors address into a simple variable, as it will
1780 be referenced a few times. Check that the caller is permitted to
1785 if (s != NULL && !system_filtering)
1787 uschar *ownaddress = expand_string(US"$local_part@$domain");
1788 if (strcmpic(ownaddress, s) != 0)
1790 *error_pointer = US"errors_to must point to the caller's address";
1795 /* Test case: report what would happen */
1797 if (filter_test != FTEST_NONE)
1800 printf("%seliver message to: %s%s%s%s\n",
1801 (commands->seen)? "D" : "Unseen d",
1803 commands->noerror? " (noerror)" : "",
1804 (s != NULL)? " errors_to " : "",
1805 (s != NULL)? s : US"");
1812 DEBUG(D_filter) debug_printf("Filter: %sdeliver message to: %s%s%s%s\n",
1813 (commands->seen)? "" : "unseen ",
1815 commands->noerror? " (noerror)" : "",
1816 (s != NULL)? " errors_to " : "",
1817 (s != NULL)? s : US"");
1819 /* Create the new address and add it to the chain, setting the
1820 af_ignore_error flag if necessary, and the errors address, which can be
1821 set in a system filter and to the local address in user filters. */
1823 addr = deliver_make_addr(expargs[0], TRUE); /* TRUE => copy s */
1824 addr->p.errors_address = (s == NULL)?
1825 s : string_copy(s); /* Default is NULL */
1826 if (commands->noerror) setflag(addr, af_ignore_error);
1827 addr->next = *generated;
1834 mode = commands->args[1].i;
1836 /* Test case: report what would happen */
1838 if (filter_test != FTEST_NONE)
1842 printf("%save message to: %s%s\n", (commands->seen)?
1843 "S" : "Unseen s", s, commands->noerror? " (noerror)" : "");
1845 printf("%save message to: %s %04o%s\n", (commands->seen)?
1846 "S" : "Unseen s", s, mode, commands->noerror? " (noerror)" : "");
1849 /* Real case: Ensure save argument starts with / if there is a home
1850 directory to prepend. */
1854 if (s[0] != '/' && (filter_options & RDO_PREPEND_HOME) != 0 &&
1855 deliver_home != NULL && deliver_home[0] != 0)
1856 s = string_sprintf("%s/%s", deliver_home, s);
1857 DEBUG(D_filter) debug_printf("Filter: %ssave message to: %s%s\n",
1858 (commands->seen)? "" : "unseen ", s,
1859 commands->noerror? " (noerror)" : "");
1861 /* Create the new address and add it to the chain, setting the
1862 af_pfr and af_file flags, the af_ignore_error flag if necessary, and the
1865 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1866 setflag(addr, af_pfr|af_file);
1867 if (commands->noerror) setflag(addr, af_ignore_error);
1869 addr->next = *generated;
1875 s = string_copy(commands->args[0].u);
1876 if (filter_test != FTEST_NONE)
1879 printf("%sipe message to: %s%s\n", (commands->seen)?
1880 "P" : "Unseen p", s, commands->noerror? " (noerror)" : "");
1882 else /* Ensure pipe command starts with | */
1884 DEBUG(D_filter) debug_printf("Filter: %spipe message to: %s%s\n",
1885 (commands->seen)? "" : "unseen ", s,
1886 commands->noerror? " (noerror)" : "");
1887 if (s[0] != '|') s = string_sprintf("|%s", s);
1889 /* Create the new address and add it to the chain, setting the
1890 af_ignore_error flag if necessary. Set the af_expand_pipe flag so that
1891 each command argument is expanded in the transport after the command
1892 has been split up into separate arguments. */
1894 addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */
1895 setflag(addr, af_pfr|af_expand_pipe);
1896 if (commands->noerror) setflag(addr, af_ignore_error);
1897 addr->next = *generated;
1900 /* If there are any numeric variables in existence (e.g. after a regex
1901 condition), or if $thisaddress is set, take a copy for use in the
1902 expansion. Note that we can't pass NULL for filter_thisaddress, because
1903 NULL terminates the list. */
1905 if (expand_nmax >= 0 || filter_thisaddress != NULL)
1908 int ecount = (expand_nmax >= 0)? expand_nmax : -1;
1909 uschar **ss = store_get(sizeof(uschar *) * (ecount + 3));
1910 addr->pipe_expandn = ss;
1911 if (filter_thisaddress == NULL) filter_thisaddress = US"";
1912 *ss++ = string_copy(filter_thisaddress);
1913 for (i = 0; i <= expand_nmax; i++)
1914 *ss++ = string_copyn(expand_nstring[i], expand_nlength[i]);
1920 /* Set up the file name and mode, and close any previously open
1923 case logfile_command:
1924 log_mode = commands->args[1].i;
1925 if (log_mode == -1) log_mode = 0600;
1928 (void)close(log_fd);
1931 log_filename = expargs[0];
1932 if (filter_test != FTEST_NONE)
1935 printf("%sogfile %s\n", (commands->seen)? "Seen l" : "L", log_filename);
1939 case logwrite_command:
1942 if (filter_test != FTEST_NONE)
1945 printf("%sogwrite \"%s\"\n", (commands->seen)? "Seen l" : "L",
1946 string_printing(s));
1949 /* Attempt to write to a log file only if configured as permissible.
1950 Logging may be forcibly skipped for verifying or testing. */
1952 else if ((filter_options & RDO_LOG) != 0) /* Locked out */
1955 debug_printf("filter log command aborted: euid=%ld\n",
1956 (long int)geteuid());
1957 *error_pointer = US"logwrite command forbidden";
1960 else if ((filter_options & RDO_REALLOG) != 0)
1963 DEBUG(D_filter) debug_printf("writing filter log as euid %ld\n",
1964 (long int)geteuid());
1967 if (log_filename == NULL)
1969 *error_pointer = US"attempt to obey \"logwrite\" command "
1970 "without a previous \"logfile\"";
1973 log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode);
1976 *error_pointer = string_open_failed(errno, "filter log file \"%s\"",
1982 if (write(log_fd, s, len) != len)
1984 *error_pointer = string_sprintf("write error on file \"%s\": %s",
1985 log_filename, strerror(errno));
1991 DEBUG(D_filter) debug_printf("skipping logwrite (verifying or testing)\n");
1995 /* Header addition and removal is available only in the system filter. The
1996 command is rejected at parse time otherwise. However "headers charset" is
1997 always permitted. */
1999 case headers_command:
2001 int subtype = commands->args[1].i;
2004 if (filter_test != FTEST_NONE)
2005 printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" :
2006 (subtype == FALSE)? "remove" : "charset", string_printing(s));
2008 if (subtype == TRUE)
2010 while (isspace(*s)) s++;
2013 header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')?
2015 header_last->type = header_checkname(header_last, FALSE);
2016 if (header_last->type >= 'a') header_last->type = htype_other;
2020 else if (subtype == FALSE)
2026 while ((ss = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
2028 header_remove(0, ss);
2031 /* This setting lasts only while the filter is running; on exit, the
2032 variable is reset to the previous value. */
2034 else headers_charset = s;
2038 /* Defer, freeze, and fail are available only when explicitly permitted.
2039 These commands are rejected at parse time otherwise. The message can get
2040 very long by the inclusion of message headers; truncate if it is, and also
2041 ensure printing characters so as not to mess up log files. */
2044 ff_name = US"defer";
2046 goto DEFERFREEZEFAIL;
2051 goto DEFERFREEZEFAIL;
2053 case freeze_command:
2054 ff_name = US"freeze";
2059 if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, " ... (truncated)");
2060 fmsg = string_printing(fmsg);
2061 *error_pointer = fmsg;
2063 if (filter_test != FTEST_NONE)
2066 printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg);
2068 else DEBUG(D_filter) debug_printf("Filter: %s \"%s\"\n", ff_name, fmsg);
2071 case finish_command:
2072 if (filter_test != FTEST_NONE)
2075 printf("%sinish\n", (commands->seen)? "Seen f" : "F");
2079 DEBUG(D_filter) debug_printf("Filter: %sfinish\n",
2080 (commands->seen)? " Seen " : "");
2082 finish_obeyed = TRUE;
2083 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2087 uschar *save_address = filter_thisaddress;
2088 int ok = FF_DELIVERED;
2089 condition_value = test_condition(commands->args[0].c, TRUE);
2090 if (*error_pointer != NULL) ok = FF_ERROR; else
2093 ok = interpret_commands(commands->args[condition_value? 1:2].f,
2097 filter_thisaddress = save_address;
2098 if (finish_obeyed || (ok != FF_DELIVERED && ok != FF_NOTDELIVERED))
2104 /* To try to catch runaway loops, do not generate mail if the
2105 return path is unset or if a non-trusted user supplied -f <>
2106 as the return path. */
2109 case vacation_command:
2110 if (return_path == NULL || return_path[0] == 0)
2112 if (filter_test != FTEST_NONE)
2113 printf("%s command ignored because return_path is empty\n",
2114 command_list[commands->command]);
2115 else DEBUG(D_filter) debug_printf("%s command ignored because return_path "
2116 "is empty\n", command_list[commands->command]);
2120 /* Check the contents of the strings. The type of string can be deduced
2121 from the value of i.
2123 . If i is equal to mailarg_index_text it's a text string for the body,
2124 where anything goes.
2126 . If i is > mailarg_index_text, we are dealing with a file name, which
2127 cannot contain non-printing characters.
2129 . If i is less than mailarg_index_headers we are dealing with something
2130 that will go in a single message header line, where newlines must be
2131 followed by white space.
2133 . If i is equal to mailarg_index_headers, we have a string that contains
2134 one or more headers. Newlines that are not followed by white space must
2135 be followed by a header name.
2138 for (i = 0; i < MAILARGS_STRING_COUNT; i++)
2141 uschar *s = expargs[i];
2143 if (s == NULL) continue;
2145 if (i != mailarg_index_text) for (p = s; *p != 0; p++)
2148 if (i > mailarg_index_text)
2150 if (!mac_isprint(c))
2152 *error_pointer = string_sprintf("non-printing character in \"%s\" "
2153 "in %s command", string_printing(s),
2154 command_list[commands->command]);
2159 /* i < mailarg_index_text */
2161 else if (c == '\n' && !isspace(p[1]))
2163 if (i < mailarg_index_headers)
2165 *error_pointer = string_sprintf("\\n not followed by space in "
2166 "\"%.1024s\" in %s command", string_printing(s),
2167 command_list[commands->command]);
2171 /* Check for the start of a new header line within the string */
2176 for (pp = p + 1;; pp++)
2179 if (c == ':' && pp != p + 1) break;
2180 if (c == 0 || c == ':' || isspace(*pp))
2182 *error_pointer = string_sprintf("\\n not followed by space or "
2183 "valid header name in \"%.1024s\" in %s command",
2184 string_printing(s), command_list[commands->command]);
2191 } /* Loop to scan the string */
2193 /* The string is OK */
2195 commands->args[i].u = s;
2198 /* Proceed with mail or vacation command */
2200 if (filter_test != FTEST_NONE)
2202 uschar *to = commands->args[mailarg_index_to].u;
2204 printf("%sail to: %s%s%s\n", (commands->seen)? "Seen m" : "M",
2205 (to == NULL)? US"<default>" : to,
2206 (commands->command == vacation_command)? " (vacation)" : "",
2207 (commands->noerror)? " (noerror)" : "");
2208 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2210 uschar *arg = commands->args[i].u;
2213 int len = Ustrlen(mailargs[i]);
2214 int indent = (debug_selector != 0)? output_indent : 0;
2215 while (len++ < 7 + indent) printf(" ");
2216 printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2217 (commands->args[mailarg_index_expand].u != NULL &&
2218 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2221 if (commands->args[mailarg_index_return].u != NULL)
2222 printf("Return original message\n");
2227 uschar *log_addr = NULL;
2228 uschar *to = commands->args[mailarg_index_to].u;
2233 if (to == NULL) to = expand_string(US"$reply_address");
2234 while (isspace(*to)) to++;
2236 for (tt = to; *tt != 0; tt++) /* Get rid of newlines */
2237 if (*tt == '\n') *tt = ' ';
2241 debug_printf("Filter: %smail to: %s%s%s\n",
2242 (commands->seen)? "seen " : "",
2244 (commands->command == vacation_command)? " (vacation)" : "",
2245 (commands->noerror)? " (noerror)" : "");
2246 for (i = 1; i < MAILARGS_STRING_COUNT; i++)
2248 uschar *arg = commands->args[i].u;
2251 int len = Ustrlen(mailargs[i]);
2252 while (len++ < 15) debug_printf(" ");
2253 debug_printf("%s: %s%s\n", mailargs[i], string_printing(arg),
2254 (commands->args[mailarg_index_expand].u != NULL &&
2255 Ustrcmp(mailargs[i], "file") == 0)? " (expanded)" : "");
2260 /* Create the "address" for the autoreply. This is used only for logging,
2261 as the actual recipients are extracted from the To: line by -t. We use the
2262 same logic here to extract the working addresses (there may be more than
2263 one). Just in case there are a vast number of addresses, stop when the
2264 string gets too long. */
2269 uschar *ss = parse_find_address_end(tt, FALSE);
2270 uschar *recipient, *errmess;
2271 int start, end, domain;
2275 recipient = parse_extract_address(tt, &errmess, &start, &end, &domain,
2279 /* Ignore empty addresses and errors; an error will occur later if
2280 there's something really bad. */
2282 if (recipient != NULL)
2284 log_addr = string_cat(log_addr, &size, &ptr,
2285 (log_addr == NULL)? US">" : US",", 1);
2286 log_addr = string_cat(log_addr, &size, &ptr, recipient,
2287 Ustrlen(recipient));
2294 log_addr = string_cat(log_addr, &size, &ptr, US", ...", 5);
2298 /* Move on past this address */
2300 tt = ss + (*ss? 1:0);
2301 while (isspace(*tt)) tt++;
2304 if (log_addr == NULL)
2306 log_addr = string_sprintf(">**bad-reply**");
2307 badflag = af_bad_reply;
2309 else log_addr[ptr] = 0;
2311 addr = deliver_make_addr(log_addr, FALSE);
2312 setflag(addr, (af_pfr|badflag));
2313 if (commands->noerror) setflag(addr, af_ignore_error);
2314 addr->next = *generated;
2316 addr->reply = store_get(sizeof(reply_item));
2317 addr->reply->from = NULL;
2318 addr->reply->to = string_copy(to);
2319 addr->reply->file_expand =
2320 commands->args[mailarg_index_expand].u != NULL;
2321 addr->reply->expand_forbid = expand_forbid;
2322 addr->reply->return_message =
2323 commands->args[mailarg_index_return].u != NULL;
2324 addr->reply->once_repeat = 0;
2326 if (commands->args[mailarg_index_once_repeat].u != NULL)
2328 addr->reply->once_repeat =
2329 readconf_readtime(commands->args[mailarg_index_once_repeat].u, 0,
2331 if (addr->reply->once_repeat < 0)
2333 *error_pointer = string_sprintf("Bad time value for \"once_repeat\" "
2334 "in mail or vacation command: %s",
2335 commands->args[mailarg_index_once_repeat]);
2340 /* Set up all the remaining string arguments (those other than "to") */
2342 for (i = 1; i < mailargs_string_passed; i++)
2344 uschar *ss = commands->args[i].u;
2345 *((uschar **)(((uschar *)(addr->reply)) + reply_offsets[i])) =
2346 (ss == NULL)? NULL : string_copy(ss);
2351 case testprint_command:
2352 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2354 uschar *s = string_printing(expargs[0]);
2355 if (filter_test == FTEST_NONE)
2356 debug_printf("Filter: testprint: %s\n", s);
2358 printf("Testprint: %s\n", s);
2362 commands = commands->next;
2365 return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED;
2370 /*************************************************
2371 * Test for a personal message *
2372 *************************************************/
2374 /* This function is global so that it can also be called from the code that
2375 implements Sieve filters.
2378 aliases a chain of aliases
2379 scan_cc TRUE if Cc: and Bcc: are to be scanned (Exim filters do not)
2381 Returns: TRUE if the message is deemed to be personal
2385 filter_personal(string_item *aliases, BOOL scan_cc)
2387 uschar *self, *self_from, *self_to;
2388 uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL;
2389 void *reset_point = store_get(0);
2395 /* If any header line in the message is a defined "List-" header field, it is
2396 not a personal message. We used to check for any header line that started with
2397 "List-", but this was tightened up for release 4.54. The check is now for
2398 "List-Id", defined in RFC 2929, or "List-Help", "List-Subscribe", "List-
2399 Unsubscribe", "List-Post", "List-Owner" or "List-Archive", all of which are
2400 defined in RFC 2369. We also scan for "Auto-Submitted"; if it is found to
2401 contain any value other than "no", the message is not personal (RFC 3834).
2402 Previously the test was for "auto-". */
2404 for (h = header_list; h != NULL; h = h->next)
2407 if (h->type == htype_old) continue;
2409 if (strncmpic(h->text, US"List-", 5) == 0)
2412 if (strncmpic(s, US"Id:", 3) == 0 ||
2413 strncmpic(s, US"Help:", 5) == 0 ||
2414 strncmpic(s, US"Subscribe:", 10) == 0 ||
2415 strncmpic(s, US"Unsubscribe:", 12) == 0 ||
2416 strncmpic(s, US"Post:", 5) == 0 ||
2417 strncmpic(s, US"Owner:", 6) == 0 ||
2418 strncmpic(s, US"Archive:", 8) == 0)
2422 else if (strncmpic(h->text, US"Auto-submitted:", 15) == 0)
2425 while (isspace(*s)) s++;
2426 if (strncmpic(s, US"no", 2) != 0) return FALSE;
2428 while (isspace(*s)) s++;
2429 if (*s != 0) return FALSE;
2433 /* Set up "my" address */
2435 self = string_sprintf("%s@%s", deliver_localpart, deliver_domain);
2436 self_from = rewrite_one(self, rewrite_from, NULL, FALSE, US"",
2437 global_rewrite_rules);
2438 self_to = rewrite_one(self, rewrite_to, NULL, FALSE, US"",
2439 global_rewrite_rules);
2442 if (self_from == NULL) self_from = self;
2443 if (self_to == NULL) self_to = self;
2445 /* If there's a prefix or suffix set, we must include the prefixed/
2446 suffixed version of the local part in the tests. */
2448 if (deliver_localpart_prefix != NULL || deliver_localpart_suffix != NULL)
2450 psself = string_sprintf("%s%s%s@%s",
2451 (deliver_localpart_prefix == NULL)? US"" : deliver_localpart_prefix,
2453 (deliver_localpart_suffix == NULL)? US"" : deliver_localpart_suffix,
2455 psself_from = rewrite_one(psself, rewrite_from, NULL, FALSE, US"",
2456 global_rewrite_rules);
2457 psself_to = rewrite_one(psself, rewrite_to, NULL, FALSE, US"",
2458 global_rewrite_rules);
2459 if (psself_from == NULL) psself_from = psself;
2460 if (psself_to == NULL) psself_to = psself;
2465 /* Do all the necessary tests; the counts are adjusted for {pre,suf}fix */
2469 header_match(US"to:", TRUE, TRUE, aliases, to_count, self, self_to, psself,
2473 header_match(US"cc:", TRUE, TRUE, aliases, to_count, self, self_to,
2476 header_match(US"bcc:", TRUE, TRUE, aliases, to_count, self, self_to,
2482 header_match(US"from:", TRUE, FALSE, aliases, from_count, "^server@",
2483 "^daemon@", "^root@", "^listserv@", "^majordomo@", "^.*?-request@",
2484 "^owner-[^@]+@", self, self_from, psself, psself_from) &&
2486 header_match(US"precedence:", FALSE, FALSE, NULL, 3, "bulk","list","junk") &&
2488 (sender_address == NULL || sender_address[0] != 0);
2490 store_reset(reset_point);
2496 /*************************************************
2497 * Interpret a mail filter file *
2498 *************************************************/
2502 filter points to the entire file, read into store as a single string
2503 options controls whether various special things are allowed, and requests
2505 generated where to hang newly-generated addresses
2506 error where to pass back an error text
2508 Returns: FF_DELIVERED success, a significant action was taken
2509 FF_NOTDELIVERED success, no significant action
2510 FF_DEFER defer requested
2511 FF_FAIL fail requested
2512 FF_FREEZE freeze requested
2513 FF_ERROR there was a problem
2517 filter_interpret(uschar *filter, int options, address_item **generated,
2521 int yield = FF_ERROR;
2522 uschar *ptr = filter;
2523 uschar *save_headers_charset = headers_charset;
2524 filter_cmd *commands = NULL;
2525 filter_cmd **lastcmdptr = &commands;
2527 DEBUG(D_route) debug_printf("Filter: start of processing\n");
2529 /* Initialize "not in an if command", set the global flag that is always TRUE
2530 while filtering, and zero the variables. */
2534 filter_running = TRUE;
2535 for (i = 0; i < FILTER_VARIABLE_COUNT; i++) filter_n[i] = 0;
2537 /* To save having to pass certain values about all the time, make them static.
2538 Also initialize the line number, for error messages, and the log file
2541 filter_options = options;
2542 filter_delivered = FALSE;
2543 finish_obeyed = FALSE;
2544 error_pointer = error;
2545 *error_pointer = NULL;
2549 log_filename = NULL;
2551 /* Scan filter file for syntax and build up an interpretation thereof, and
2552 interpret the compiled commands, and if testing, say whether we ended up
2553 delivered or not, unless something went wrong. */
2556 ptr = nextsigchar(ptr, TRUE);
2558 if (read_command_list(&ptr, &lastcmdptr, FALSE))
2559 yield = interpret_commands(commands, generated);
2561 if (filter_test != FTEST_NONE || (debug_selector & D_filter) != 0)
2567 s = US"Filtering ended by \"defer\".";
2571 s = US"Filtering ended by \"freeze\".";
2575 s = US"Filtering ended by \"fail\".";
2579 s = US"Filtering set up at least one significant delivery "
2580 "or other action.\n"
2581 "No other deliveries will occur.";
2584 case FF_NOTDELIVERED:
2585 s = US"Filtering did not set up a significant delivery.\n"
2586 "Normal delivery will occur.";
2590 s = string_sprintf("Filter error: %s", *error);
2594 if (filter_test != FTEST_NONE) printf("%s\n", CS s);
2595 else debug_printf("%s\n", s);
2598 /* Close the log file if it was opened, and kill off any numerical variables
2599 before returning. Reset the header decoding charset. */
2601 if (log_fd >= 0) (void)close(log_fd);
2603 filter_running = FALSE;
2604 headers_charset = save_headers_charset;
2606 DEBUG(D_route) debug_printf("Filter: end of processing\n");
2611 /* End of filter.c */