Troubleshooters.Com® and T.C Email Technologies Present:

Procmail Resource File Builder

Career Skills nobody else teaches


CONTENTS:

I Never Saw It Coming

I never saw it coming. My ~/.procmailrc started life as a simple list of mailing lists, mail identities, spammers, trolls, vigilante enforcers of the perfect symptom description, militant top-posters, nut cases, proudly stupids, and other undesirables. You know, the usual suspects.

But as I joined more and more email lists, each of which had two or three wild and crazy impediments to technical communication, my ~/.procmailrc got ever more disorganized, with interleaved blacklisting, mailing list and other recipes. I decided to have several resource files, each containing only one type of entry. For instance:

  1. envvars.rc
  2. vitals.rc
  3. badguys.rc
  4. maillists.rc
  5. diag_first.rc
  6. by_account.rc
  7. diag_second.rc
  8. fallthrough.rc

Trouble is, when Procmail reads its resource file, there's no import or include statement. Oh, you can use Procmail's INCLUDERC or SWITCHRC environment variables, but that's harder to do than you might think, and if you make a mistake, you can lose email, have everything go into your inbox, which is a disaster, or suddenly receive scads of email from every troll and bully you've ever filtered out.

So I made a new plan.

The Solution

The new plan was simple enough: A shellscript to concatenate all the component files in the desired order. Before you look at the following shellscript, keep this in mind: The license disclaims all liability on my part. Believe it! Back up your current ~/.procmailrc, and save it for a long time , because it's possible the shellscript will produce a disastrous ~/.procmailrc, even though it produces an excellent one for me.

I feel so strongly about this that the shellscript shown here writes to a file called myprocmailrc in the current directory, so you'll need to change the appropriate environment variable in order to change the destination to ~/.procmailrc. Or, if you want to play it a little safer, you could run it to myprocmailrc, and then manually copy when ready.

The shellscript follows:

#!/bin/bash

######################################################
# Copyright (C) 2014 by Steve Litt
# 
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and
# associated documentation files (the "Software"), to
# deal in the Software without restriction, including
# without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom
# the Software is furnished to do so, subject to the
# following conditions:
# 
# The above copyright notice and this permission notice
# shall be included in all copies or substantial
# portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
# ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO
# EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
# USE OR OTHER DEALINGS IN THE SOFTWARE.
######################################################

#### The Procmail resource file
#### Careful, gets overwritten on every run
pmrcfile=myprocmailrc

#### Dir containing component files
componentdir=/mydata/pmfilters/   

#### Procmail resource components, ORDER IS IMPORTANT!!!
componentfiles="envvars.rc
   vitals.rc
   badguys.rc
   maillists.rc
   diag_first.rc
   by_account.rc
   diag_second.rc
   fallthrough.rc"

function apppend(){
   local fname=$1
   echo  >> $pmrcfile
   echo  >> $pmrcfile
   echo  >> $pmrcfile
   echo "###############" >> $pmrcfile
   echo "##### $fname" >> $pmrcfile
   echo "###############" >> $pmrcfile
   echo  >> $pmrcfile
   fname=$componentdir$fname
   cat $fname >> $pmrcfile
}

function makeheader(){
   echo -n "##### CREATED BY $0: " > $pmrcfile
   echo "DO NOT EDIT BY HAND!!! #####" >> $pmrcfile
   echo -n "##### COMPONENT FILE DIRECTORY " >> $pmrcfile
   echo "IS $componentdir #####" >> $pmrcfile
   echo >>$pmrcfile
   echo >>$pmrcfile
}

cd $componentdir

echo
echo -n "This will concat the following component "
echo "files to $pmrcfile,"
echo "in the following order ..."
echo
for f in $componentfiles; do
   echo $f
done

echo
echo "Next, will test that all component files exist..."
echo

let errs=0
for f in $componentfiles; do
   if ! test -f $f; then
      let errs=$errs+1
      echo -n "FATAL ERROR: "
      echo "No file $f in directory $componentdir"
   fi
done

if test $errs -gt 0; then
   echo "$errs ERRORS, aborting..."
   echo
   exit 2
else
   echo "All componentfiles accounted for, continuing..."
fi

makeheader
for f in $componentfiles; do
   echo Appending component file file $f
   chmod 600 $f
   apppend $f
done

chmod 600 $pmrcfile

echo
echo -n "Procmail resource file $pmrcfile "
echo "is now updated"
echo "with contents of component files."
echo

The preceding shellscript is simple enough. You define the $componentfiles array, which is a list of all the component files, in the order in which you want them concatenated into your Procmail Resource File (typically ~/.procmailrc).

Here's what the shellscript does:

  1. Lists the component files for the user, so the user knows what component files are involved.
  2. Tests that each component file exists, errors out if any don't.
  3. Truncates the destination Procmail Resource File and appends a header.
  4. Appends the component files, in order, to the destination, and changes the component file's permissions to 600.
  5. Sets the destination file's permissions to 600. Maybe 400 would be better, but right now it's 600.

The Benefits

There are probably a hundred ways to accomplish what this script does. Probably better alternatives, perhaps easier alternatives. But this shellscript does have some benefits:

It's Expat-licensed free software, so if you like it, use it. Just copy it from this web page into your favorite editor. And, if you do, please remember to change environment variables $pmrcfile, $componentdir, and $componentfiles to values appropriate for your setup and needs.