Lessons by Jon

Real World Lesson - Email

In this lesson we will learn two ways of using a form to send electronic mail. One method uses AppleEvents to control Eudora, a popular (and free) e-mail application. The other method uses the TCPIP Scripting OSAX to send e-mail. The latest version of the TCPIP Scripting OSAX is not free, but it is reasonably priced if you are getting a lot of use out of it, and it places less of a memory load on your server. Otherwise, go with Eudora.

Required OSAX

either the TCPIP Scripting OSAX or Eudora

If you don't already have these installed, look at instructions for obtaining and installing the needed software.

Step By Step

These scripts are getting much too long for me to keep printing them out in full. From here on I'll print only the sections pertinent to the lesson. You can still get the full scripts from the archive, though. They are "Email.txt" (using TCPIP Scripting OSAX) and "EmailEudora.txt" (using Eudora).

Both scripts assume that you have obtained certain information from the user via a form. The variables and their contents are as follows:

The real name of the user
The e-mail address for the user (who it is from)
The subject of the message
The message itself
You should already know how to do this. If not, see the last lesson.


The first lesson we will look at is the one that uses Eudora to handle the mailing. The code section below is inserted just after you have finished parsing the post_args argument and have all of the variables assigned.

-- create new message in Eudora 1.4.3 (any later version will work as well)
   -- to compile this, you have to do "Check Syntax" and locate Eudora.
   -- Don't forget to configure Eudora correctly!!
   tell application "Eudora1.4.3"
      set newmessage to (make message InsertHere end of mailbox "Out" of mail folder "")
      set field "To" of newmessage to "user@machine.name.net"
      set field "From" of newmessage to from_address
      set field "Subject" of newmessage to email_subject
      set field "" of newmessage to "From: " & username & return & return & email_body
      queue newmessage QueueType 0
   end tell
You can see that Eudora allows every element of the mail message to be set via AppleScript, a very nice thing for them to do. I've heard that the commercial version allows even more control! Although it should be very clear what is happening here, there are a few points to remember:

Don't Forget! - MacHTTP is still waiting for a reply. Even though you've mailed off a message, MacHTTP still wants a little something to hand back to the user. The best thing is to make up a quick HTML page that says "this is what I think you sent" and pass it back. Look at the script provided.

TCP/IP Scripting OSAX

This OSAX is a product of Mango Tree Software and costs $20 for the latest release. That may seem a little bit much for sending e-mail, but it is much more powerful than that. I just don't have the patience to try anything else. Using this method has the added advantage of being faster than using Eudora, at least in my own experience. I'm not sure why this is so. The portion of the script that handles mailing uses routines provided by Eric Morgan in his email.cgi.

The code for this example is much longer than for Eudora. This is because we have to do everything manually that Eudora automates. That includes negotiating connections with a mailserver, handling data streams, and checking for errors or interruptions. There is no way I am going to comment on every line of this code; I don't even understand every line and I don't feel like reading a TCP/IP book right now. Instead, I'll just give you the code and point out key areas to change for your own site.

First, the code. It comes in four sections. The first is one line that is added to the main Appleevent handler in the same place the Eudora code should have gone. It looks like this:

		send_message(email_host, to_address, from_address, email_subject, email_body)
As you can see, it requires two more variables, to_address and email_host. The to_address is simply the address you want to mail to. You could enter the text directly, but this is easier to read. email_host is the name of the SMTP mailer host that you will be using to send the mail. This is usually a Unix or IBM machine that handles all of the mail at your site. That's all I know about that.

The second section is the send_message handler that is called above. This handler gets passed the five variables and is responsible for sending the mail message. Basically, it takes the place of Eudora. The code is very long, as follows:

on send_message(email_host, to_address, from_address, email_subject, email_body)
   set crlf to (ASCII character 13) & (ASCII character 10)
   set sss to (tcp connect to host email_host port 25)
   tcp write data "mail from: " & from_address & return stream sss using ISO88591
   tcp write data "rcpt to: " & from_address & return stream sss using ISO88591
   tcp write data "data" & return stream sss using ISO88591
   tcp write data "To: " & to_address & return stream sss using ISO88591
   tcp write data "Subject: " & email_subject & return stream sss using ISO88591
   tcp write data email_body & crlf & return stream sss using ISO88591
   tcp write data "." & return stream sss using ISO88591
   tcp close stream sss
end send_message
This section calls another subroutine, readresponse(sss) in order to handle the information returned from the mail server. The code for readresponse is as follows:
on readresponse(sstream)
 set LF to ASCII character (10)
 set continuechar to "-"
 set wholemessage to ""
   repeat until continuechar = " "
      repeat until (tcp ahead characters LF stream sstream)
      end repeat
      set readline to (tcp read until characters LF stream sstream using ISO88591)
      set scan to (scanline(readline))
      set continuechar to item 2 of scan
      set wholemessage to wholemessage & " " & item 3 of scan
   end repeat
   set errorCode to item 1 of scan as integer
   if (errorCode >= 400) then
      error wholemessage number errorCode
   end if
 on error errMsg number errNum
   set return_page to http_10_header & "<HTML><HEAD><TITLE>Error Page</TITLE></HEAD>" ¬
      & "<BODY><H1>Error Encountered!</H1>" & return ¬
      & "An error was encountered while trying to read the mailer response." & return
   set return_page to return_page ¬
      & "<H3>Error Message</H3>" & return & errMsg & return ¬
      & "<H3>Error Number</H3>" & return & errNum & return ¬
      & "<H3>Date</H3>" & return & (current date) & return & "</BODY></HTML>"
   return return_page
 end try
end readresponse
readresponse accepts a text stream from the mail server and breaks it up into a list of three items, the first of which is a response number. Notice how this subrouting uses the "try...on error" structure to handle errors. Any return code greater than 400 indicates an error. It wouldn't be a bad thing for the send_message to use this same type of structure to notify the user in case of errors. Notice also that the error message returned is different in each one. This lets you know more exactly where the error occured.

readresponse in turn calls a very small subroutine, scanline that looks like this:

on scanline(lline)
	return {characters 1 through 3 of lline as string, character 4 ¬
		of lline as string, characters 5 through end of lline as string}
end scanline
It's not much, and probably could be rolled into the previous subroutine easily, but that's the way it Eric wrote it and I don't feel like rewriting it just for that.

You will definitely want to take a look at the original script for this one, to see how everything is laid out. It is much more complex than the Eudora script, although everything is pre-written for you and shouldn't need changing.

Test the Script

From now on you will have to test these scripts on your own machine. There's nothing more my machine can teach you, and it's about time you learned to install your own forms and CGI applications. If you are a bit confused by that process, look at these easy to use instructions. The form and script are both provided in the archive you downloaded. Use the form named "FormTest2.html" and one of the two Email scripts listed above.

Wrap It Up

Well, we actually got something useful done this time. These scripts are very popular since very few clients handle the "mailto:" reference yet. Beyond that, there is a lot more flexibility with these, since you can use hidden fields to pass more information, do special checks on the data, and do other things besides mail (like logging the mail). In addition, the scripts could be extended to automatically include a file enclosure or two if you wanted. Maybe someday I'll cover that lesson, too.
[Back To Form Page]

Jon Wiederspan
Last Edited: December 11, 1994