Back to PocoScript Index         < Previous

PocoScript Tutorial

Script writing, like any form of computer programming, requires planning. Think, in general terms, of the steps that will be required to complete the task. Remember to include error checking in your planning, think of where possible errors might be encountered and how you will overcome them. Another good method for developing a script is to take an existing one and adapt it to your needs. There are a number of very well written scripts available for free from the PocoMail website. Choose a script that has the basics of what you want to do and customize it from there. Remember to save it under a different name when you start editing it.

Another very useful technique in script writing is to only program small segments at any one time, inserting MessageBox commands to display the results of each step. If the script is composing a message to be sent and you want to view the contents of the message in order to debug it then the EditMessage command is particularly useful.

Two techniques that will assist you in reading a script are:

For the purpose of this tutorial we will create two scripts, one that will notify people who send us email that we are on vacation and the other to tag all annotated messages in a mailbox so they can be displayed using "Show only" bar.

Vacation Reply script

This script will notify people who send us email that we are on vacation. We don't want to confirm our email address to spammers so we will restrict the replies to people whose email addresses are in one of our address books. We also want to keep track of any messages which we have sent vacation replies to.

This script must extract the email address from the sender (the "To:" header in the incoming message), check the address book(s) to see if it is present and, if the address is found, format and send an automated reply to the sender.

Starting the script

The first step in creating the script is to open the scripts window. To do this press the F9 key or select "Scripts..." from the "Tools" menu. Press the "Edit Script" tab in the form header and then the "New Script" button near the bottom of the form.

Adding comments to describe the script

Enter some
comments describing the purpose of the script, the date you created it. In addition, if more than one person may be creating and/or editing scripts within your organization then add your name. Also include a modification log section. Something like the following:

     {  Script: VacationReply
     {  Created: June 13, 2001
     {  Author: Michael Motek
     {  Purpose: Part of the PocoScript tutorial. This script will send a message informing people you are on vacation.
     {  Mode: This script is designed to run against incoming messages.
     {  Modification log:

The next step is to add statements to handle any errors that may be generated. Since this script is designed to run unattended we do not want a message box to be displayed when an error in encountered. Thus we do not use the OnErrorMessage variable. The code to handle errors consists of a single statement immediately following the initial comments:

     Set $OnErrorGoTo ErrorHandler

This command directs the script to branch to the ":ErrorHandler" label if an error is detected. We must also add this label to the script. We insert an "Exit" statement after the label so the script will simply exit if an error in encountered (later we will enhance the error handling to write the messages to a log file). The statements we insert at this point are:

        Exit
     :ErrorHandler
        Exit

Note: We add an "Exit" statement immediately before the ":ErrorHandler" label. This will prevent the error handler from being executed when no error is encountered.

Allowing for customization of the reply text

Now we have to allow for customization of the reply text. This is done by adding statements that will run when the script is run in "Setup" mode. The text for the reply will come from a file named "VacationReply.txt". Add the following statements after the "Set" statement for the $OnErrorGoTo system variable:

     External $userfile1 "Reply text" "VacationReply.txt"

Reading the reply text

The script will also need to read the reply text. The "External" command above will put the file into Poco's "Mail" directory. Since people may customize the directory where they install Poco we need to construct a variable containing the drive, path and file name of the reply text file:

     Set $replyfile $mailpath
     AddStrings $replyfile "VacationReply.txt"
     OpenBody $replytext $replyfile

To test to see that we have read the file correctly we add a MessageBox statement:

     MessageBox $replytext

Now we test the script to this point. The first step is to use the "Setup" function to create a reply text file. Next we test the script itself. Since at this point we don't need a message for testing we can use the "Debug Run" button at the bottom right of the "Edit Script" pane.

Extracting the email address

Provided this step works properly we remove the MessageBox and proceed with the next task which is extracting the email address of the person who sent the note to which we are formatting the reply. We use the ReadHeader command to read the "From:" header and the ExtractEMail command to extract their email address from the header itself:

     { Get the sender's email address
     ReadHeader $from "From:" %message
     ExtractEMail $from

Note the use of the %message system variable. When a script is run against a message this variable contains the message passed to the script.

To verify the script is picking up the correct information add a MessageBox statement and test the script by running it against a message in one of your mailboxes.

Checking the address books

The next step, after removing the MessageBox statement inserted for testing, is to determine whether or not the email address of the sender is present in any of our address books. The new IsAddressPresent command is used here:

     { Check to see if the sender's email address is present in one of our address books.
     IsAddressPresent &sw $from
     If &sw Then Continue
        MessageBox "Not in any address book, no reply will be sent"
        Exit
     :Continue
        MessageBox "In address book, a reply will be sent"

Notes:
  1. The IsAddressPresent command checks your address books to see if the email address stored in the "$from" variable is present in any of them. Boolean variable "&sw" is set to the result of this search (True or False).
  2. The "If" command tests the value of boolean variable "&sw". If the value is true then the script branches directly to the ":Continue" label without executing any of the intervening commands, otherwise the script continues with the command following the "If" command. In this case we simply want to exit the script so an "Exit" command is inserted.
  3. Note the use of indenting to help see which commands are dependent on the result of the "If" command.
  4. Both MessageBox statements are for debugging only, once you have satisfied yourself that they are working remove them from the script.
To test this section of code you will need to run the script against two different messages you have received. One of the messages should be from someone in one of your address books while the other should be from someone who is not in any of your address books. After you are satisfied that this section of the script is working remove the "MessageBox" statements. From this point on, for the purposes of brevity in this tutorial, we will no longer be adding "MessageBox" statements for debugging. We encourage you to use this technique for testing and debugging your scripts.

Creating a message

The next step is to create a variable to contain the reply to the message. The CreateMessage command accomplishes this:

        { Create the reply and add the necessary headers.
        CreateMessage %m

This command is inserted immediately following the ":Continue" label.

Filling in the message header fields

We need to fill in the various header variables to ensure the message can be delivered. The mandatory headers are: We use the address extracted from the message (in the "$from" variable) as the recipient:

        AddTo %m $from

Now we want to assign a subject to the email. We don't want the person receiving the note to think we are actually replying to it so we use a static subject line rather than copying the subject line from their note: The AddHeader command accomplishes this task.

        AddHeader %m "Subject:" "Vacation reply"

We also need to set put our email address into the "From" header in the reply. This can be extracted from the settings for the current Poco account using the following commands:

        ReadEmail $from
        AddHeader %m "From:" $from

For debugging purposes at this point you would use the EditMessage command:

        EditMessage %m

Adding the message body

The next step is to copy the body from the file to the message. We use the AssignBody command to do this:

     { Assign the body from the template file.
        AssignBody %m $replytext

Sending the message

The next step in the script is to actually send the message. We could send it via the directly via the SMTP server via the SendMessage command but we will use the technique of saving the message to the Out mailbox instead. This requires that Poco be setup to "Send queued messages when checking mail".

     { Save the message to the out box. Note: The "Send queued messages when checking mail"
     { option must be selected in the program options in order for the message to be sent.
        AppendToFile True
        SaveMessage %m "out.mbx"

Keeping track of the messages

We want a mechanism to keep track of the messages we have sent automated replies to. While we could write a file containing the sender, date and subject using the techniques described in the Enhanced error handling section we will simply add a mark to the message. We will use a mark of 8 which we can customize in terms of description using the "Options" form. The command that will perform this task is the MarkMessage command.

        MarkMessage %message 8

Note: We use the %message variable, not the %m variable. This marks the incoming message rather than the message we just created.

Full script

At this point the script should look something like this:
{  Script: VacationReply
{  Created: June 13, 2001
{  Author: Michael Motek
{  Purpose: Part of the PocoScript tutorial. This script will send a message informing people you are on vacation.
{  Mode: This script is designed to run against incoming messages.
{  Modification log

Set $OnErrorGoTo "ErrorHandler"
External $userfile1 "Reply text" "VacationReply.txt"

{  Read the reply text
Set $replyfile $mailpath
AddStrings $replyfile "VacationReply.txt"
OpenBody $replytext $replyfile

{  Get the sender's email address
ReadHeader $from "From:" %message
ExtractEMail $from
MessageBox $from

{  Check to see if the sender's email address is present in one of our address books.
IsAddressPresent &sw $from "*"
If &sw Then Continue
   Exit
:Continue

{  Create the reply and add the necessary headers.
   CreateMessage %m
   AddTo %m $from
   AddHeader %m "Subject:" "Vacation reply"
   ReadEmail $from
   AddHeader %m "From:" $from

{  Assign the body from the template file.
   AssignBody %m $replytext

{  Save the message to the out box. Note: The "Send queued messages when checking mail"
{  option must be selected in the program options in order for the message to be sent.
   AppendToFile True
   SaveMessage %m "out.mbx"
   MarkMessage %message 8

Exit

:ErrorHandler
  Exit

All that remains is testing the script to ensure it is functioning correctly. We have tested various steps the script uses so it is simply a matter of sending ourselves a test message and running the script against that message. Once we have done that the script will be ready to install. Once you have received the test message run the script against it using the technique described to run a script against selected messages.

Once you have confirmed the script is working properly it is ready to install. When you are about to go on vacation you would enable the script by configuring it to run against incoming messages. Remember to check the reply text to ensure it is what you want to send. Also, make a note to disable the script when you return from vacation.

Tag Annotated Messages

We have used the message annotation feature to annotate messages in our mailboxes. We would like to be able to filter the mailbox index to include only those messages that are annotated, unfortunately Poco doesn't have an option to do this. We can overcome this by writing a script that will Tag all messages in the mailbox that have an annotation.

Starting the script

As this script will not run unattended we don't need to be as concerned with the error handling. We will start by simply adding some comments at the start of the script:

     {  TagAnnotatedMessages - Select (tag) all messages that have an annotation
     {  (or whose annotation contains a user specified phrase)

     {  Author: Michael Motek - June 19, 2001

     {  Usage: This script is designed to be run against selected messages.

     {  Purpose: This script will select (tag) all messages that have annotation attached
     {  to them or those with a specific phrase in the annotation.
     {  Once tagged the Poco "Show Only" bar can be used to display only those messages.

Extracting the annotation header

Examining the full headers for one of the annotated messages we note that the annotation is saved in the X-Poco-Annotation: header. We extract this header and check to see if it contains a value:

     ReadHeader $note "X-Poco-Annotation:" %message
     If $note = "" Then NoAnnotation
        Exit
     :NoAnnotation

Tagging annotated messages

To tag the annotated messages we insert a
TagMessage command between the "If" and "Exit" commands:

        TagMessage %message

Untagging messages without annotations

We also want to remove the tagging from any message that doesn't contain an annotation. This is accomplished by adding an UntagMessage command immediately following the ":NoAnnotation" label:

        UntagMessage %message

Full version of the script

When complete, the script should look something like this:
{  TagAnnotatedMessages - Select (tag) all messages that have an annotation
{  (or whose annotation contains a user specified phrase)

{  Author: Michael Motek  - June 19, 2001

{  Usage: This script is designed to be run against selected messages.

{  Purpose: This script will select (tag) all messages that have annotation attached
{  to them or those with a specific phrase in the annotation.
{  Once tagged the Poco "Show Only" bar can be used to display only those messages.

ReadHeader $note "X-Poco-Annotation:" %message
If $note = "" Then NoAnnotation
   TagMessage %message
   Exit
:NoAnnotation
   UntagMessage %message

Extending the script

This script can easily be extended to test for phrases within the annotation. Try doing this yourself and then look at the "TagAnnotatedMessage" script posted at PocoMail website for a solution to this problem by the author of this tutorial. This is not the only possible solution to this problem.

Enhancing Error Handling

Proper error handling is important when scripts are to be run unattended or when they are written for other people to use. In these situations it is very important to record the details of the error in a file for future reference. This section of the tutorial will demonstrate a techniques that you can use to accomplish this.

The first decision that must be made is the location and name of the error log. We will put the error long into the user's temporary directory and name it "pocoscripterrorlog.txt". We want to produce a cumulative log of the errors rather than only the last one so we will also test to see if the file exists, if it does we will append new entries to it, otherwise a new file will be created.

The script name, error number, line number on which the error occurred, date and time the error occurred should be recorded.

The commands that will accomplish this are:

     {  Log any errors to file "pocoscripterrorlog.txt" in the user's temporary file directory.
     {  Construct the information to log
        GetDate $date
        GetTime $time
        AddStrings $ErrMsg "Error " #ErrorResult " occurred at " $time " on " $date " on line " #ErrorLine " in VacationReply"

     :LogError
     {  Construct the name and path for the error log file.
        Set $errfile $temppath
        AddStrings $file "pocoscripterrorlog.txt"

     {  Test to see if the error log file exists
        FileExists &sw $file
        AppendToFile &sw

     {  Save the message to the log
        SaveBody $ErrMsg $errfile

Notes:

< Previous