Win32::Exchange - Exchange 5.5 and Exchange 2000 functions


Win32::Exchange - Exchange 5.5 and Exchange 2000 functions


  $provider = Win32::Exchange->new($info_store_server)) ||
      die " - error creating new object\n';

  #--- Exchange 5.5
  $mailbox = $provider->CreateMailbox($info_store_server,$mailbox_alias_name);
  if (!$mailbox) {
    die "Error creating mailbox\n";
  print "Create successful\n";

  #--- Exchange 2000
  $mailbox = $provider->CreateMailbox($info_store_server,
                                           "") ||
    print 'Mailbox create failed\n';
  $mailbox->Win32::Exchange::SetAttributes(\%Attributes) ||
        print 'Set Attributes failed\n';


The mailbox functions have moved to Win32::Exchange::Mailbox. This is a base class. By "use"ing Win32::Exchange, the other sub-modules like Mailbox, Const and SMTP::Security are auto included. This module deals with low-level functions that most all the other modules might want to use as well.

Win32::Exchange uses Win32::OLE exclusively (and technically is just a wrapper for the underlying OLE calls) so feel free to look at them, and make a suggestion or two.

All methods return 0 (or undef) on failure and 1 for success unless otherwise noted.


$provider = Win32::Exchange->new($server_name | $version);
The new() class method starts a new instance of an Exchange provider object. It returns a reference to this object or undef if the creation fails.

$provider = Win32::Exchange->new($server_name); #new performs a check on your exchange server for versioning
$provider = Win32::Exchange->new($version); #creates an object suitable for a $version server.. ("5.5" or "6.0")

This function should probably be deprecated, as it serves no current purpose. Maybe it will in the next release. :)

The ErrorCheck() method takes an input value something similar to "0x00000000" where the string is the error you are expecting. $error_num and $error_name are output variables if an error other than the value you expected has happenned. All values are checked against Win32::OLE->LastError for string comparisons.

if (Win32::Exchange::ErrorCheck("0x80073020",$error_num,$error_name)) {
print "Mailbox does not exist. Good... Let's create it.\n";
} else {
if ($error_num eq "0x00000000")) {
print "OOPS.. The mailbox already exists!!!\n";
} else {
print "Unexpected error getting mailbox! ($error_num,$error_name)\n";

[$dc_name] = Win32::Exchange::FindCloseDC($exch_server_name,[$dc_name]);
function takes the exchange server name, and finds a close DC to that server, very useful in remote sites because of replication and lag times due to differing connection on remote sites. This function uses WMI, requires Exchange 2000 Service Pack 2, and was contributed to the Win32::Exchange project by Andy Webb.

This function takes an optional second parameter for the output ($dc_name) of a close domain controller in proximity the Exchange Server specified in the first parameter. If the second parameter is omitted, the function returns the DC name as the return result.

if (Win32::Exchange::FindCloseDC("thisexchangeserver",$dc_name)) {
print "dc_name = $dc_name\n";

- or -

$dc_name = Win32::Exchange::FindCloseDC("thisexchangeserver");
print "dc_name = $dc_name\n";

The GetDistinguishedName function takes the Server name you want to query, an object type (or properly formatted ADODB filter, see below) and returns the distinguished name of the object on that server. This function is cross-compatible within Exchange versions, but not tested in Exchange 2000 (but would probably be useful in querying Active Directory Server attributes.

This function opens LDAP on the $server_name, applies the $filter, and then performs an ADODB search on the entire sub-tree. Once it finds values that meet your search criteria, it performs a pattern-match to see if $server_name is found anywhere in the distinguished name of search results. If it finds the server name in the results, it returns the first match.

if (Wi32::Exchange::GetDistinguishedName($info_store_server,'Home-MTA',$result)) {
print 'result = $result\n';
} else {
print 'Error Returning from GetDistinguishedName\n';

Currently this type of "pre-declaration" of a filter is available for 'Home-MTA' and 'Home-MDB' (case sensitive), but the function also accepts ADODB stype filters such as (objectClass=MTA) or (objectClass=MHS-Message-Store), which is the same as declaring 'Home-MTA' or 'Home-MDB'

Get familiar with the ADSVW program found in the ADSI 2.5 SDK. If you can find something helpful in ADSVW, chances are you can come up with an ADODB filter to meet your needs.

Win32::Exchange::GetLDAPPath($server_name,$org,$ou);#Exchange 5.5
The GetLDAPPath method takes a server name (Exchange 5.5) and returns the Organization and OU for the Server.

The function has no corresponding Exchange 2000 function, but performs the same objective (of determinig where to eventually create a mailbox) as provided by LocateMailboxStore.

if (Win32::Exchange::GetLDAPPath($info_store_server,$org,$ou)) {
print 'returned -> o='.$org.',ou='.$ou.'\n';
} else {
print 'Error Returning from GetLDAPPath\n';

This function returns a HASH of version information in the form of:

if (!Win32::Exchange::GetVersion($info_store_server,\%ver)) {
die "$rtn - Error returning from GetVersion\n";

print "version = $ver{ver}\n";
print "build = $ver{build}\n";
print "service pack = $ver{sp}\n";

This method allows you to query the Exchange 2000 server to determine:

if (Win32::Exchange::LocateMailboxStore($info_store_server,$storage_group,$mailbox_store,$store_name,\@counts)) {
print "storage group = $storage_group\n";
print "mailbox store = $mailbox_store\n";
print "located store distinguished name= $store_name\n";
print "$info_store_server\n";
print " Total:\n";
print " storage groups = @counts[0]\n";
print " mailbox stores = @counts[1]\n";

In this example, @counts is an optional parameter and should be populated providing the function is able to query the:
classes, and even if the function is unable to locate $storage_group and $mailbox_store, either because these variables are null strings and there is more than 1 mailbox store or storage group, or because they were not found as a valid storage group and mailbox store (useful for debugging purposes).

Module Options

Currently there are none, but I intend to make DEBUG a passable parameter as it is currently hard-coded to 1 (enabled).


This area under construction.  Sorry.



Bugs and Limitations



With the advent of Exchange 2000, lots of perl scripts started pouring through the listservs, that tried to parse the Storage Group name and Mailbox Store names into an incredibly long string to allow for Exchange 2000 mailbox creation (circa 2001?).

I knew that the entire string had to be all parsed together somewhere in the Directory, and it was just a matter of finding it.

It was; LocateMailboxStore is an implementation of that idea.

As it turns out, there are a lot of tricks like LocateMailboxStore that have helped develop this module from a string concatenation mess into a lot of fancy searches for the complete ldap paths and distinguished names that power mailbox creation and Exchange Server administration.

Most of the fancy searches were created by poking around in the objects themselves with ADSVW.EXE (an ADSI SDK tool), and then writing an ADODB search to return the right result set.

Thanks for taking the time to read all of this..

I'd like to extend thanks to the following:

Please send questions, comments or suggestions about this module to Steven Manross <>.


Version May 4, 2003


Microsoft, Active Directory, ADSI, Windows, Windows NT, MSDN, and Exchange are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

 Win32::Exchange - Exchange 5.5 and Exchange 2000 functions