PerlJacket User's GuidePerlJacket rev: 2
PerlJacketis provided for your use free of charge, at at your own risk: only you can determine its suitability for the purposes which you have in mind. You are granted a perpetual, royalty-free license to use, distribute and modifyPerlJacketprovided that you agree to hold the author, Fred Morris, harmless and to defend and indemnify him against any and all claims arising from your use.
PerlJacket?PerlJacket is, appropriately enough, a perl
script which can perform certain filtering and tagging operations
on e-mail messages. It is meant to run on a mail server, typically
in the context of a user (mail recipient's) account on that server.
As an "out of the box" solution it offers filter
control by sending mail to oneself, and the ability to strip html
parts of messages entirely (when the plaintext of the message
is available) as well as rewrite multipart/alternative
or multipart/parallel messages so that the parts
are saved as attachments instead of being loaded by the mail reader;
as a customizable utility it offers a single-pass, MIME-aware
framework for processing incoming e-mail messages.
There were a few important design goals which motivated the
development of PerlJacket:
procmail;
text/plain
e-mail body parts;
The reasoning for each of these goals is discussed below.
MIME, which stands for Multipurpose Internet Mail Extension, is the protocol within the internet e-mail protocol which describes how e-mails are made up of multiple body parts, of different kinds, including plaintext, html text, attachments, etc.
procmail knows nothing about MIME; all it knows
is that a message has a header and a body. It is impossible to
filter for example specifically on an attachment, or to specifically
do something with a particular part of an e-mail message, such
as the HTML version, or a particular attachment type.
procmailJust because! It could be used with other things and in other
ways, but it was envisioned as an adjunct for use with procmail.
Off-the-shelf procmail filtering scripts often include
what are essentially programs embedded into the script, many of
them written in perl. I chose to write this as a
separate perl script (or program) rather than embedding
it in a .procmailrc file because I felt that maximized
the flexibility of both.
I generally don't need the HTML version of a message, the plaintext conveys meaning or the message is meaningless (I'm a snob and I believe in the power of the written word itself; deal with it.) And I certainly don't need bugged e-mail, or less-than-savory active payloads. But I do nonetheless get a lot of e-mail with attachments which I do want.
As just alluded to, there is some stuff I want and some that I don't. I change my mind often. Seems silly that the filter which controls the filtering can't be updated in the same mode: I shouldn't have to telnet in or use a web interface to change my e-mail filter, I should be able to do it using e-mail itself.
Some sophisticated MIME processing frameworks and tools exist. However they require buffering of the message so that it can be operated on in a "random access" manner, and this takes space if not processing power.
I was willing to sacrifice the ability to look ahead and write behind in return for something which would run in a single pass, and never load more than one MIME part of the messsage into memory at a time.
You must have:
perljacket.plx to your home (login)
directory. The file is available
here in an HTML-ized version which you can save as
text and rename perljacket.plx.
perljacket.plx
is protected and executable. Execute the commandperljacket.filter
to your home directory. The file is available
here in an HTML-zied version which you can save as
text and rename perljacket.filter.perljacket.filter
is writeable by you, but (at most) can be read by anybody else.
Execute the commandgo=r, and
make it so nobody can read your filter file, but on some systems
it needs to be world readable so that it will be accessible to
the mail delivery thread.perljacket.filter and create the initial
filter settings. Technically and theoretically speaking you
can leave this file blank when you turn filtering on at the end
of this setup procedure and everything will keep working just
the same, but you're probably not interested in that if you're
going to the trouble of installing PerlJacket, are
you? Execute the command.procmailrc file to a temporary
location. The file is available
here in an HTML-ized version which you can save as
text and rename procmailrc.new..procmailrc! You
may already have a file named .procmailrc, in which
case suddenly switching to a different one might cause unexpected
problems; plus, on some systems such as the Cobalt Qube,
the simple act of placing a .procmailrc in a user's
directory enables it.. there is no final setup of .forward.
Call it something like procmailrc.new..procmailrc use the
command procmailrc.new and create the initial
handling and postprocessing options. The sample .procmailrc
offers categories for: discarding messages, bouncing messages
based on who they're from, and bounding messages based on who
they're (not) to; filtering of MIME parts within an individual
message is done internally in PerlJacket as is the
e-mail updating of the filter..procmailrc. Use
the command.procmailrc tailored to your corporate culture
and policies, and documentation on how it interacts with PerlJacket's
filtering..procmailrc
is writeable by you, but (at most) can be read by anybody else.
Execute the commandgo=r, and
make it so nobody can read your filter file, but on some systems
it needs to be world readable so that it will be accessible to
the mail delivery thread..forward
file. On some systems you won't need to do this, and it "went
live" during the previous step. On others you will need
to create one of these. Instructions can be found in the Procmail
Resource Guide and the Procmail
Recipe Generator.
PerlJacket will filter your messages based on
the filter you define:
After that, you will probably want to have procmail
perform some action(s) based on the headers inserted, such as
sending an autoreply, discarding the message, saving it to a special
folder, etc.
At this point, the mail arrives in your "dropbox" or inbox on the server, where it will be downloaded or viewable by your e-mail client.
You may want to define filters in your e-mail client as well, which do certain things depending on the headers inserted.
The filter can be updated by sending yourself an e-mail in two stages. It is important when you send these e-mail messages that you:
To update the filter:
REQUEST UPDATE COOKIE
UPDATE COOKIE=(some large number)
TTL=(some large number)UPDATE COOKIE=(some large number)
TTL=(some large number)ADD and DELETE at the beginning of
the appropriate lines; all other lines will be ignored.
The headers inserted by PerlJacket can be utilized
in e-mail clients such as Eudora and Outlook
to flag incoming mail messages or send them to particular folders.
Common post-processing by procmail includes discarding
mail outright (such as that identified as spam); but more conservative
approaches include stripping spam to just the headers and saving
those to a separate mail folder on the server, where they won't
be downloaded by a mail client such as Eudora or
Outlook. Providing this folder is located in an appropriate
directory (typically the subdirectory mail under
the user's login directory), pine will be able to
open the folder and you can review the headers and delete delete
them one at a time; or, you can just delete this folder every
so often.
By default, the supplied .procmailrc recipe writes
a logfile named procmail.log in the user's login
directory. This file will keep growing and growing and growing,
and will need to be deleted every so often. Alternatively, once
you're sure everything is working file, you can disable logging.
PerlJacket itself.
I use this every day, and I've set it up for at least one client as of this writing. But we're all computer-savvy, and at least somewhat familiar with mail filtering, so we have a general idea of what to do and what not to do.
Particularly, I call your attention to the following:
PerlJacket in rewriting messages,
plus postprocessing in procmail, may cause some
messages to be reported as mangled by certain e-mail clients
under certain conditions (however, spammers send mangled mail
deliberately to get around filtering countermeasures, so what's
new?)
PerlJacket will write headers describing the actions
it is taking, and even for some error conditions it detects.
By default, procmail will write a log. Procmail
has different logging modes, and verbose in particular
will give you lots of information about exactly what is happening
(and result in a logfile which grows very rapidly!).
.procmailrc
do?The supplied .procmailrc disposition recipes are
pretty close to verbatim as to what the recipes in my own .procmailrc
do. I really intended them to be samples, but based on feedback
it seems as though people want to use them "as shipped",
and as a consequence of that they want more documentation as to
what they do.
There are several places in the file where you must substitute your own account and domain. This section is not a tutorial on using procmail; there are plenty of those around, if you need one, go find one.
perljacketThe following fragment invokes perljacket to preprocess all messages which are less than 3Mbytes in size:
# Pass everything through perljacket :0 H B h b f w * < 3000000 | ./perljacket.plx -t1000 :0 E h b f w | formail -A"X-PerlJacket: Warning: oversized message or error!"
Place any other preprocessing before this.
After PerlJacket processes the message, the various
mungings described elsewhere will have been performed, and gratuitous
headers will have been inserted. The sample recipes deal with
them as outlined in the following section. After that, you may
want to call something like SpamAssassin... or you
may want to call it first. That's up to you.
Basically my paradigm is:
PerlJacket to perform various mungings which
depend on the structure of the e-mail, and insert gratuitous
headers based on the filters defined in perljacket.filter.
.procmailrc and based on
the gratuitous headers to determine the disposition of the message.
As documented, I typically have rules in my perljacket.filter
file which insert the following headers:
# In addition to the X-PerlJacket header, my perljacket.filter defines # the following headers: # # X-Null Nuke em! # X-Bcc Stuff that was BCCed # X-Alias Stuff that was sent to an alias # X-Friend Friendlies # X-Mail-List Stuff from a recognized mailing list # X-Special Stuff that is special # X-Nozzle Stuff from misconfigured autoresponders # X-Banned Obnoxious domains # X-Banned-Pass Recognized subject line passwords for banned domains # X-Alias-Pass Recognized subject line passwords for aliased mail
The rest of this section describes how those headers interact with each other and with the remaining 4 recipes. These recipes deal with messages in the following order of precedence:
X-Null:
X-Banned:
X-Alias:
X-Bcc:
X-Null: RecipeThis recipe immediately discards any mail which was tagged with this header. For instance if I have a filter such as
<EXPR>bozo\.com</EXPR> <SCOPE>From:,Received:</SCOPE> <HEADER>X-Null:</HEADER>
Then any mail with bozo.com in the From:
or Received: headers is immediately discarded.
X-Banned: RecipePlaces identified by filters which I don't expect to get e-mail from, but which I do get spam from.
X-Banned-Pass: filter) they're ok and not processed
as banned
X-Alias: RecipeMail which is detected by filters as being to some account other than my primary account.
X-Banned-Pass: filter) they're ok and not processed
as banned.
X-Bcc: RecipeMail which is detected by filters as not being addressed to me at all... so-called "blind carbon copies".
X-Alias-Pass: filter) they're ok and not processed
as banned.
X-Friend: and X-Special:My friends and other important things get tagged like this. They are largely immune from the disposition processing above. Having more than one category allows me to highlight them different in my mail client.
X-Banned-Pass: and X-Alias-Pass:Special keyphrases allow people who make the effort to bypass the usual disposition processing for mail sent to a "junk" account or from banned domains.
X-Nozzle:Some people don't use X-Loop: headers on their
autoreplies. Worse still, they insist on stripping your headers
as well. As a consequence you end up with an "infinite loop"
of mail autoreplies.
This includes vacation programs, thank yous saying how much they appreciate your contacting them, etc., etc. Over the years I've had several conversations with people with such brain-damaged autoresponders, and their responses invariably seem to involve self-justification based on one or both of the following:
X-Loop: in the RFCs.
(True, but there's precious little about vacation programs, mailing
lists, or autoresponders in general.)
So, I use a filter to tag them with an X-Nozzle:
header which disables my autoreplies... or I just give them an
X-Null: header and send them straight to /dev/null..
it just depends.
The following table attempts to summarize the interaction of the various headers and disposition recipes:
/dev/nullbanned domains mail addressed to aliases blind carbon copies X-Null:Straight to /dev/null!X-Banned:Tagged by a filter as being from a banned user/domain. X-Alias:Tagged by a filter as being addressed to some address other than my primary account (an alias). X-Bcc:Tagged by a filter as being a blind carbon copy. X-Friend:Tagged by a filter as being someone I recognize as a friend; exempted from disposition processing. X-Mailing-List:Tagged by a filter as being a posting to a mailing list to which I belong. My mail client uses these headers to place the messages in special folders. Exempted from disposition processing. X-Special:Tagged by a filter as being special for some reason. My mail client uses these headers to highlight the messages. Exempted from disposition processing. X-Nozzle:Disables autoreplies. X-Banned-Pass:Tagged by a filter as containing a special keyword or passphrase. Exempted from disposition processing. X-Alias-Pass:Tagged by a filter as containing a special keyword or passphrase. Exempted from disposition processing.
procmail As a Calling Environmentprocmail is a convenient calling environment because
it knows how to do certain things with e-mail already, and lets
you interact with the operating system in certain ways (such as
calling PerlJacket).
Take advantage of the capabilities of procmail
to perform actions based on the results of PerlJacket's
filtering!
Alternatively, you don't have to use procmail
as a calling environment: PerlJacket expects to see
a "proper" e-mail message on stdin, and
writes the filtered message to stdout.
Once you know anything at all about the structure of e-mails
and the purposes of various mail headers, it is apparent that
semantically speaking a message for instance "To" somebody
might be addressed to them on the To: header, or
the Cc: header, etc. It's tedious to have to repeat
each of these in every scope statement, so certain cliches
are defined for your use, for instance =To= for the
above case.
You can edit these cliches in perljacket.plx,
and define your own as well. This is probably one of the simplest
customizations you can make, and also very useful.
Don't like what PerlJacket does to your e-mails?
Want something special done with a particular kind of attachment?
Change it!
perljacket.plx is a big file (!), but don't be
intimidated as long as you know at least some perl:
most of the action occurs in three routines near the end of the
file:
at_Header is called immediately after
the e-mail's headers have been loaded and before reading the
body;
at_Multipart is called immediately after
processing the multipart headers for a multipart MIME message
(or immediately after at_Header for a top-level
MIME multipart);
at_Entity is called immediately after
processing the part headers for a terminal or atomic MIME part.
Start there.
Fred Morris Consulting, Licensed in Seattle, WA, USA. since 1984
Document/Collaboration/Content Management Tools and Solutions
Better, Cheaper, Highly Adaptable, Less Hassles
Custom and Extraordinary Needs Data Processing Services
What else is on this web site?
An Internet Plumber... not a web cowboy
telephone: 206.297.6344
e-mail: x0xm3047x0xatx0xinwa.net