The mailme command is designed to simplify sending text files
from the bash shell of a Linux or Unix system to an external e-mail
address. The goal of this project is to develop a simple
command and demonstrate some of the features and capabilities
of bash shell script programming to assist in systems administration
tasks.

Say that we decide that it is desirable to
have a simple command to send text files in the body of an e-mail
message which looks like this at the command-line level:

mailme filename

where filename is the name of the file we want to get. The
syntax for the mail command to accomplish this task is:

mail -s subject address
< filename

In this example, the contents of filename
is used to create the body of an e-mail message sent to address with
the subject line indicated by subject. In a specific example:

mail -s 'mailme test' james@keeline.com
< resume.txt

where the contents of resume.txt is sent
to james@keeline.com with the subject line of "mailme test".

We can use a feature of the bash shell
to make an alias which will create a temporary command.
If we want to have this available all the time, we can place the
following instruction in our .bash_profile file to be implemented at each login:

alias mailme="mail
-s 'mailme test' james@keeline.com < resume.txt"

This will create a function to send this particular
file, resume.txt, to james@keeline.com. It is not very useful as is. Fortunately, the
bash shell assigns variables to command lines it tries
to interpret. In our target example:

mailme filename

the phrase "mailme" is assigned
to a variable called $0 and the first argument following the command, "filename"
in this case, becomes $1. If additional parameters followed "filename",
they would be assigned to $2, $3, and so on. We can use this feature to designate
a filename in our alias definition without "hard coding" it.

alias mailme="mail
-s 'mailme test' james@keeline.com < $1"

This is a help and it is functional but it
would be nice if we could make the subject line more meaningful.
A useful subject line might be the name of the file. To
accomplish this, we use the $1 variable a second time in the definition:

alias mailme="mail
-s $1 james@keeline.com < $1"

Notice the use of quotation marks in these
examples. By using single quotes ('), we tell the bash shell
to print the contents exactly as shown. When we use double
quotes ("), the contents are evaluated. That is, if special
character are seen, like $1, the value will be looked up and inserted in the command
line in place of the symbol.

An additional consideration is that while you
can nest single quotes inside of double quotes, you cannot nest
the same type of quotes within themselves. If you are using
double quotes to define your entire alias, you cannot use
double quotes inside that definition. It would confuse the
bash shell.

This would cause a problem if we decided that
we wanted to use the name of the command (represented by $0) followed
by a space and the name of the file (represented by $1).
To get the quotes nested in the proper order we would have to
do something like:

alias mailme='mail -s "$0
$1" james@keeline.com < "$1" '

Here we are using single quotes for the alias
definition which is allowed. As expected, the $0 and $1 variables
need to be placed inside of double quotes to have them evaluated
by the bash shell as the command is interpreted.

Maybe we decide that this isn't general enough.
If we were a systems administrator, we might want to make this
useful command available to everyone of our users. We could
create an alias definition in each user's .bash_profile file
or we might want a more general command which could be placed
in one of the profile files which is run for each user.

To accomplish this we would need a way to get
the e-mail address for each user as they use the command.
Fortunately, the bash shell maintains a set of "environmental variables"
for each user session. To see a list of these we can issue
the following command:

printenv

The result is a screen-long list of variable
names which are in ALL CAPS. A couple which are useful
for us are the USER and HOSTNAME which can comprise the e-mail address of a user on
this system. To display the results of one of these variables
at the command-line level, we can type:

echo $USER

We could use these in the previous example
in the following way:

alias mailme='mail -s "$0
$1 $USER@$HOSTNAME < $1" '

Notice the placement of the quotation marks.
The material in the double quotes will be evaluated and replaced
with their values before the command is executed.

The trouble with this particular implementation
is that it sends the message to an account on this system. While
it is true that e-mail on that system could be accessed with a
POP3 client at home (if the server was turned on), it might be
nice to send the e-mail to a completely different e-mail address.

Fairly early in the class we used the chfn command
to change the information about ourselves in the finger database.
We placed our main e-mail address in the "Office" field
of the database. Normally, of course, this would be used
to store our office phone number. To display the contents
of the database for a given user, we can type:

As you can see, the external e-mail address
and group number appears on a line which begins with "Office:".
We can use the grep command to search for "Office:" and output
the line which contains it. To do this we use the "pipe"
function using the pipe character (|) as follows:

finger keeline | grep 'Office:'

The result is a single line of output:

Office: James@Keeline.com,
4

As before, we can replace the single specific
user name ("keeline") with the environmental variable $USER thus:

finger $USER | grep 'Office:'

to get a single line containing the user's
external (or internal) e-mail address if it was placed in the
"Office" field of the finger database.

The trouble is that there is extra information
in the line. It is not a valid e-mail address with the extra
information. As expected, the Linux operating system has
utilities to assist with this. In this case we can use the
cut
command with certain options.

After reading the pages under man cut, we can
see that two the cut command defines "fields" as separated
by the [tab] character by default. In the example above,
however, we see that we really want to look at the second field
if the fields are defined by [space] characters.

This can be achieved by using the '-d' option
to define the separation character and the '-f' option to specify
the field we want. The cut command we want looks like this when attached to the
previous finger example:

finger $USER | grep 'Office:'
| cut -d' ' -f2

The result is almost what we want:

James@Keeline.com,

The extra comma (,) will cause a problem;
it is not a valid e-mail address with it and it might confuse
the mail command into thinking that the next item is another
e-mail address. We can use the cut command again, this time
by defining the separation character as the comma and grabbing
the first column from the output of the previous command.
The entire command looks like:

finger $USER | grep 'Office:'
| cut -d' ' -f2 | cut -d',' -f1

The result is exactly what we want:

James@Keeline.com

Now we want to get this into the previous mailme
definition in place of the address. The definition was:

alias mailme="mail
-s $0 $1 $USER@$HOSTNAME < $1"

We can use a feature of the bash shell
which tells the system to evaluate a single command or a series
of commands and replace the command definition with the results
of that command. By using the accent mark (`) which
is located on the same key as the tilde (~), we can define the
beginning and end of the command we want evaluated. The
result looks long and complicated (and it is) but if you look
at the previous two command line examples, it should be possible
to decode what is going on. We will insert our finger|grep|cut|cut command in place of the $USER@$HOSTNAME in
the mail command:

This line is longer than the 80 characters
on our terminal session but will work if carefully typed in exactly
in the order shown. The specific use of quotation marks
is important.

This does not work perfectly, however.
Our previous efforts to use the argument of the command ($1) as the
subject of the message is not evaluated properly and the subject
line is blank. The problem occurs because of the nesting
of the quotes.

We can simplify the quotation marks considerably
if we don't use the alias command. To do this, we must use
another method to create a command. In this case, we create
a text file with vi or some other method containing the following line:

and save it as 'mailme'. Notice that we can remove the space holders
(' ') from the previous example.

This will not execute as it is so we use the
chmod command to alter the permissions for the file to allow
us to execute the file but no one else (700):

chmod 700 mailme

If our home directory is not included in the
command search path, we will need to use the following syntax
to execute the command until the $PATH variable is changed:

./mailme resume.txt

This time, the subject line is appropriately
evaluated with the filename sent as the subject of the e-mail
message.

If we want to have this as a regularly avaliable
executable command, we can do one of two things. The first
is to place this file in a directory which is listed in the $PATH.
One of these which is available to us is a bin directory (not
/bin which is for the entire system unless we want to give
it to everyone in which case the permission would have to be changed
to 711) within our home directory. For me, the full
path is:

/home/keeline/bin

If it is not present, you can add the directory
by typing:

mkdir ~/bin

and then move the file to that directory:

mv mailme ~/bin/mailme

The other method involves examining how the
$PATH variable is set in .bash_profile and adding your home directory (/home/keeline in my
case) to the string with the vi editor. Either method will work.

This is how I added this command to my system.
What commands would you add with these techniques?

James D.
KeelineWarning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /home/keeline/public_html/iteachphp/index.php on line 130