Pushing The Envelope With Perl Using Perl With Microsoft Exchange by wulinqing


									Pushing The Envelope With Perl: Using Perl With Microsoft Exchange
Rick Tatem
Messaging and Directory Resources Group
Cary, NC

This paper describes the use of Perl fo r managing and extending the Microsoft Exchange messaging
system. Perl‟s versatility has made several critical (and expensive!) tasks possible. Fro m synchronizing
the Exchange Directory Service with our employee directory to reporting on the volume of mail traffic
between servers and sites, Perl has proven its elf up to the task. Perl is used in several incarnations: plain
scripts, PerlScript in ASP pages, “executable” (IndigoSTAR‟s perl2exe), and Win 32 COM objects
(ActiveState‟s PerlCtrl). In an environ ment where solutions are usually needed yesterday, Perl h as always

Brute Force
Most of the Perl solutions I have implemented over the years have been of a nocturnal nature. They run
very late at night and try to attract as little attention as possible. Most of them began their existence as
quick, n imble, and focused on immed iate needs. Over t ime, due to never-ending requests for feature
enhancements and handling of exceptional input, they have become more like lu mbering beasts of burden.
While certainly not pretty, they do their nightly tasks witho ut a whimper. Interaction is not necessary (or
even wanted).

As is the case in most technology companies, it is a constant struggle to keep pace with all of the advances
being made on both the software and hardware fronts. Time to soak in knowledge is a lu xu ry. Hence, most
of the innards often come fro m code pilfered fro m any book, web site, Q article, or colleague that has
anything that even remotely resemb les something useful. It is open source… right?

Humble Beginnings
SAS Institute decided in 1996 that the standard corporate desktop would be the “Wintel” platform (low cost
Intel processor PCs running Microsoft Windows NT). The back-end wou ld continue to be the usual mix of
UNIX (HP and Sun, mostly) and NT. As part of that decision, Microsoft Exch ange was also deemed the
new corporate messaging platform. At the time, the support staff for the PC p latform was not capable of
immed iately handling the additional workload. Because the UNIX support group had been handling the
email system (sendmail on HPUX) it was thought that perhaps they would be interested in getting involved.
I was approached since I had been stuck in the world of backups and restores for 2 years. ANYTHING else
was an improvement. So I transitioned fro m the UNIX world to NT… and I brought Perl along with me.

Because of my inexperience with Exchange and Windows in general, most of the early solutions were
merely text -based processing. These “quickie” solutions resulted in .bat files for executing manually.
Because of Exchange‟s close ties with the underlying operating system, often the problems to be solved
were closely related to the NT accounts. Perl is adept at supplying arguments for common NT
administrative co mmands, such as “net user” for creating accounts. Although primit ive, (in my own
opinion) these “quickie” tools provided a wonderful opportunity to evangelize Perl to the main NT/PC
support staff. Without exaggeration, there were several instances of outright astonishment as to the ease
with which Perl could provide these ad hoc tools. (Using „v i‟ instead of „notepad‟ also added to the fun.)

The first purely Exchange-related process to be automated was transferring employee data (office, phone,
title, etc.) fro m our corporate Emp loyee Directory (a SAS Dataset, naturally) to the Microsoft Exchange
Directory Serv ice. I ad mit, I‟m not really a SAS programmer, so the bulk of the process is taking the
output of few simp le SAS Data Steps (text files) and “massaging” them enough to match the fields
necessary for importing into the directory.
Growi ng Up Quickly
As the demands and expectations of admin istering our Microsoft Exchange site grew, I searched (mostly in
vain) for examp les using Perl for solutions to the tasks before me. There were some very useful sources
(Dave Roth‟s site, http://www.roth.net/perl/, in part icular) but they mainly dealt with the OS and general
account maintenance. There wasn‟t a lot of Exchange-specific code in Perl. But there is a wealth of
samples using Visual Basic .

Visual Basic (and more o ften VBScript), wh ile easy to learn and rife with samp le code, couldn‟t sway me
completely. There are still plenty of routines that are mo re co mfortable to do in Perl. Arrays and hashes, in
particular, are much simp ler to manipulate in Perl. As it turns out, “translating” fro m most VB/ VBScript
samples to Perl is actually achievable without too much effort.

Listing 1 shows a VBScript that asks for an email address in SMTP format and returns the corresponding
Display Name and Distinguished Name of the Directory Ob ject. Listing 2 shows the same thing, with the
exception that the email address is a command-line argument.

Listing 1                                                           Listing 2
                                                                    use strict;  # Always!
                                                                    use Win32::OLE;

Set conn = CreateObject("ADODB.Connection")                         my $conn = Win32::OLE->new("ADODB.Connection");
conn.Provider = "ADSDSOObject"                                      $conn->{'Provider'} = "ADsDSOObject";
conn.Open "ADsProvider;CN=uid,DC=DOMAIN;passwd"                     $conn->Open("ADs Provider;CN=uid,DC=DOMAIN;passwd");

myEmail = inputbox("Enter First.Last@sas.com address:")             my $Email = $ARGV[0]; # lazy

Set rs = conn.Execute("<LDAP://MERC01/O=SAS _
Institute/OU=CANDY>;(mail=" & myEmail & _ ");adspath,cn;subtree")   my $rs = $conn->Execute("<LDAP://MERC01/O=SAS “ .
While Not rs.EOF
    msgbox rs.Fields(0) & vbcrlf & _
    rs.Fields(1)                                                    while ( !$rs->EOF ) {
    rs.MoveNext                                                       print $rs->Fields('adspath')->value . "\n" .
Wend                                                                  $rs->Fields('cn') ->value . "\n";
rs.Close                                                              $rs->MoveNext;
conn.Close                                                          }

The object/property/method approach of VB fits neatly into Perl. While VB uses the “dot” notation
(object.method or object.property), most examp les I‟ve seen in Perl distinguish between properties and
methods (object->Method() vs. object->{„Property‟}). As is the Perl way, there‟s more than one way to do
it. Th is is the way I‟ve chosen, as I consider it easier to fo llo w with “method as function”. The
Win32::OLE modules do the lion‟s share of the work.

Deli vering the Goods
A handful of projects have really showcased the power and adaptability of Perl in working with a co mplex
application such as Microsoft Exchange. Exchange is more than simply email. Exchange encompasses
many facets of a Windows co mputing environment: networking, databases, directory services (LDAP),
account maintenance, collaboration, etc. Perl has been used, in one form or another, with all o f these. A
few pro jects in particular demonstrate Perl‟s ability to quickly and effectively deliver a solution when and
where it‟s needed. Table 1 contains some Exchange-specific terms and a brief description of each. The
solutions presented will include these terms often.
Table 1
Exchange-related Term        Descripti on
Information Store            The underlying database containing all mail messages,
                             attachments, and other various items. There are t wo types
                             of Informat ion Store: Public and Private. The Public Store
                             is the content of the Public Fo lders “homed” on the server
                             holding the Store. The Private Store is the content of all
                             user mailbo xes “homed” on the server holding the Store.

Site                         An admin istrative grouping of one or more Exchange
                             Servers connected to the same local area network.

Organization                 The root of the directory. All Exchange sites belong to the
Public Folder                A specialized mailbo x for sharing among many users. Can
                             receive e-mail. Contents kept separate from user
                             mailbo xes.
MAPI                         Messaging Application Programming Interface. An API
                             providing access to Messaging systems such as Exchange.
                             Difficult to work with, at best.
GA L                         Global Address List. All mail recipients in an Exchange
ADSI                         Active Directory Services Interface. An API for accessing
                             Windows 2000 Active Directory. A lso provides access to
                             Exchange 5.5 directory and Windows NT 4 accounts.
                             Easily accessible via the Win32::OLE modules.
LDAP                         Lightweight Directory Access Protocol. Internet standard
                             for directory services. Exchange 5.5 and Windows 2000
                             Active Directory are LDAP v.3 co mpliant. Great way to get
                             the UNIX folks to access the Exchange directory.
Directory Name               The unique identifier in the Exchange Directory of an
                             object. Appears in the same context as the Relative
                             Distinguished Name in an LDAP d irectory. Ho wever, the
                             Exchange Directory forces uniqueness throughout the entire
                             Organization, not just within the same directory node. Like
                             having unique filenames for all files on a disk.
Distinguished Name/AdsPath   The fully qualified name of an object, fro m the root of the
                             directory. Like a fully qualified pathname for a file. If you
                             know (o r can construct) this, you can access the object
                             directly, instead of having to perform a search for it.
Message Tracking
I was pleasantly surprised to find Perl mentioned pro minently in the July 2000 issue of Exchange
Admin istratori . The art icle discusses using Perl to parse the message tracking logs generated by Microsoft
Exchange. The logs are plain text containing tab-separated fields. Exchange provides the ability to track
messages within the Exchange Administrator GUI, so there had not been much push for anything more.
The Perl code contained in the article was, to put it bluntly, quite simp le. It merely split() each line into an
array then, based on the value of one field (specifica lly the „Event‟ field ), incremented two counters. This
simp le parsing yielded (according to the article) the number of messages delivered locally, the number sent
to another server, and their ratio.

These numbers are can be quite useful to an Exchange ad ministrator. Exchange utilizes “single instance
storage”, mean ing that regardless of how many recipients on an Exchange server a message is to be
delivered, only one instance of the message (body and all attach ments) exists in the Information Store
(database). By being selective when putting mailbo xes on servers, the Exchange Admin istrator can
minimize both the traffic of messages between servers and sites, and the cumulative size of the mail

It became apparent after trying out the code that it needed some improvement. There were t wo main points
where the examp le provided did not succeed. First, the „Local Delivery‟ event (Event ID 1000) indicates
both the submission and delivery in a single instance. In the case of this particular event, a „Message
Submission‟ event (Event ID 4) is not al ways noted. If a message is addressed only to local recipients, no
„Message Submission‟ event is triggered. So subtracting the number of „Local Delivery ‟ events from the
number of „Message Submission‟ events is incorrect. Secondly, a submitted message may still end up
delivered locally, though not in the context of the „Local Delivery‟ event. By noting the message -id of
submitted messages (Event ID 4) and delivered messages (Event ID 9), a mo re accurate ass essment of
message delivery can be made. Listing 3 shows the improved (though still not perfect) report.

Automated Rules-based Distribution Lists
As the number of emp loyees using Exchange grew, there were several processes that begged for updates.
Most of SAS‟ o fficial corporate mailing lists were hosted by the ListServ system running on VM. All
mailing lists based upon employee data (depart ments, divisions, buildings, etc.) were maintained
automatically. Because of the visual nature of the Global Address List, employees began requesting that
these lists be made available in the GA L.

Because many of these lists were quite large it was not practical to continue using simple directory
import/export files. Also, because we were try ing to mimic the behav ior of the ListServ lists, we needed to
have archives available. Exchange Public Fo lders were the obvious choice, but manipulat ing them
automatically can be tricky.

Microsoft‟s examp le code for creating Distribution Lists based on search criteria were fo und to be lacking.
While useful for in itially creating the list, they provided no logic for updating existing lists. Also, some of
our existing lists used data not yet available in the Exchange directory. A query -based solution was not
appropriate at the time.

I came up with a process to provide exactly the same functionality as was currently on the VM ListServ
system, including archives. Lists and archives are designated by an entry in a text file called
DLRULES.TXT”. Th is file contains three comma -separated fields: list alias, list rule, and list display
name. The list rule is written in Perl syntax. For examp le:

MNR,(($unit eq 'MNR') && ($location eq 'Cary')),*Dept: MNR Multivariate
& Numerical R&D)
Listing 3
#Message Tracking Log parser
use strict;
my(@tfiles,$t file,@servers,$server);
my ($eventid,$submitted,$locally,$remotely,$count,$repdate);
my ($messageid,%sent,$returns);
@servers = qw(SERVER01 SERVER02); #replace with your own server names
foreach $server (@servers) {
  unless (opendir(DIR,"//$server/tracking.log")) { # the tracking.log directory is shared by default
  print "Cannot open directory on $server: $!\n";
   @tfiles = g rep { /\.log$/ } readdir(DIR);
   foreach $count (0 .. 6) {
      open(TLOG, "<//$server/tracking.log/@tfiles[$count]") ||
         die "Cannot open tracking log @tfiles[$count] on $server: $!\n";
      # Reset counters… bound to be a more clever way...
      $submitted = 0;
      $locally = 0;
      $remotely = 0;
      $returns = 0;
      wh ile(<TLOG>) {
         cho mp;
         ($messageid,$eventid) = (split(/\t/))[0,1];
         # Event ID 4 - Message Submitted by client
         if ($eventid == 4) {
            $sent{$messageid} = 0; # will remain 0 if no local delivery
         # Event ID 1000 - Local Delivery (no transfer)
         } elsif ($eventid == 1000) {              # send/recieve at same time
         # Event ID 9 - Message Delivery
         } elsif ($eventid == 9) {
            if (defined($sent{$messageid})) { # sent fro m this server
      close (TLOG);
      foreach (keys(%sent)) {
         if ($sent{$_} == 0) {
         } else {
      substr(@tfiles[$count],6,0) = "/";
      $repdate = substr(@tfiles[$count],4,5);
      print "\nDelivery Nu mbers for $server ($repdate)\n";
      print "-------------------------------------------\n\n";
      print " $submitted messages submitted by users \n\n";
      print " $remotely sent off server\n\n";
      print " $returns messages delivered to server\n\n";
      print " $locally delivered locally (no transfer)\n\n";
Allowances are made to include exceptions to the membership rules in the “DLEXCEPT.TXT” file. Of the
seven steps listed below, five of them are purely for dealing with the public folder archives. A single Perl
program (autodl.exe) handles the actual creation and update of the distribution lists.

Here are the steps involved:

    1.   Expo rt recipient info rmation fro m the Global Address List and our corporate emp loye e data in
         order to map between the Exchange Directory Name (the unique identifier for an object) and an
         Emp loyee Nu mber (the unique identifier in our Corporate data). These files will be used to
         determine membership.
    2.   Create an arch ive public folder, if necessary.
    3.   Expo rt info rmation fo r public folders. (directory name in part icular)
    4.   Create two files for impo rting temporary changes to the archive folders (show/hide fro m address
    5.   Change the “hide fro m address book” property of the archive folders temporarily to “False”.
    6.   Update/create the distribution lists. (autodl.exe)
    7.   Change the “hide fro m address book” property of the archive folders back to “True”.

The autodl.exe executable is the heart of the automated distribution list create/update process. Beca use of
the nature of the server running the updates (it is used for all scheduled administrative jobs), there was
concern about changing the configuration in any way… including the installation of Perl. To avoid that
issue, we have a licensed copy of perl2exe fro m IndigoSTAR software
(http://www.indigostar.com/perl2exe.ht m). This allows the creation of co mpletely stand -alone executable,
which is much easier to convince the other NT ad ministrators to approve.

The logic is straightforward:
    1. Emp loyee data is read into a hash
    2. Each ru le (fro m the DLRULES.TXT file) is eval‟ed for each employee.
    3. If the eval is TRUE, then the employee nu mber is pushed into an array of employees who should
         be members of that distribution list.
    4. If the corresponding Distribution List exists, then the current membership (read direct ly fro m the
         list properties and pushed into an array) and the eval‟ed membership array are co mpared to
         determine who needs to be added or deleted.
    5. Otherwise the list is created and populated.

Listing 4 shows example code. It shows the create_DL and dl_enum subroutines. The dl_enum
subroutine accesses an existing distribution list and enumerates the membership. It then returns a reference
to an array of the current members.

Having Public Fo lders availab le for archiv ing messages to the list is tricky to imp lement. By default,
Public Folders are not visible in the Address Book. Th is also means they aren‟t visible by normally used
ADSI routines. In order to get things working quickly, I decided to foreg o much of the programmat ic
access to Public Folders. Instead, I utilize a special import/export routine to expose the Public Fo lders to
the Address Book just while the list updates are occurring. I use the dsimport.exe and dsexport.exe
programs fro m M icrosoft‟s Platform SDK. By utilizing specific syntax in naming the folders, it‟s easy to
create the necessary syntax for including them in the lists.

As hinted to earlier, this process is one of the lumbering beasts toiling away in the wee hours of the
morn ing. It‟s not the most efficient Perl in the world, although I have made some attempts at keeping
things in check. Currently there are more than 350 lists being updated nightly, some with up to four
thousand members.
The next step is to get rid of our dependency on the ListServ system entirely (as we have it implemented).
Exchange and the Outlook client provide the basic “owner-controlled” list functionality. A list is owned
Listing 4
sub create_DL {
my $dldn = shift(@_ );
my $DL = "cn=" . $dldn;
my $DisplayName = $DISPLA Y{$dldn};
## Edit strings below to match requirements
my $SMTP = $dldn . "\@corp.co m";
my $DLDN = $DL . ",cn=Recipients,ou=Site,o=Organizat ion";
my $DLX400 = "c=US;a= ;p=Organization;o=Site;s=" . $dldn . ";";
my $CPath = "LDAP://$EXSERVER/cn=Container,ou=Site,o=Organization";
my $my IADS = W in32::OLE->GetObject(" LDAP:");
# ***IMPORTA NT*** Put a valid userid/password combo in the line below!!!
my $Recip ients = $my IADS->OpenDSObject($CPath,"dc=Do main,cn=userid",'password',0);
my $newDL = $Recip ients ->Create("groupOfNames",$DL);
$newDL->Put("uid",$dldn); # Alias
$newDL->Put("name",$dldn); # Simp le Display Name
$newDL->Put(" mail",$SMTP);
$newDL->Put("te xtEncodedORaddress",$DLX400);
$newDL->Put("info","This list is created automatically fro m informat ion in the ALLEMPS dataset.");
$newDL->SetInfo; # Co mmit changes
return "LDAP://$EXSERVER/ $DLDN";
sub dl_enum
my $adspath = shift;
# Having the AdsPath makes access so easy…
my $DL = Win 32::OLE->Get Object($adspath);
my $mems = $DL->Members;
my $Enu m = Win 32::OLE::Enu m->new($mems);
my @M EMS = $Enu m->All;
my (@members,$member,$dname);
foreach $member (@M EMS) {
return \@members;

and maintained by one or more persons. The automated distribution list job takes care of the lists that have
fixed membership (in the sense the no one decides who is/isn‟t a member). What was missing was the
concept of the “open” list: distribution lists that anyone could join/leave as they wished.

At first we looked at most of the options already available, mostly fro m third parties. The one
overwhelmingly lacking feature of all products we examined was their lack of integration with the
Exchange Directory Serv ice. The product from Reddfish (http://www.reddfish.co.nz/reddfish/listserver/)
requires a separate recipients container and new directory objects for ALL list members … even those
already in the directory. We felt this was unacceptable. Managing the primary recipients container was
enough work, we didn‟t want to duplicate our efforts. The product fro m NTP Soft ware
(http://www.ntpsoftware.co m/products/lm/) doesn‟t even use the directory. It stores all subscribers in a
Personal Address Book. (There‟s an Exchange Administrators‟ mantra. Say it with me: “PAB=BAD”)
Even an examp le solution fro m Microsoft was weak. Well, that wasn‟t good enough, so I did it myself.
The solution I came up with is NOT a co mplete solution (although I‟m working on it ). However, it does
solve the immediate need: provide a mechanism for SAS emp loyees to join/leave mailing lists hosted on
SAS‟ Exchange servers. The major missing piece is the ability to allow external recipients as members
(without compro mising the directory). The surprising thing is that this solution accomplished with four
pieces: an Exchange mailbo x, a Public Folder, an Exchange Server Event Script (written in VBScript), and
a COM Object/ActiveX Control written in Perl (and co mpiled into DLL form by PerlCt rl, part of the Perl
Develop ment Kit fro m ActiveState Tool Corporation). No new service needs to be installed. No overtly
suspicious permissions are required.

DLManager consists of a mailbo x, a public folder with an event script, and the ActiveX control. The
Exchange 5.5 Event Serv ice provides asynchronous events. This means that by the time the event actually
registers, the underlying message may not be in the same state. For example, the ONDELETE event can
only be used as an indicator, since by the time you see the event, the message has, in fact, been deleted.
While not appropriate for all possible scenarios, the requirements for DLMA NA GER are not time crit ical.
The Event Script actually does very little. When a message arrives, it extracts the sender and the subject
and just hands them over to the DLL. The sender is resolved against the Global Address List if possible,
and the subject is parsed to determine if a valid co mmand has been sent. Based on the resulting command
and the sender, the Event Script either sends an error message, or continues by calling the appropriate
methods of the control (subscribe/unsubscribe/etc.), then sending the results back to the sender. All access
is based on the directory and its security. If the sender isn‟t in the directory, they don‟t count!

There was one particularly troublesome problem to overcome: not all employees are Exchange (or more
specifically, Outlook) users. Many of these employees have Custom Recipients (i.e. aliases) instead of
mailbo xes. This presented a challenge since the „sender‟ of the message (as viewed by the Event Script)
wouldn‟t already be resolved against the directory. To further co mp licate matters, some of these folks had
been set up with a Mailbo x (so they could use the calendaring functions) and a Custom Recipient
(Exchange‟s way of provid ing forwarding). Depending on where such a person originated the message
determined whether they could be verified against the directory. We were able to make the stipulation that
such persons should send mail fro m their “primary mail account”. In a develop ment environment, it‟s not
unusual to have mailbo xes spread over a wide variety of hosts: UNIX/Windows/mainframe/etc. I devised a
three-step query to determine whether the sender resolves to a GA L entry.

Listing 5 is the Event Script. Most of the code is of the housekeeping variety. NOTE: I have edited out
some of the debugging/logging to save space. Listing 6 is the Subscribe method (the Unsubscribe is quite
similar). Note that this method demonstrates the special sender query as described above.

Our Sales & Market ing division has used DLManager heavily. One of the first lists offered by DLManager
was a list to subscribe to our monthly corporate “webzine”… currently mo re than 1100 subscribers.

There are several benefits to DLManager :
    1. Relies on the Directory (secure)
    2. A DLManager list is a normal list (owner can still modify as usual)
    3. By using the subject line for co mmands, it is easily incorporated into web pages
         (mailto:d lmanager@corp.co m?subject=subscribe%20listname)

Other Perl goodies
I‟ve used Perl in several other capacities, as well. I‟ve used PerlScript in web page for crea ting general
distribution lists (including a checkbo x for making it a „ DLManager‟ list!). Tools have been provided to
our Help Desk support staff for tasks such as “cleaning up” the directory: removing objects, including
„hidden‟ ones, fro m distribution lists and removing Access Control List entries fro m Public Folder
Permissions. So far, there hasn‟t been anything that couldn‟t be done using Perl.
Listing 5 – DLManager Event Script
Option Exp licit
Dim gc_Rep lySubject
gc_ReplySubject = " Your DLManager request..."
' Event Handler Description: This event is fired when a new message is added to the folder
Public Sub Folder_ OnMessageCreated
Dim oSession
Dim o CurrentMsg
Dim o ReplyMsg
Dim oFo lderOutbo x
Dim o Recip ient
Dim str_Log
Dim oSender
On Error Resume Next
Set oSession = EventDetails.Session
Set oCurrentMsg = oSession.GetMessage(EventDetails.MessageID,NULL)
oCurrentMsg.Unread = False
str_Log = "Message received, Subject=" & o CurrentMsg.Subject & ";Sender=" &
Set oFolderOutbox = oSession.Outbox
Set oReplyMsg = oCu rrentMsg.Reply
Set oSender = o CurrentMsg.Sender
oReplyMsg.Subject = gc_ReplySubject
Dim str_return
Dim ctrlDLManager
Set ctrlDLManager = CreateObject("PRK.DLManager")
ctrlDLManager.Subject = oCurrentMsg.Subject
ctrlDLManager.UserID = oSender.Address
str_return = ctrlDLManager.ParseSubject
Select Case str_return
   Case "HELP"
     str_return = ctrlDLManager.Help
   Case "INFO"
     str_return = ctrlDLManager.In fo
   Case "REVIEW"
     str_return = ctrlDLManager.Review(ctrlDLManager.DList)
     str_return = ctrlDLManager.Subscribe(ctrlDLManager.UserID,ctrlDLManager.DList)
     str_return = ctrlDLManager.Unsubscribe(ctrlDLManager.UserID,ctrlDLManager.DList )
End Select
oReplyMsg.Text = str_return
str_Log = str_Log & ", Rep ly sent!"
Set oRecip ient = Nothing
Set oReplyMsg = Nothing
Set oFolderOutbox = Nothing
Set ctrlDLManager = Nothing
Set oCurrentMsg = Nothing
Set oSession = Nothing
Script.Response = str_Log
End Sub
Listing 6 – DLManager Subscribe subroutine
my $person = shift;
my $list = shift;
my $dlpath = "LDAP://server/cn=" . $list . ",cn=Container,ou=Site,o=Organization";
my $confirmat ion;

# lookup the dl...
my $DL = Win 32::OLE->Get Object($dlpath);
return(&main::Error('REVIEW',$list)) if (! $DL);
# Used this because it exists, isn‟t readily exposed, and is already indexed for easy queries!
my $status = $DL->Get('physicalDeliveryOfficeName');
if ($status ne 'Open') {
    my $o wner = $DL->Get('o wner');
    my $Owner = Win 32::OLE->GetOb ject("LDAP://MERC51/ $owner");
    $DLManager::DListOwner = $Owner->Get('cn');
# lookup the person...
my ($upath,$uname) = &main::ADO($person,"OPEN");
if ($upath =~ m/NULL/) {
    ($upath,$uname) = &main::ADO($person,"HIDDEN");
    if ($upath =~ m/ NULL/ ) {
       ($upath,$uname) = &main::ADO($person,"TARGET");
       if ($upath =~ m/ NULL/) {
           $confirmation = &main ::Error($upath,$person);
          return($confirmat ion);
if (! &main::Is_Member($upath,$DL)) {
    $confirmat ion = &main ::Confirm('SUBSCRIBE',$uname,$list);
} else {
    $confirmat ion = &main ::Error('SUBSCRIBE',$uname,$list);
return($confirmat ion);

Looking Ahead: Windows 2000/Acti ve Directory/ Exchange 2000
At the time of this writ ing, many exciting advancements are occurring in conjunction with SAS‟ adoption
and deployment of Windows 2000 and Exchange 2000. The first challenge is Active Directory. As an
Exchange Admin istrator, I describe Active Directory as the Exchange 5.5 d irectory “taking over” and
moving into the OS. There are (in my op inion) more similarities between Active Directory and Exchange
5.5 directory than Active Directory and the NT4 SAM database. Whereas, in Exchange 5.5 the NT Account
was a property of the mailbo x, now in A D the mailbo x is a property of the NT Account. The consolidation
of NT security groups and Exchange Distribution Lists provides tremendous opportunity. The exact same
logic used for distribution lists can now be applied to security groups, freeing up administrator resources.

There are significant changes on the Informat ion Store, as well. Mo st significant is the conversion of the
database to what Microsoft calls the WebStore. Before, MAPI was the only way to access data in the store.
Now the WebStore exposes the data in a much more accessible manner. The IFS (Installable File System)
allo ws you to access your mailbo x as if it were a file system (you can „cd‟ into your mailbo x!). Fro m a
programmers perspective, even more excit ing is the fact that the Information Store is accessible via the
WebDAV p rotocol. Every item in Exchange is URL addressable!

These changes are excit ing, and the challenges will be many. Ad mittedly, many of the processes and
programs mentioned here are currently in a state of flu x. A ll of the code I‟ve present is being updated to
work directly with Active Directory. In addit ion, there will be new problems to solve. Fro m my
perspective, the question isn‟t whether it can be done with Perl… it‟s a question of what you want to do
first! If you‟d like to obtain the Perl code presented (and alluded to) here, send an e -mail to me
(Rick.Tatem@sas.com) and I‟ll be happy to provide it to you.

I‟d like to exp ress my gratitude for the hard work of Perl porters. I‟ve used Perl on a wide variety of
platforms (including a much-tin kered Atari 1040ST a few years back) and have always been amazed at the
consistency of the ports. I‟d also like to thank the fo lks at ActiveState. The Windows NT world generally
has a different mindset than the UNIX wo rld. The products and services provided by ActiveState are
helping to broaden the impact of Perl where it‟s needed most. Specifically, I‟d like to thank:
Jan Dubois and Gurusamy Sarathy for their work on the Win32::OLE modules
Dave Roth for his work on the Win32:: AdminMisc (and many other useful) modules
Graham Barr and Mark Wilco x for their work on the Net::LDAP module

    Exchange Administrator, Vo l. 3, No. 4, Duke Co mmun ications International, Inc.

To top