Next: sendmail plain, Up: sendmail [Contents][Index]
Here we discuss how to programmatically compose a minimal email message to be used in testing email scripts. Basically a message should look like this:
Sender: marco@localhost From: marco@localhost To: root@localhost Subject: demo from sendmail-plain.sh Message-ID: <15704-6692-23464@this.hostname> Date: Tue, 28 Apr 2009 06:16:01 +0200 This is a text demo from the sendmail-plain.sh script. -- Marco
We have to remember that the SMTP server receiving the message may rewrite the addresses, for
example: replacing localhost
with the fully qualified local host name (the output of the
command hostname --fqdn
); so, when reading the delivered message, we do not have to be
surprised to find changed addresses.
We want to notice the following:
hostname
command like this:
LOCAL_HOSTNAME=$(hostname --fqdn)
do not confuse this value with the host name of the SMTP server!
Message-ID
header must be enclosed in angular parentheses, and it must
contain an address–like string with random characters in the name part. We can generate it with:
printf -v MESSAGE_ID '%d-%d-%d@%s' \ $RANDOM $RANDOM $RANDOM "$LOCAL_HOSTNAME"
or with:
printf -v MESSAGE_ID '%s@%s' \ $({ IFS= read -n 15 line </dev/random \ echo "$line" ; } | \ md5sum --binary | cut -f1 -d' ') \ "$LOCAL_HOSTNAME"
Date
header must be the current date in a specified format. We can generate
it using the GNU Date program like this:
DATE=$(date --rfc-2822) || exit 2
--
(dash, dash, white space). When composing the message we have to be
careful to use commands that do not drop white spaces.
In the end, we can use the following chunk of code to compose an email message:
PROGNAME=${0##*/} FROM_ADDRESS=marco@localhost TO_ADDRESS=root@localhost function print_message () { local LOCAL_HOSTNAME DATE MESSAGE_ID MESSAGE LOCAL_HOSTNAME=$(hostname --fqdn) || exit 2 DATE=$(date --rfc-2822) || exit 2 printf -v MESSAGE_ID '%d-%d-%d@%s' \ $RANDOM $RANDOM $RANDOM "$LOCAL_HOSTNAME" MESSAGE="Sender: $FROM_ADDRESS From: $FROM_ADDRESS To: $TO_ADDRESS Subject: demo from $PROGNAME Message-ID: <$MESSAGE_ID> Date: $DATE This is a text demo from the $PROGNAME script. --\x20 Marco " printf "$MESSAGE" }
notice that to put the required single white space character in the text/signature separator we use
the escape sequence \x20
(where 20 is the hexadecimal value of the white space character in
the ASCII encoding) and print the message with printf
, which expands the escape sequences.
When sending the message to the SMTP server we have to:
\r\n
).
So we can use an equivalent of the following chunk of code, assuming 3
is the file descriptor
connected to the remote SMTP server:
print_message | while IFS= read line do if test "${line:0:1}" = '.' then printf '.%s\r\n' "$line" >&3 else printf '%s\r\n' "$line" >&3 fi done
notice that read
is executed in an environment in which IFS
is set to the empty
string, this is to prevent unwanted modification of the message text. read
splits the string
it reads into words according to the current value of IFS
, and this may lead to mutation of
the input string; word splitting happens when there is a single output variable, too. To prevent
word splitting, we set IFS
to the empty string.
Next: sendmail plain, Up: sendmail [Contents][Index]