EXPERIMENTAL

This document describes the proposed implementation of filters. The syntax is
designed to be simple, easy to remember, and unambiguous to parse.



RULE  SYNTAX
------------

A rule line ends with a ';' character and may span multiple-lines of input:

COMMAND;

for each ITEM;
	COMMAND;
next;

if CONDITIONAL then;
	COMMAND;
else if CONDITIONAL then;
	COMMAND;
else;
	COMMAND;
endif;

do {ACTION-LIST};

set VAR [=|+=|-=|*=|/=|%=] WORD;

ITEM := [ADDRESS|header|attachment]
CONDITIONAL := [EXPRESSION1|EXPRESSION2|...EXPRESSIONn]
EXPRESSION1 := PART contains {WORD-LIST}
EXPRESSION2 := size [<|less|>|over] [n[K|M|G]|VAR]
EXPRESSION3 := age [<|less|>|over] [n[M|H|D]|VAR]
EXPRESSION4 := [ADDRESS|WORD] verifies
EXPRESSION5 := [ADDRESS|WORD] in(FILENAME)
EXPRESSION6 := [true|false]
EXPRESSION7 := VAR [<|<=|=|>=|>] WORD

PART := [HEADER|BODY]
HEADER := header.[mime|subject|date|ADDRESS]
ADDRESS :- [from|replyto|to|cc]
BODY := body.[size|text|ATTACHMENT]
ATTACHMENT := attachment.[mime|name|size|data]
WORD-LIST := WORD1[,WORD2[,...WORDn]]
WORD := [VAR|string|"string"]
VAR := $CHAR
CHARS := CHAR1[CHAR2...CHARn]
CHAR := [a-z|A-Z|0-9]

ACTION-LIST := ACTION1[,ACTION2[,...ACTIONn]]
ACTION := [CMD|"CMD"]
CMD := [file(FILENAME)|exec(WORD)|forward(RECIPIENT)|dirlist(PATH)|attach(FILENAME)|addto(FILENAME)|delfrom(FILENAME)|reply(WORD)|reject(WORD)|move(MBOX)|mark(WORD)|print(WORD)|println(WORD)|keep|skip|discard|echo]
RECIPIENT := [mailto:address|news:newsgroup|file:filename|tolist:filename]
FILENAME := WORD
PATH := WORD
MBOX := WORD


Where 'string' cannot contain tabs, spaces or commas unless enclosed in double quotes.


And...

K = 1024 bytes
M = 1024 * K
G = 1024 * M

M = 1 minute
H = 1 hour
D = 1 day

Where and ADDRESS is of the form  "$U" <$A@$D> and the built-in variables...

$_ = address
$U = user
$A = account
$D = domain

are set whenever an ADDRESS is encountered.

Other built-in variables...

$p = PART contents
$f = from
$r = replyto
$t = to
$c = cc
$d = date
$s = subject
$b = body
$? = attachment name
$+ = attachment size (bytes)
$- = attachment size (formated)
$~ = attachment MIME type (e.g. 'text/plain')
$= = attachment contents

All age compararisons are done in GMT and may not be the most reliable considering how some
client and/or servers are set up.

NOTE: If raw-mode is on then message 'body' is the whole message (with headers).



COMMAND SUMMARY
---------------

file(filename)      - write message-body/attachment to named file (previous contents are overwitten).
append(filename)    - append message-body/attachment to named file (previous contents are preserved).
exec(cmd)           - execute specified command feeding in message-body/attachment.
forward(recipient)  - send message to recipient.
addto(filename)     - add $_ to file (-tolist:filename compatible).
delfrom(filename)   - delete $_ from file (-tolist:filename compatible).
attach(filename)    - attach file to subsequent response.
reply(string)       - send a message in response.
move(mbox)          - move message to named folder (IMAP4 only).
dirlist(path)       - send a directory-listing in response.
mark(string)        - subject line is marked with the string (relay mode only).
print(string)       - print string.
println(string)     - print string followed by newline.
discard             - delete message/attachment.
keep                - does nothing really.
skip                - no further rule processing occurs on current message.
echo                - display message-body/attachment on output (same as print($b) or print($=) commands).
noop                - no-operation (i.e. do nothing).


RECIPIENT DESCRIPTION
---------------------

tolist:filename     - every address listed in file (one address per line, as in -tolist:filename).
mailto:address      - named address (in user@domain format only).
news:newsgroup      - named newsgroup.
file:filename       - write to named file (previous contents are overwritten).




EXAMPLE1 - implementing a simple mailing-list
---------------------------------------------

if header.from contains {"MAILER-DAEMON"} then;
	do { echo };
else;

	if header.subject contains {"unsubscribe","leave"} then;
		do { delfrom("postie.lst"), reply("Unsubscribed!") };
	else if header.subject contains {"subscribe","join"} then;
		do { addto("postie.lst"), reply("Subscribed!") };
	else if header.from contains {"adavison@ozemail.com.au"} then;
		do { forward(tolist:postie.lst) };
	endif;

endif;

do { discard };




EXAMPLE2 - implementing a simple discussion-list
------------------------------------------------

if header.from contains {"MAILER-DAEMON"} then;
	do { echo };
else;

	if header.subject contains {"unsubscribe","leave"} then;
		do { delfrom("postie.lst"), reply("Unsubscribed!") };
	else if header.subject contains {"subscribe","join"} then;
		do { addto("postie.lst"), reply("Subscribed!") };
	else if header.from in("postie.lst") then;
		do { forward(tolist:postie.lst) };
	endif;

endif;

do { discard };


EXAMPLE3 - implementing a simple file-server
--------------------------------------------

if header.from contains {"MAILER-DAEMON"} then
	do { echo };
else;

	if header.subject contains {"index", "dir"} then;
		do { dirlist("fetch") };
	else if header.subject contains {"fetch", "get"} then;

		if header.subject contains {"postie.zip"} then;
			do { attach("fetch/postie.zip"), reply("Here it is!") };
		elseif header.subject contains {"changes.txt"} then;
			do { attach("fetch/changes.txt"), reply("Here it is!") };
		elseif header.subject contains {"readme.txt"} then;
			do { attach("fetch/readme.txt"), reply("Here it is!") };
		else;
			do { echo };
		endif;

	else;
		do { echo };
	endif;

endif;

do { discard };



EXAMPLE4 - attachment processing
--------------------------------

do { print("Subject: "), println($s) };
do { print("From: "), println($f) };
do { print("To: "), println($t) };

for each attachment;
	do { print("Name: "), print($?) };
	do { print(", Size: "), print($-) };
	do { print(", MIME-type: "), print($~) };
	do { println() };
	do { file($?) };
next;

do { println() };




