Articles Archive
Articles Search
Director Wiki
 

Sending email in Director

January 5, 2000
by Zac Belado

"You've got a potential trademark violation!"

Director has very strong net integration features. You can access data from web pages, download files from servers and even communicate with CGIs. But most importantly, you can access and monitor the status of these processes and report back to the user if there is an error or problem. If you want to send email from Director though, you are not so lucky. Director has no native functions that handle processing email, with the result that you have to rely on other means if you want to send mail from within Director.

This article will discuss three ways to send email in Director. Using gotoNetPage, connecting with a server side CGI or by using the DirectEmail Xtra from DirectXtras.

gotoNetPage

Perhaps the simplest way to attempt to send an email message via Director is to use the gotoNetPage command and use a mailto URL instead of an http URL. The mailto format is quite simple.

mailto:<address>

or

mailto:zac / at / director-online.com

Test it out. Open Director, open the Message Window and enter

gotoNetPage "mailto:zac / at / director-online.com"

and then hit RETURN.

If your system is configured properly then your designated email client should activate and display a new email message with the To: recipient filled out with my email address.

The mailto URL can also be passed an optional subject which is separated from the email address by a query marker (a question mark to the rest of the world). That subject has to be URL encoded in order for your email client to be able to process any spaces or special characters. So if you wanted to send me a an email message with the subject "Hi Zac" you might use...

thisSubject = "Hi Zac"
thisSubject = os_URLEncode(thisSubject)
url="mailto:zac / at / director-online.com?subject=" & thisSubject
gotoNetPage url

Notice that in the example I do not use the URLEncode() function provided in Director 7. That is because the function that comes with Director 7 converts spaces in a string to a +. Most email clients (and browsers I suspect) will have problems with this as they will expect spaces to be encoded as %20 instead. So I have written my own function to "properly" encode the strings. The code for the function (with a few supplementary functions it calls) are in the sample movie.

While this is a very simple way to create an email message there are several problems with it. First, you can't uniformly specify the body of the message or any of the other recipients. So if you want to add CC and BCC recipients, as well as define the message body you may or may not be able to do this depending on how much information your user's email client will parse from a mailto URL. Some might and some might not. So unless you know what email client the user has, it is a bit of a crap shoot to attempt to send more data than the To: address and the subject.

Secondly, even though you can create a message there is no guarantee that you can get the user to send it. All a mailto URL will do is create the message. The user still has to send the message themselves.

Thirdly, you can't monitor the progress of the process. Once you make the gotoNetPage call you've lost control of the process. This means you can not provide any feedback to the user if there is an error. Or even know if there is an error.

Finally, gotoNetPage is notoriously flaky when it comes to processing mailto URLs. This isn't a result of any problem with Director but in the way that most browsers and operating systems deal with mailto URLs. If the user's system is not configured properly they will quite often see their web browser open and then it will open/activate their email client. In some extreme circumstances, the browser is misconfigured and won't be able to pass the mailto URL to the email client. And since you can't track the process you have no way to know if this happens.

All in all not an optimal solution.

Server side CGI

A better solution is to use a server side CGI to send the email. This requires that a CGI exists on your server to handle the task of actually sending the mail. Most ISPs have standard CGIs available for their clients, and if not, you can find numerous examples at sites like the CGI Resource Index. Communicating with the CGI is quite simple with Director 7 since it has a postNetText function that works in the same fashion that most web based forms do. The following example will be a bit vague as this article has (for reasons that will become clearer later on) no sample CGI. Instead we will deal with more general issues surrounding the topic.

Let's assume that you are sending data to a CGI that allows you to supply the following data: to, from, subject, CC and messageBody. If these data elements were all supplied from fields in your Director project then you could communicate this data by creating a postNetText call.

toRecipient = member("toField").text
fromRecipient = member("fromField").text
subject = member("subjectField").text
ccRecipient = member("ccField").text
body = member("bodyField").text
thisURL = "http://www.somedomain.com/cgi-bin/formMail.cgi"
propList = [#to: toRecipient, #from: fromRecipient, ¬
  #subject: subject, #cc: ccRecipient, # messageBody: body]
thisNetId = postNetText (thisURL, propList)

postNetText is very similar to getNetText. It takes a URL and a property list (or a series of string data) and returns a network ID that you can use to track the progress and results of the network call. So any network code that you have (or have lifted from articles dealing with communicating with CGIs will work with postNetText calls with little or no modification.

For the postNetText call to actually send the data to the CGI you need to provide a property list with a property for each data element you want to send to the CGI. As mentioned before our example CGI needs to, from, subject, CC and messageBody data elements. So the property list we build in the code sample above provides a symbol and string for each data element. This data will be sent to the CGI.

You can also send the data as plain strings but if you do this the data is sent as "text/html" and this may not be compatible with most CGIs.

While using a server side CGI does give you more control over the emailing process there are also downsides. First, most CGIs are written in Perl. This is fine if you know Perl or have access to a Perl programmer but if you aren't experienced with it then modifying a Perl CGI can be a bit daunting.

Secondly, Perl scripts (and most CGIs) can be rather problematic to install and get running. I know that some people will disagree with this but my experience has been that Perl configuration is something best left to the experts. On the plus side, once the CGIs are installed and configured they usually run with no problems.

Thirdly, most of the easily available CGIs will be written for use in web pages and will report their data in a fashion that might not be optimal for use in Director or Shockwave. This means that you will most likely have to rewrite some of the CGI in order to customise the data it returns in order to be able to report back to the user about the status of the message.

DirectEmail Xtra

Perhaps the best solution is to use the DirectEmail Xtra from DirectXtras. The xtra is cross-platform and is also Shockwave safe (check out this Shockwave version of the sample movie) meaning that you can create and deliver email solutions to a wide range of users with it. The xtra is also relatively easy to use and allows you to contain the entire messaging process inside Director.

A sample movie is available for download in Mac or PC format. This is a Director 7 movie

The xtra has very few methods

The process of using the Xtra to send an email message is very straightforward.

Step 1

The first thing you will need to do is create an instance of the xtra. This is done using the new method. You need to provide the xtra with the address of the mail server that the xtra will attempt to send mail through. This can either be provided by the user or, more likely, hard coded by you.

global gEmail
gEmail = new (Xtra "DirectEmail", "mail.somedomain.com", ¬
  "", "")

Once you've created the instance of the xtra you need to store it either in a global variable or in an object property so you can refer to it later. Note that the last two parameters (mailBoxName and password) are not currently used in this version of the xtra so you just supply blank strings instead.

Step 2

Now you need to gather the actual information that will make up the email message. In the sample movie this is done by getting the contents of a series of the fields that the user enters their data in. First you would get the data from the fields...

messageHasErrors = FALSE
errorMessage = ""
recipients = member("To").text
fromAddress = member("From").text
mailServer = member("MailServer").text
CCRecipients = member("CC").text
BCCRecipients = member("Bcc").text
body = member("Body").text
attachment = member("Attachment").text
subject = member("Subject").text

then store it somewhere convenient, like a property list, for easy reference...

  
-- store all the data in a nice property list
messagePropList = [#to:recipients, #from: fromAddress, ¬
  #server:mailServer, #CC:CCRecipients, ¬
  #BCC:BCCRecipients, #body:body, #subject:subject, ¬
  #attachment:attachment]

...and then do some tests to make sure that the user has entered data. You might also want to test the validity of the data to ensure that they enter valid email addresses and, if necessary, a valid mail server address. The code for the isValidEmail() function and the emailValidationError () are both in the sample movie. In this instance we're just testing the To: and From: addresses.

  
 if recipients = EMPTY then
    messageHasErrors = TRUE
    errorMessage = errorMessage & "You need to ¬
      specifiy at least one recipient" & RETURN
  end if
  
  if fromAddress = EMPTY then
    messageHasErrors = TRUE
    errorMessage = errorMessage & "You need to ¬
      an email address to send the message from" & RETURN
  end if
  
  -- check to see if the email addresses are valid
  toAddressHasErrors =  isValidEmail (messagePropList.to)
  fromAddressHasErrors = isValidEmail (messagePropList.from)
  
if toAddressHasErrors then
    messageHasErrors = TRUE
    errorMessage = errorMessage & "The To: address ¬
      you supplied is not valid because" && ¬
      emailValidationError (toAddressHasErrors) & RETURN
  end if
  
  if fromAddressHasErrors then
    messageHasErrors = TRUE
    errorMessage = errorMessage & "The From: address ¬
      you supplied is not valid because" && ¬
      emailValidationError (fromAddressHasErrors) & RETURN
  end if

If there are no errors then it's safe to send the message data to the instance of the Xtra that was created earlier.


  if NOT messageHasErrors then
    
    isOkayToSend = sendEmail (gEmail, ¬
      messagePropList.from, messagePropList.to, ¬
      messagePropList.cc, messagePropList.bcc, ¬
      messagePropList.subject, messagePropList.body, ¬
      messagePropList.attachment)
 
  else
    alert errorMessage
  end if
  

Step 3

Now we just have to wait until the process is complete. The DirectEmail Xtra has a function, emailDone(), that can be tested to see if the process is complete. This is very similar to using netDone() to see if a network process has completed. Except that you use a reference to the xtra's instance instead of a network ID. You can test this function in an exitFrame handler or, more preferably, in a stepFrame handler in an object or behavior.

The sample movie included with this article handles all the mail processing inside a single object in order to simplify the movie. This doesn't mean that you have to use objects, only that the author is the fussy type of person that uses objects for everything. It is quite simple to test the emailDone() function in an exitFrame handler and then go to another frame once the process is complete

global gEmail
on exitFrame
-- are we done?
  if EmailDone(gEmail) then
   
    go to frame "done"
  else
    member("status").text = "Waiting for results..."
  end if
end

Step 4

Once you know that the mail process has been completed you need to test the emailErrorCode() function to see if the mail has been sent successfully.

emailHasErrors = EmailErrorCode(gEmail)
    
 If NOT emailHasErrors then
   member("status").text = "Your Message was Sent!"
 else 
   member("status").text = "Error:" && emailHasErrors ¬
     && emailErrorMessage(gEmail)
 end if

emailErrorCode() returns a zero if the process was a success or an integer value, representing the particular error, if there was some problem. The emailErrorMessage() will return a string describing the error that you can use to report the problem to the user.

Part of the appeal of the DirectEmail xtra is that it allows you to test, and report, for conditions that the other two methods don't allow you to do. If the user's net connection was terminated in the middle of the mailing process then the xtra will report this condition. If the mail server the user specified has no DNS entry then you will be informed of this and be able to pass this information back to the user. Additionally, it allows you to initialise and control the entire process inside your Lingo code. Meaning that you are not subject to OS configuration problems, missing email clients or CGI peculiarities.

Details, details, details

The code in the sample movie uses the same steps that are outlined above but it uses an object to contain all the interaction with the xtra. This was done for two reasons. First, it simplifies the movie. The movie has, with the exception of some utility routines, two button scripts, a function to test the validity of the user supplied data and a "go to the frame" exitFrame handler. It is an extremely basic movie. Secondly, it makes it very easy to re-use the majority of the code with very little work. Since the bulk of the code is in one object you can almost add the code to another movie with a simple copy and paste.

In the sample movie nothing actually happens until the user hits the send button. Then a handler, the aptly named sendMail (), tests the data. If the data is valid it then creates a property list, creates a new object and then passes the data off to the object. The object is stored as a global variabe.

The object creates an instance of the xtra and stores it as a property. The xtra isn't accessed at all except from inside the object. The object then sends the mail data to the xtra and then adds itself to the actorList.

Inside a stepFrame handler, the object checks to see if the email process is complete and, if it is, it tests for any errors and reports them back to the user. The object then destroys the instance of the DirectEmail xtra and calls an external handler stopEmail (). The stopEmail handler then destroys the object.

Summing up

Out of the three options discussed, the only two really usable methods are server side CGIs and the DirectEmail Xtra. gotoNetPage might look like a quick and easy solution but it has several potential problems that you will not only have no control over but no way of testing for. Using a server side CGI is a workable solution if you have experience writing CGIs or have access to a programmer who can write, or modify, a CGI to fit your needs. The DirectEmail Xtra is perhaps the best answer if you want to create a self contained Director based email solution.

Zac Belado is a programmer, web developer and rehabilitated ex-designer based in Vancouver, British Columbia. He currently works as an Application Developer for a Vancouver software company. His primary focus is web applications built using ColdFusion. He has been involved in multimedia and web-based development, producing work for clients such as Levi Straus, Motorola and Adobe Systems. As well, he has written for the Macromedia Users Journal and been a featured speaker at the Macromedia Users Convention.

Copyright 1997-2024, Director Online. Article content copyright by respective authors.