Hi, I recently wrote a greylisting implementation that uses ${exists}, ${stat}, and ${run{/bin/touch}} in order to use the filesystem as a database, rather than using something more complex like MySQL, or talking to an external daemon via a socket.
It occured to me, that if I could do something like: ${if touch{/path/to/file}{succeeded}{failed}} I could do it entirely "natively" inside exim rather than having the massive overhead of spawning an external process with ${run} We already have expansions to check if a file/dir exists, one to get the mode, timestamps, uid, gid, and one for reading the contens of files so why not a an expansion to create them as well? My attempt... https://secure.grepular.com/exim-4.67_touch.patch.txt That updates expand.c and macros.h. I'm not an experienced C coder and this is my first attempt at implementing something more complicated in Exims code than a couple of characters change. But that patch works for me... Well, it works against 4.63 which is what I'm using, and I've just modified the patch so it applies against 4.67 before submitting here. This feature *basically* gives you the ability to set a light weight, persistant flag that you can check/update the age of, without having to use a much more heavy weight ${lookup} against a DB. So it has a much wider scope for usage than just my greylisting solution. Here's another simplified example of how it could be used: You want to defer any mail from a host if it has sent a virus in the last 10 minutes: ## Macros BLACKLIST_FILE = /var/spool/mail/blacklist/$sender_host_address BLACKLIST_FILE_AGE = ${eval:\ $tod_epoch - \ ${extract{mtime}{${stat:BLACKLIST_FILE}}}\ } ## acl_smtp_mail acl_check_sender: defer condition = ${if exists{BLACKLIST_FILE}} condition = ${if <{BLACKLIST_FILE_AGE}{600}} message = You are blacklisted. Try again in \ ${eval:600-BLACKLIST_FILE_AGE} seconds ## acl_smtp_data acl_check_data: deny malware = * continue = ${if touch{BLACKLIST_FILE}} message = Virus attached. You have been blocked for 10 \ minutes How else would you do stuff like this without using an external db, or an external process or, "abusing," the new ratelimit features? There are also some other functions I'd like to see in Exim too like: ${mkdir}, ${rmdir}, ${unlink}, ${writefile}, but I'm waiting to see if I get slapped down for this one before I worry about those ;) My main concern was the security implications, but I don't *think* there are any as the writes only happen as the exim user, and it should have the same restrictions regarding filters etc as do the ${exists}/${readfile} etc functions... There are no locking issues afaics as we're only creating a file and not writing. It works the same as the GNU touch util regarding touching symlinks and dirs... I'll stop babbling now. :) Mike -- ## List details at http://lists.exim.org/mailman/listinfo/exim-dev Exim details at http://www.exim.org/ ##