Alternatives to mhook Programs
[previous]
[next]
[table of contents] [index]
Some systems with MH can't use the mhook utilities because the MTA
doesn't support them, because the MTA runs on another computer, and so on.
You may want your mail processed in batches, late at night -- instead of
one by one, with .maildelivery.
Besides, the .maildelivery file and mhook programs
can't do everything:
-
How about printing some or all messages automatically -- especially for users
(managers, maybe, or their secretaries) who want to get their messages on paper?
-
Wouldn't it be nice to have UNIX regular expression matching of message
headers and bodies -- instead of the case-insensitive substring matches
you get in .maildelivery?
-
Maybe you need to process incoming mail quickly but interactively,
so you have a choice about what's done with each message.
-
Do you want to be notified about important mail with pop-up windows or
big notices -- not just the 80 characters that rcvtty sends?
-
You might want to process incoming mail in a batch, automatically,
once a day or once a week.
That can be more efficient than running a handler for each new message.
It can also let you make decisions about the whole group of messages.
I hope that gives you an idea of what's possible.
You can replace part or all of the mhook utilities with utilities
that you develop or get from someone else.
This chapter explains the basic concepts and shows a few examples.
Another example is the autoinc script.
For more about shell programming and using MH utilities like scan
in your programs, see the Chapter
Introduction to UNIX Programming with MH, and
any good shell programming book (try
the Reference List).
With shell programming, as well as utilities like awk
and perl,
you can develop your own ways of handling mail automatically.
You may not need to use the .maildelivery file at all.
Your system's MTA may be able to start a program of yours for each new
message you get.
I think it's safer (for beginners, at least) not to do this.
If your handler fails, your mail could bounce.
Instead, run your mail handler from the .maildelivery file,
as the Section
Running Your Own Mail Handler explains.
But that's your choice, not mine!
How to Set Up
If your system uses the popular sendmail or smail MTAs,
you can probably start your own mail-handling program by putting
its pathname in your .forward file.
For example, this line in my .forward file will start the
program /u/jerry/bin/inmail:
"| /u/jerry/bin/inmail"
If your system handles executable files that start with #! (see the
Section How Does Your System Execute Files?), you can probably execute shell scripts that way
by just giving the script's name.
Otherwise, start scripts by giving the pathname to the
interpreter -- for example:
"| /bin/sh /u/jerry/bin/inmail"
The MTA will start the program and feed the incoming message to the
program's standard input.
When the program finishes and returns a zero exit status, the message
will have been delivered.
Gotchas: UID, GID, Permissions...
If your mail handler is run directly by the system MTA, you can run
into some tough problems making it work correctly.
On our Sun with SunOS 4.1, for instance, the sendmail MTA will
run a private mail handler in several ways:
-
If I send mail to myself, the mail handler runs as me (jerry)
with all my groups set, with all my current environment variables
set, and so on.
-
If another user on the same computer sends mail, the handler runs
as jerry but with the environment of the other user.
So any files the handler creates will be owned by me (jerry).
-
If the mail comes in from the Internet or by UUCP, the handler runs
as jerry and creates files owned by me.
But the USER and LOGNAME environment variables are set to
values like daemon or uremote; the home directory to, for
instance, /var/spool/uucppublic; and so on.
The rules are different in some other versions of sendmail.
So, running your handler this way may mean some careful programming.
You might run your handler from .maildelivery
(see the Section
Running Your Own Mail Handler)
-- this is a safer but maybe less efficient way to do it.
To find out more about the environment set in your handler, start with
a Bourne shell script like the one in the
Example below, Mail handler for debugging.
It stores the incoming message in one temporary file.
It also opens a temporary log file.
The log file stores the verbose output from the shell and the output of
two commands that help you see the environment while the handler runs.
Both files are created in /tmp; you can list them with ls -l
to see what permissions and ownership your handler will give files it creates.
Example: Mail handler for debugging
#! /bin/sh
exec > /tmp/inmail$$.log 2>&1 # Send all output to log file
set -xv # Make shell show debugging output
/bin/id # On BSD systems, use "whoami" and "groups" instead
/bin/env # On BSD systems, use "printenv" instead
/bin/cat > /tmp/inmail$$.stdin # Grab incoming message
exit 0 # Important to set a zero status if handler succeeds
Many UNIX systems come with the Berkeley vacation program.
It's designed to run from a .forward file, sending automatic
replies when you're away from the office.
When I run it, my .forward file looks like this:
\jerry, "| /usr/ucb/vacation jerry"
If you just want to acknowledge incoming mail or send a standard
reply, vacation can be a good way to do it.
The details about the format of the reply, as well as who will get replies
and how often, should be in your online
vacation(1)
manual page.
Do you want to have all incoming messages processed by your own mail handler?
It's probably safer to run your handler from a entry in a
.maildelivery file than to have the MTA run your handler
directly
(see the Section
Replacing All of Your .maildelivery File).
That's because, if no entry in your .maildelivery file
delivers a message, the system defaults will be used; you'll still
get the message and it won't "bounce back" to the sender.
Also, when your MTA delivers a message through .maildelivery,
the environment doesn't have so many
inconsistencies.
Setting Up
To feed all of your mail to your handler, put a entry in
your .maildelivery file like one of the three below.
Use the first entry if your handler can be executed directly.
The second entry runs awk; the third runs a Bourne shell:
* - ^ A /u/jerry/bin/inmail
* - ^ A "/usr/bin/awk -f /u/jerry/bin/inmail"
* - | A ". /u/jerry/bin/inmail"
Of course, you can use fields besides * to control what messages
are passed to your handler -- and results besides A to control
what other entries in .maildelivery are executed.
The exit status that your handler returns is important.
If your handler returns a nonzero status, .maildelivery will
act as if that the handler failed.
Try to make your handler set a zero status when it succeeds.
(The section Using Exit Status explains.
The exit 0 command sets a zero status in Bourne shell scripts.)
Printing Incoming Mail
You can print incoming mail from .maildelivery.
For instance, the following entry would print all messages sent to
the company-standards address.
As always, the R means that messages won't be marked
"delivered" when they're printed:
to company-standards ^ R "/usr/ucb/lpr -Plaser"
The print job may come out with a banner page that says it
was printed by daemon or some other user you wouldn't expect.
(See the Section on Gotchas.)
If you use a window system like X, rcvtty will tell you about
new mail in a window where you're logged in.
That window might be buried behind other windows, iconified, or full
of other text when important mail comes in.
Will you see the notice?
This script, rcvxterm, makes sure that you will.
It's designed for the X Window System, but it should be easy to
adapt for other window systems.
If you don't need a pop-up window, you might look at the script anyway.
It uses a technique for running programs from .maildelivery
that's good to know.
The script should probably be run only for important mail.
It opens a red xterm (X terminal emulator) window in the
top-right corner of an X display.
The title bar will say (depending on your window manager):
Important mail. Press q to quit.
There'll be a copy of the mail message inside the window, shown
by a pager program like less or pg.
(Note that, to keep the window from closing too soon, the pager program
can't exit
until you select the window and type a command like q.
The more pager quits at the end of the file, so it won't do.)
The script is simple on purpose: to make it easy to customize for
your window system, and to make it easy to understand.
The environment inside your .maildelivery file has almost
no information about where you're logged on.
So, I hard-coded most of the information into the script.
If you need help understanding the script,
see the Chapter
Introduction to UNIX Programming with MH.
To run it, put an entry like the one below in your .maildelivery file.
(If
your system can directly execute files that start
with #!, you can omit the /bin/sh.)
From root | R "/bin/cat >/tmp/m$$; /bin/sh /x/y/rcvxterm /tmp/m$$ &"
The script reads a file named on its command line.
It could read its standard input, the message from the
.maildelivery file.
But actions in .maildelivery that don't finish after a
reasonable amount of time are killed automatically.
To be sure your window stays there, and to avoid blocking other actions
in .maildelivery, run rcvxterm in the background as shown above.
Use cat to copy the message into a temporary file.
(Note that, during .maildelivery, your umask is set at 077.
That keeps other users from reading the temporary file.)
The script is below.
If you haven't installed a shell script before, there's help in the
Section Writing Shell Scripts for MH.
NOTE:
If you leave this simple-minded demonstration script running while the
display is unattended for long periods, it can overload your system with
too many processes and/or open windows.
You might hack the script to
count the number of rcvxterm processes -- with ps and
grep -c, for instance -- and quit without opening an xterm
if there are too many running already.
#! /bin/sh
# $Id: rcvxterm,v 1.2.1.2 92/08/02 18:19:27 jerry book2 $
### rcvxterm - HACK script to notify you about new mail
### Usage in .maildelivery: "/bin/cat >/tmp/m$$; /x/y/rcvxterm /tmp/m$$ &"
trap '/bin/rm -f $1' 0 1 2 15 # REMOVE TEMP FILE BEFORE EXITING
# USE less BECAUSE IT DOESN'T QUIT UNTIL YOU TYPE q. pg WORKS, TOO.
# USE FULL PATHS; REMEMBER THAT .maildelivery ENVIRONMENT IS LIMITED.
/usr/bin/X11/xterm -display hostname:0.0 \
-geometry 80x24-0+0 -bg red -fg white \
-title "important mail. Press q to quit" \
-ut -e /usr/local/bin/less $1
Instead of running your handler separately each time a new message
comes in, it can be better to run a separate handler periodically.
On systems where you can't run a handler for each new message, this is
your only choice!
A handler can read your system mailbox file directly, usually with inc.
I think it's easier to do that, splitting your messages into a
folder -- then have my handler run MH programs like scan and
pick to handle the messages.
Most handlers are probably shell or perl scripts.
A script can be run by hand when you type its name at a shell prompt,
or your computer can run it automatically with at or cron.
One automatic handler is the
autoinc shell script.
After you write a script like autoinc, add an entry to your
personal crontab file or start an at job to run your
script whenever you want.
It's probably a good idea to run it late at night, if you can.
The load on the system might be less then.
Also, and more important, there's less chance of the handler being
executed while you're logged on and might be reading mail -- it could change
your current folder and current message while you weren't expecting it.
(You can avoid that by making the handler use a different MH
profile, context, and sequences file.
The rmmer script
uses most of those tricks.)
If you haven't used crontab or at before,
there are examples.
Also, be sure to check the exit status of commands like inc to see
if something has gone wrong -- the Section
Using Exit Status has tips.
[Table of Contents] [Index]
[Previous: Storing in Mailbox Files: rcvpack]
[Next: Practical Tips]
|