[The intro is meant for people that do not know what procmail is]
Tinypm.el -- (p)roc(m)ail minor mode
Preface, Sep 1997
The 1997 was a turning point in my daily email management. I
started receiving 10-25 UBE messages per week to my private account
and that raised my body temper by couple of Celsius degrees. I
wanted to nail down those idiots, or at least get rid of the UBE so
that it never landed to my promary inbox $MAIL. The I met procmail
and that solved the mail handling for me. It also made possible to
subscribe to several mailing lists without bloating the $MAIL:
procmail filed the incoming mail to defined mailing list inboxes.
I also started using Gnus to read the mailing lists, but the mail
splitting work was best handled by procmail. Why? because procmail
is always running, while your Emacs and Gnus isn't. Procmail always
listens the incoming messages and takes care f them, like
forwarding those UBE messages to appropriate postmasters.
To get more info about procmail, send following email and request
pm-* (Procmail) shar archive. (including pm-tips.txt)
To: jari(_dot_)aalto(_at_)poboxes(_dot_)com
Subject: send help
Procmail installation kit can be found at
ftp://ftp.informatik.rwth-aachen.de:/pub/packages/procmail/
What is Procmail?
[from procmail faq http://www.iki.fi/~era/procmail/]
Procmail is a mail processing utility, which can help you filter
your mail; sort incoming mail according to sender, Subject line,
length of message, keywords in the message, etc; implement an
ftp-by-mail server, and much more. Procmail is also a complete
drop-in replacement for your MDA. (If this doesn't mean anything to
you, you don't want to know.)
Some terms
[from Email Abuse FAQ]
._UBE_ = Unsolicited Bulk Email.
._UCE_ = (subset of UBE) Unsolicited Commercial Email.
_Spam_ = Spam describes a particular kind of Usenet posting (and
canned spiced ham), but is now often used to describe many kinds of
inappropriate activities, including some email-related events. It
is technically incorrect to use "spam" to describe email abuse,
although attempting to correct the practice would amount to tilting
at windmills
Overview of features
o Minor mode for writing Procmail receipes (tab key for coding)
o Linting procmail code: can also auto-correct code.
Problematic line is highlighted with overlay.
o Font-lock supported.
o files that have extension .rc or name .procmailrc trigger
turning on `tipm-mode' (By using `auto-mode-alist'). Please
check that the first line does not have anything that would
override this, like "-*- text -*-".
Quick reference
o M-x `tipm-mode' activates Procmail writing mode
o C-c ' L to Lint whole buffer interactively
o C-u C-c ' L to Lint whole buffer and gathers info.
o C-u C-u C-c ' L, same as above, but be less pedantic.
Writing the procmail code
The coding functions are provided by other modules. Your tab
advances 4 characters at a time, and a minimalistic brace alignment
is supported when you press tab before the ending brace.
TAB tit-tab-key tinytab.el
The RET autoindents, but this can be turned off by calling
C-c ' RET tit-return-key-mode tinytab.el
Whole regions can be adjusted with commands
C-TAB tit-indent-by-div-factor tinytab.el -->
A-S-TAB tit-indent-by-div-factor-back tinytab.el <--
C-c TAB tit-indent-region-dynamically tinytab.el <-->
Jumping to matching brace or matching parenthesis
% timy-vi-type-paren-match tinymy.el
Tabs and spaces
When the procmail mode is active, the tab key does not produce a
tab character, but sufficent amount of spaces. There is a reason
for this, mostly due to Lint parser which has to move up and down
columnwise when checking the code. The movements can't be done if
the code includes tabs. If you need a literal tab in your regexps,
you can get it with standard emacs way 'C-q` `TAB'.
Aligning the lines that have backslashes.
In procmail, you use backslashes a lot, like in following example.
The backslashes here are put after each line, but this construct is
error prone, because if you later on add new `echo' commands or
otherwise modify the content, you may forget to update the
backslashes.
:0 fh
* condition
| (formail -rt | \
cat -; \
echo "Error: you requested file"; \
echo "that does not exist";\
) | $SENDMAIL -t
To fix this code block, you can use command C-c ' \ or
`tipm-fix-backslashes-region'. It would have been enough to write
the first backslash and then call C-c ' \ and the rest of the
backslashes would have been added.
:0 fh
* condition
| (formail -rt | \
cat -; \
echo "Error: you requested file"; \
echo "that does not exist"; \
) | $SENDMAIL -t
Rules how to write Procmail code
In order to use the linting service, This package requires that
you write your procmail code in following manner. These rules are
needed, so that it would be possible to parse the procmail code
efficiently and more easily.
[Receipe start]
: # although legal procmail, illegal here. Use :0
[flag order]
In order to autocorrect read flags from the buffer, the following
flag order is considered *standard*. The exra space after zero is
also desired.
:0 aAeEfhbHBDwWic:
[lockfile]
Every receipe starts with ':0 ', notice the embedded space, and the
flags are added after it. So while ':0:' would be valid, the
lockfile will be written in format ':0 :'. This is needed for the
lint parser, so that code looks the same everywhere (compare
with ':0 wic:'). This format is automatically retained when you
Call Lint: function `tipm-standardize-receipe-start' will do the
standardization.
Lockfile name must be longer than two characters. Shorter lockfile
name trigger an error. Also lockfile must have extension $LOCKEXT or
.lock or .lck; no other non-standard extensions are allowed. The
lockfile name must be within charsert [-_$.a-zA-Z0-9/] and anything
else is considered as an odd lock file name.
:0 : c # Error, should have been :0 c:
:0 : file # Invalid, should read "file.$LOCKEXT"
:0 : file.tmp # Invalid, non-standard extension.
:0 : file=0 # Invalid filename (odd characters in name)
[condition line]
* H B ?? regexp # valid procmail, llegal here: write "HB"
[Variables]
The literal value to the right hand side must be quoted with double
quotes if a simple string is assigned. If there is no quote or
backtick, then the lint assumes that you forgot to add variable
dollar($). Try to avoid extra spaces in the varaible initialisation
construct too `:-'.
DUMMY = yes # Warning, did you mean DUMMY = $yes
VAR = ${VAR:-1} # No spaces allowed: "$ {" is illegal.
[program names]
Program `sendmail' must be named sendmail, but it can also be variable
$SENDMAIL. Similarly program `formail' must be named `formail' or
it can be variable $FORMAIL. Use of $MY_SENDMAIL or $MY_FORMAIL are
illegal and cause missing many lint checks.
[commenting style]
In new procmail release you're allowed to place comments inside
condition lines. The lint will issue warning about this practise
if your procmail version does not support this. But while you
may place comments inside conditions, they should be indented by
some amount of spaces. The default indent is 4 spaces.
* condition1 --> * condition
# comment # comment
# comment # comment
* condition2 * condition
This is recommended due to readability (separating conditions
from comments) and the lint will fix these comment misplacements.
[redirecting to file]
If you print something to file, then the redirectioning commands
> and >> must have surrounding spaces, otherwise they are not
found from the procmail code. (because > can be used in regexps)
:0 :
| echo > test.tmp # Do not use "echo >test.tmp"
Linting procmail code
Writing procmail receipes is very demanding, because you have to
watch your writing all the time. Forgetting flag or two, or adding
non needed flag may cause your procmail code to work inproperly.
The lint interface in this module requires that
o You write your procmail code in certain way. (see above)
o buffer is writable and can be modified. This is due
to fact that program moves up and down to the same column
as previous or next line. In order to make such movements,
the tabs must be expanded when necessary.
To help *Linting* you procmail code, there are two functions
C-c ' l tipm-lint-forward
C-c ' L tipm-lint-buffer
These functions check every receipe and offer corrective actions if
anything suspeicious is found. If you don't want to correct the
receipes, you can pass prefix argument, which gathers the Lint run
to separate buffer. In parenthesis you see the buffer that was
tested and to the right you see the program and version number.
In this buffer you can press Mouse-2 or RET to jump to the line.
*** 1997-10-19 19:37 (pm-test.rc) tinypm.el 1.10
cd /users/foo/pm/
pm-test.rc:02: Error, Invalid or extra flags.
pm-test.rc:10: Error, Invalid or extra flags.
pm-test.rc:10: info, Redundant `Wc:' because `c:' implies W.
pm-test.rc:11: String `>' found, receipe should have `w' flag.
pm-test.rc:15: info, Flag `H' is useless, because it is default.
The output buffer can be sorted and you can move between blocks
with commands
sl tipm-output-sort-by-line
se tipm-output-sort-by-error
b tipm-output-start
e tipm-output-end
Lint: auto-correct
In many cases the lint functions are able to autocorrect the code:
answer `y' to auto-correct current point. If you want to correct
the place yourself, then abort the linting with `C-g' and fix the
indicated line.
Lint: directives
Most of the time the lint knows what is best for you, but there
may be cases where you have very complex procmail code and you
know exactly what you want. Here are the lint directives that you
can place immediately before the receipe start to prevent lint
from whining. The word `Lint:' can have any number of surrounding
spaces as long as it is the first word after comment.
# Lint: <Lint flags here>
:0 FLAGS
The comment must be in the previous line, the following is not
recognized.
# Lint: <Lint flags here>
# I'm doing some odd things here and ....
:0 FLAGS
Here is list of recognized lint directives. each directive must have
leading space.
o `-w'. In "|" receipe, ignore exit code. If you don't give
this directive, the missing "w" flag is suggested to put there.
o `-i'. If you have receipe that, 1) has no "f" 2) has nt ">"
3) has "|" action, then the receipe doesn't seem to store
the stdin anywhere. This may be valid case eg. if you use
MH's rcvstore. You can suppress the "-i" flag check with
this directive.
o `-c'. This is used in conjunction with `-i' when you only
do something as a side effect and you reaally don't want copy.
Lint: error messages
The error messages should be self explanatory, but if you don't
understand the message, please refer to pm-tips.txt file available
from the mentioned file server above.
"info, backticks in var init. Not a recommended practise"
See pm-tips.txt and section that talks about variable definitions.
Highlighting
Just couple of words about the chosen regexps for procmail code.
Notice, taht if you make a mistake, the dollar($) in front of
identifier is not highlighted. This should help spotting errors by
eye better.
$VAR = ${VAR:-"no"} # Error, extra $ to the left.
===