home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  

19.3 Using Automation Objects

In this section, we're going to explore automation objects by building a simple progam that sends a message using Microsoft's Active Messaging Library . If you don't have Active Messaging (if you have MAPI, you probably have it) on your system, you can still follow the concepts, which are generally applicable to using automation. Remember, though, that the specific methods, properties, and objects that a server exposes are specific to that server. To learn more about Active Messaging, try the Microsoft MSDN[ 2 ] web site at www.microsoft.com/msdn/sdk/ and look for the for Active Messaging Library documentation. The Active Message Library is a complex API that provides complete services for messaging, message stores, providers, transports, and more; but we're just going to touch on the basics of sending a message here.

[2] Microsort Developer Network - you might also have it on CD, if you're a Win32 programmer and subscribe to MSDN.

The first thing we need to do is to create a Active Messaging session. This happens to be the top-level automation object for our purposes, so we'll start here with CreateObject :

use OLE;
$ActiveSession = CreateObject OLE "MAPI.Session" || 
        die "CreateObject: $!";

The ProgID for the Active Messaging Session object is MAPI.Session, so that's the argument that we give to CreateObject . After we have an Active Messaging session, we need to logon. Active Messaging provides a couple of options for doing this. If you don't supply a valid username/password combination, you'll get a logon dialog that lets you supply a user and password:

$LogonName = "Erik Olson";
$LogonPasswd = undef; # use stored one, or prompt
die "Logon: $!" if $ActiveSession->Logon($LogonName, 
        $LogonPasswd); # Logon returns 0 on success

Here, we're calling the Logon method of the Active Messaging Session object. Because Logon returns 0 on success, we are only dying if we get a return value (indicating an error code). If we successfully logon to the Active Messsaging session, we're ready to create a Message object. A message object is another automation object that (appropriately enough) encapsulates a message. For example:

$Message = $ActiveSession->Outbox->Messages->Add();

Now, things are starting to get interesting. We're using the $ActiveSession object to call a method named Outbox that returns an automation object (the Outbox object). We're then calling a method of the Outbox object called Messages that returns another automation object (the Message object). We're then calling a method of the Message object named Add that returns yet another automation object, which we're assiging to our $Message variable. Perl lets you merrily create as many nested automation objects as you need.

Now that we have a Message object, we can start doing things with the message. First, we need to add a recipient. This involves another nested automation-object call:

$Recipient = $Message->Recipients->Add();

Here we're calling the Recipients method of the message object that returns a recipients object. We then call the Add method of the recipients object to get a Recipient object that we can use. Let's set some properties of the recipient object:

$Recipient->{Name} = "Erik Olson"; # to address
$Recipient->{Type} = 1; # ugly constant, means this is a To address

We've set the Name property of the Recipient object by setting the property using the object's hash. As for that assignment to the Type property, we've set it to 1, which is the Active Messaging value for a TO recipient (as opposed to a CC or BCC recipient). Table 19.1 displays the values for the recipient types.

Table 19.1: Recipient Type Values

Recipient Type


MAPI_ORIG (recipient is message originator)


MAPI_TO (recipient is a primary recipient)


MAPI_CC (recipient is a copy recipient)


MAPI_BCC (recipient is a blind copy recipient)


After setting the recipient information, we need to resolve it to a name in the Active Messaging address book. We do this by calling the Resolve member of the Recipient object:


Now that we know where our message is going, let's add some data to it. We need at least a subject and a body, both of which are properties of the Message object.

$Message->{Subject} = "A Message From Perl";
$Message->{text} = "Perl does automation!";

All that remains is to save the message, send it, and terminate our session:

$Message->Send(1, 0, 0);

We call the Update method of the message object to save it, then the Send method to actually send the message. The parameters to Send are shown in Table 19.2 .

Table 19.2: Send Parameters




Save a copy of the message in the Sent-Items folder (one or zero)


Display a send-message dialog where the user can change the message contents or recipients (1 or 0)


Parent-window handle for the dialog, if showDialog is true; in Perl, you'll normally be passing this as 0

Let's put everything together:

use OLE;
$LogonName = "Erik Olson";         # send message to me
$LogonPasswd = undef;              # use stored passwd
$ActiveSession = CreateObject OLE "MAPI.Session" || 
        die "CreateObject: $!";    # create session
die "Logon: $!" if $ActiveSession->Logon($LogonName, 
        $LogonPasswd);             # logon (returns 0 on success)
$Message = $ActiveSession->Outbox->Messages->Add();
$Recipient = $Message->Recipients->Add();
$Recipient->{Name} = "Erik Olson"; # to address
                            # ugly constant, means this is a To address
$Recipient->{Type} = 1; 
$Recipient->Resolve();             # resolve name - hope it's there
$Message->{Subject} = "A Message From Perl";
$Message->{text} = "Perl does automation!";
$Message->Update();                # save it
$Message->Send(1, 0, 0);           # send it - don't show UI
$ActiveSession->Logoff();          # end session

19.3.1 Data-Access Objects

If you are a Perl programmer looking for a database solution, you owe it to yourself to check out Microsoft's ActiveX Data Objects (ADO), which provide an automation interface to database access. ADO is a powerful data-access layer that you can use from Perl, PerlIS, or PerlScript. This layer is particularly interesting in conjunction with Active Server pages and PerlScript. See www.microsoft.com/ADO/ for more information on ADO. The ActiveState site ( www.activestate.com ) has several samples using PerlScript and ADO for database access.

Just to tempt you, here's a quick example that uses the sample database shipped with the OLEDB SDK (OLE Database Software Development Kit), with which ADO is included. For more information on the OLEDB SDK, see www.microsoft.com/oledb . The sample database contains a table called Employees , which includes the fields LastName , FirstName , and EmployeeID . The following program just opens the data source (you have to have an ODBC driver installed for Microsoft Access database files) and lists all the rows in the Employees table. Regardless of which data source you choose to use ADO with, you'll find the procedure to be similiar.

use OLE;
$conn = CreateObject OLE "ADODB.Connection" || 
        die "CreateObject: $!";    # create ADO auto object
$conn->Open('OLE_DB_NWind_Jet');   # connect to data source
$sql = "SELECT * FROM Employees ORDER BY LastName, FirstName";
$rs = $conn->Execute($sql);        # grab all records in table
while(!$rs->EOF()) {
    $lastname = $rs->Fields('LastName')->Value;
    $firstname = $rs->Fields('FirstName')->Value;
    $empid = $rs->Fields('EmployeeId')->Value;
    write;                         # print them out

$rs->Close();                      # shut down the recordset
$conn->Close();                    # close the data source
# some formats for a quick printout
format STDOUT =
@<<<<<      @<<<<<<<<<<<<<<<<<<<   @<<<<<<<<<<<<<<<<<<<<<<<<
$empid,     $firstname,            $lastname
format STDOUT_TOP =
Page @<<
ID          First                  Last
=====       ====================   =========================

Our first task is to create the automation object using the now familiar CreateObject function. We then use the ADO Connection object to execute a SQL statement. The Execute function returns a Recordset object, which we then use to iterate through all the rows, printing out the data.

Here's another quick program that inserts an employee into the Employees table:

use OLE;
$firstname = "Homer";             # hardcode some values to insert
$lastname = "Simpson";
$empid = "3001";
$conn = CreateObject OLE "ADODB.Connection" || 
        die "CreateObject: $!";   # create the ADO object
$conn->Open('OLE_DB_NWind_Jet');  # connect to the data source
# build a simple SQL INSERT
$sql = "INSERT into Employees (LastName, FirstName, EmployeeID)";
$sql .= "VALUES ('$lastname', '$firstname', '$empid')";
$conn->Execute($sql);             # run it