Automating frequent tasks

Mail tools

The following tools are used for manipulating mail folders and sending large files through mail.

Count the number of messages in MMDF mail folder

Consider the following script:

   cnt=`grep '^A^A^A^A' $1 |wc -l`
   print $(( cntot = cnt / 2 ))
MMDF stores messages in a folder as continuous ASCII text, delimited at top and bottom by a line containing four <Ctrl>A characters. This script searches for the message delimiters and sets cnt to the number of lines containing delimiters. It then uses the Korn shell arithmetic facility to divide this total by two (because there are twice as many delimiters as messages). Thus, this script prints the number of messages in a MMDF mail folder.

It is not appropriate to use this script on a XENIX-format mail folder.

NOTE: To enter the <Ctrl>A characters in the script using vi, press <Ctrl>V then <Ctrl>A for each character.

Print the header lines of every message in a folder

The following short script searches the files named by its positional parameters for lines beginning with the string ``Subject:''.

   grep "^Subject:" $*|cut -c9-7
Mail headers consist of a series of lines beginning with keywords, like this:
The subject lines are printed through a pipe to cut, which chops out and prints only character positions 9 through 71 on each line (thus removing the string ``Subject:'' and truncating long lines).

Note that this script makes no allowances for mail messages that contain other (quoted) messages without indentation. To do this, it would be necessary to write a longer script. (Hint: The end of a mail message is indicated by two lines containing four <Ctrl>A characters each. Valid mail messages can have only one ``Subject:'' line. A better script would search for the first occurrence of a ``Subject'' line following a sequence of ``^A^A^A^A''.) Note also that the ``Subject:'' line is not mandatory, so this script will miss messages that lack a subject line altogether.

Mail a large file, in pieces

Note that the line numbers in this example are not part of the script, but are provided for clarity: script, but are provided for clarity:

1 :	#! /bin/ksh
2 :	#
3 :	#----- blocksize*80 is the maximum size of each chunk created
4 :	#
5 :	blocksize=512
6 :	#
7 :	#----- perform sanity checks on input
8 :	#
9 :	case $# in
10 :	2)	: break
11 :		;;
12 :	*)	echo "
13 :	
14 :		$0 <user> <file>
15 :	
16 :		compress, uuencode, split into 1000 line chunks and mail
17 :		<file> to <user>.
18 :	
19 :		This script is used to send large files (greater than
20 :		32KB) via email. <user> must be a valid mail address;
21 :		On completion, chunk will send a status report to you
22 :		via email.
23 :		"
24 :	
25 :		exit 2	
26 :		;;
27 :	esac
28 :	#
29 :	#--------- test for a valid file -----------
30 :	#
31 :	target=$2
32 :	user=$1
33 :	
34 :	[ -s "$target" -a -r "$target" ] || {
35 :		print -- Missing, empty or not readable: $target >&2
36 :		exit 1
37 :	}
38 :	#
39 :	# -------- end of sanity checks ------------
40 :	#
41 :	tmpdir=${TMPDIR:-/u/tmp}/$$
42 :	
43 :	mkdir $tmpdir || exit 1
44 :	compress < $target | uuencode $target | (cd $tmpdir; split -$blocksize)
45 :	cd $tmpdir
46 :	for chunk in *
47 :	do
48 :		mail -s "section $chunk of $target" $user < $chunk &&
49 :			print "Sent section $chunk at"; date
50 :	done 2>&1 | mail -s "Result of sending $target" $user
51 :	cd
52 :	rm -rf $tmpdir

This script (called chunk) takes two arguments; a valid mail address and a filename. Because the consequences of proceeding on the basis of a bad argument list could be messy, some checks are carried out (from lines 9 to 27). The case statement on line 9 tests whether there are too few arguments, and aborts with a usage message if this is the case.

The real work of the script is carried out from lines 41 to 52: target has previously been assigned the name of the file to transmit. The file is compressed, and uuencoded, then piped through split into sequentially named chunks of blocksize lines that are stored in $tmpdir.

Some mail gateways will not handle messages which are more than some arbitrary size; therefore the exact size of the chunks created by this mailer is defined in a single variable which can be adjusted easily.

A for loop now iterates over each chunk and invokes mail. Because the chunks contain no human readable information, it is vital to incorporate the name of each chunk in the message header.

Finally, a record of the transmission is mailed to the recipient, so that they know what to do with the pieces.

To reassemble a file from its component pieces, save the pieces (in order) to a file, edit the file to remove mail headers and blank lines, uudecode the file, and uncompress it. This method can be used to send large files through size-restricted mail gateways.

Next topic: File tools
Previous topic: Other useful examples

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003