A Form Letter Utility for UNIX
Paul A. Sand
A considerable amount of electronic mail sent by system
is repetitious: answers to frequently asked questions,
of account security problems, gentle reminders concerning
use, requests for information, thank-you notes, and
so on. To lessen
the tedium involved in retyping such email messages,
a useful tool
would be an electronic analog of form letters: common
can be quickly sent to one or more addresses with a
minimum of effort.
This article presents a form letter utility written
in Perl for UNIX
systems. It can be used to send form letters to one
or more recipients
with a single command, greatly decreasing the drudgery
composing messages from scratch each time. Since form
be composed in advance and revised at leisure, it is
easy to ensure
that the language they contain remains precisely worded,
consistent, accurate, and as courteous and professional
as is appropriate.
The utility also allows form letters to contain dynamic
when the letter is mailed.
Design Goals and User Interface
A form letter utility should offer significant advantages
can be obtained by normal UNIX redirection. For example,
if you need
to notify a couple of users that they have disk quota
(perhaps) offer some general hints on how they could
use disk space
more efficiently, you could create a file named overquota,
and mail it to the users with a command like
% mail dmr bwk < overquota
The overquota file could be saved for reuse later,
of course, so that you would not need to retype it the
next time a
similar situation arises.
The utility presented here can be invoked equally as
% formletter overquota dmr bwk
This will send the form letter specified in the "template
file" overquota to the users dmr and bwk.
The differences between this and the simple UNIX redirection:
The mail will have a descriptive "Subject":
line in the header, specified in the template file.
The mail will be sent separately to the two users. Neither
user will be aware of the other's quota problems --
not, at least,
by reading the mail. Each will be under the impression
that he or
she was the sole recipient.
The mail will have a personalized greeting line, typically
the recipient's first name, if that can be looked up
in the password
file. For example:
If that's unsuitable, the greeting can be customized
on an individual basis, or deleted.
The mail can include other specific information that
might be relevant to to the recipient; in this example,
it could include
information about the user's current disk quota, his
or her current
disk usage, the names and sizes of the user's biggest
files, and so
on. The information is obtained by running a Perl script
in the template file itself; this powerful mechanism
allows the mail
to contain just about any information that the sender
to access, in addition to the unchanging text.
The mail will include the sender's "signature"
at the end: either the contents of a preset signature
file or, if
that's not present, the sender's name and address.
None of these benefits is available with the simple
(at least not without making it significantly less simple).
utility also offers an organizational benefit: the program
knows where the templates it uses are stored, so the
have to remember where they are (this is not the case
with the redirection
The formletter program is invoked with the syntax:
formletter template address ...
which will send the form letter specified in template
to one or more specified addresses. If the template
is absent, the
program produces a usage message describing the command
listing all templates currently on file.
Form letter template files are assumed to be stored
in the sender's
~/lib/formletters directory. Listing 1 shows a simple
file containing a subject specification and the text
of the form letter
to be sent. (In this case, it's the notice I send when
the COPS program
suite detects that a user has a .netrc file that others
There are only two things necessary to know in order
to create such
Rule 1 -- The subject specification is a
single line in the template file with the syntax:
and the only placement requirement is that such a line
precede the formletter text specification. If the subject
contains double quotes, they should be preceded with
Rule 2 -- The text specification starts
with the single line
All lines following this line to the end of the template
file are treated as text to be included in the form
By default, the utility adds a "greeting"
line at the top
of the sent message consisting of the recipient's first
by a couple of hyphens. It guesses the first name by
looking up the
recipient's ID in the password file and splitting off
the first word
in the GCOS ("real name") field -- unless,
the recipient's specified address contains an @, in
it assumes the recipient is located at another site,
and would not
be present in the local password file.
This first-name informality is usually appropriate at
site, where most communication is with students, faculty,
Even so, it quickly became clear that it would be desirable
the default greeting in certain cases. For example,
the user wfc
is in the password file as "William F. Costa,"
but I would
prefer that my mail refer to him as "Bill."
At the opposite
end of the formality spectrum, the University's president
dfn, real name "Dale F. Nitzschke"; just to
be on the
safe side, I would prefer that he be greeted not as
but as "President Nitzschke."
Overriding greetings are set up in the optional file
which, if present, contains any number of lines in the
The .greetings file can also be used to specify
greetings for non-local recipients who aren't looked
up in the password
Advanced Form Letters
In addition to subject and text specifications, form
may optionally include eval sections containing Perl
is to be executed once for each recipient. Any Perl
code can be specified
in the eval section; in the typical case, the code will
values for one or more Perl variables. Any occurrence
of those variable
names in the template's text section will be replaced
by the variable's
value in the outgoing mail. This simple scheme allows
modification and personalization of the form letter's
content in addition
to the static text.
The eval section adds a third syntax rule for form letter
to the two seen previously:
Rule 3 -- The eval section starts
with the single line
and is terminated with a blank line. All lines between
the Eval: line and the blank line are treated as Perl
to be executed once per recipient. The eval section
the text section. The code in the eval section can use
Perl variable $whoto, which contains the address of
to whom the form letter is being sent.
As a relatively simple example, Listing 2 shows a form
that warns a user of the imminent deletion of his or
In composing this letter, I wanted to warn the user
a couple of weeks
ahead of time, and have the letter mention the specific
The Perl statements in the eval section permit that
via Perl's time and localtime functions, a list (@in2wks)
containing the components of the future date. (For C
Perl's localtime function is analogous to ANSI C's localtime()
function; it returns the values identical to those specified
struct tm structure.) The routine uses the @moname and
@dname lists to convert the month and day-of-week numbers
by localtime into the corresponding words.
The template's text section contains references to the
in the eval section; in the mail sent to the recipient,
will be replaced by the actual target deletion date.
Listing 3 shows a more complex example. This form letter
is sent to
inexperienced users who have (probably unwittingly)
stopped one or
more of their processes by typing Control-Z. (A number
users come from environments where Control-Z does something
different, so this is a pretty common occurrence.) The
section in the template runs the command ps -axuww which,
our system, outputs information concerning all processes
for all users.
A couple of calls to Perl's grep function filter out
stopped processes for the recipient; the commands that
stopped processes are extracted from this list and inserted
mail sent to the user. (Portability note: this code
on the way the ps command is invoked on our system --
a BSD-like UNIX variant -- and makes assumptions about
of the user commands and process status in the output
from the ps
command. It may well not be portable to other systems
The formletter program is shown in Listing 4. Users
to install it at their location may want or need to
change the values
of some variables initialized near the top of the code.
the code assumes:
form letter templates and the alternate greeting data
file are stored in the directory ~/lib/formletters;
the definition of $letterdict to use something else.
the sender's (optional) signature is in the file ~/.mailsig;
change the definition of $sigfile to use something else.
the underlying mailer is /usr/ucb/mail; change
$mailer if you want to use another one.
the program sleeps 30 seconds between mailings to multiple
users (our system performance degrades if too many messages
near-simultaneously); change the variable $sleepytime
system behaves better, or worse.
the alternate greeting file is named .greetings;
change $altgreetfile if you prefer another name.
The program itself is relatively straightforward Perl
code. The key
to getting variable substitution in the text relies
on Perl's powerful
eval function, which executes the Perl code passed to
an argument. The eval function is used in two ways:
run the code contained in the eval section of the form
template; (2) to do the variable substitution necessary
each line of the text section into the message which
is actually mailed.
The topics and text of form letters will vary greatly
from site to
site, depending on the nature of the user community,
and other environmental factors. At this location, I've
used the utility
in the following general areas:
To notify users of security problems with their accounts
(as in Listing 1): poor passwords, bad directory or
and so on. (Depending on the seriousness of the problem,
letter may ask them to fix the problem, or notify them
that I've fixed
To notify users of system-use problems (as in Listing 3
): runaway or stopped processes, too much disk space
used in the
spool or temporary directories, .forward files that
mail to bounce, and so on.
Administrative tasks (as in Listing 2): letting users
know of changes to their accounts, changes to system
affecting them, and so on.
Answers to frequently-asked questions. ("I just
got a 9600-baud modem, what phone number do I call?"
does my friend see to apply for an account?" "What
to my account over the summer?" And so on.)
About the Author
Paul Sand is a system administrator for academic UNIX
at the University of New Hampshire. He has worked with
since 1984. He may be contacted via email as firstname.lastname@example.org.