# Copyright 1994 Applied Reasoning Systems Corporation # written by Bill Burdick (burdick@arscorp.com) # version 1.3 # added error folder convention. # PLEASE READ THE 'USING' SECTION # version 1.2 # added forward action # extended INFO comment to make things easier to understand ############## #### INFO #### ############## # classifyMail PROGRAM # automatic mail delivery, as per /slocal # differences between this and slocal: # * component name is a (case-insensitive but complete) regexp # * component pattern is a regexp (case-insensitive by default) # * uses .maildelivery.tcl instead of .maildelivery # * order of fields is different (condition first) # * written to be easily extended # * actions can be arbitrary TCL code # * determines who's using it (doesn't use the -user option) # * error recovery # * bounce and defer actions which exit with special values for sendmail # * forward action allows forwarding on per-message basis # * mailingList action sends to a mailing list # USING (with sendmail) # 1) Make sure classifyMail is in your own directory, to prevent sendmail from # getting confused. # 2) Make sure you have a .maildelivery.tcl file (see below) # 3) make your .forward execute classifyMail; my .forward entry: # |/home/david/burdick/bin/classifyMail # 4) make sure you have a folder named error # 5) test your .maildelivery.tcl file by running it on a few messages # you already have (e.g. classifyMail < ~/Mail/inbox/1). If you # get a mail.errors file or your message gets put in the 'error' # folder, then you may have a bug in your .maildelivery.tcl file. # Check the X-error component at the top of the message and see # what it says. # FORMAT of ~/.maildelivery.tcl file: # example .maildelivery.tcl: # set < {(^|[^a-zA-Z0-9])} # set > {($|[^a-zA-Z0-9])} # ? From: ftpmail|archie {+ ftp} # ? To: uucp|Postmaster|root|usenet {+ admin} # ? To:|Cc: ${<}urs${>}|self-interest {+ self} # ? To: burdick {+ talk/bill} # R * - {> /tmp/mail.tcl} # default {+ inbox} # PATTERNS: # component-name patterns are case insensitive and complete, so you # can say 'From:' or 'from:' and it won't confuse 'Reply-To:' with # 'To:'. # Component-value patterns are case-insensitive by default. You can # turn case-sensitivity on and off with the 'case-sensitive' and # 'case-insensitive' commands. # THE DEAL: # ~/.maildelivery.tcl is just a TCL source file. It is sourced by the # classifyMail program. This is sort of roundabout, but I thought it # would be nice to keep them separate, so that each user didn't have # to have his own copy of the program and so that the # .maildelivery.tcl file would look cleaner. # The conditions and actions are TCL functions. Most conditions (?, # N, A, R) take three arguments: a component, a pattern, and an action # to perform if the component line matches the pattern (or if the # component is "*"; then the pattern is ignored, but it must be # present). The actions are the traditional '+', '>', 'file', '|', # 'pipe', '^', 'qpipe', 'destroy', plus a few others. Actually, you # can just use exit in place of destroy. I have taken care to # evaluate the actions at the level they are called from (see the # conditions and proc act? for the uplevel calls), so there shouldn't # be any problem with using variables in the actions. Errors in # actions will cause action to be unsuccessful and control to go to # the next condition. # VARIABLES: # These variables are set during the action (changing them does affect # successive actions): # components # an array: indices are the component names (complete # with trailing colon), values are the complete # components (including the component name) # body # The body of the mail message (the text after the # components). # file # The complete mail message. # CONDITIONS: # ? component value action # take action if: # message undelivered # component matches value # if successful, message considered delivered # N component value action # take action if: # undelivered # last action succeeded # component matches value # if successful, message considered delivered # A component value action # take action if: # component matches value # if successful, message considered delivered # R component value action # take action if: # component matches value # do not change delivered status # default action # always take action # if successful, message considered delivered # ACTIONS: # + folder # store message in folder # > filename # store message in file # file filename # store message in file # | arg ... # pipe message to bourne shell command # pipe arg ... # pipe message to bourne shell command # ^ arg ... # pipe message to process # qpipe arg ... # pipe message to process # destroy # stop handling this message # defer # stop handling this message and tell sendmail to queue it # bounce # stop handling this message and tell sendmail to bounce it # forward addr ... # forward this message to listed addresses # mailingList listName # send message to the mailing list named listName. # Lists are stored in files in the $listbase directory. # This is ~/lists, by default, but you can set listbase # at the top of the .maildelivery.tcl file. A list file # just has a bunch of addresses in it (separated by # whitespace). This is different from a private alias, # because it preserves the original address in the mail # message. # ERROR RECOVERY: # If there are problems delivering mail (i.e. sourcing # ~/.maildelivery.tcl causes a TCL error or the mail remains # undelivered), classifyMail places an X-ERROR: component in the # message and attempts to place it in the user's error folder. # Failing that, it is appended to the ~/mail.errors file in the packf # format. Failing that, it exits with a status of 1, which should # case the mailer to bounce the mail. So you should normally be able # to view erroneous messages with 'show +error'.