hmaurich has asked for the wisdom of the Perl Monks concerning the following question:

Dear PerlMonks,

I have to gather remotely exchange contacts that are stored in a public folder in a separate database.

While using google I learned a lot about

Win32::OLE and MAPI

but there was no way to find "MAPI", "public folder", "exchange" and "perl" in one example.

May you gif me a startpoint?
(By the way...LDAP ist not the way because of "public folder"...)

PS. I've access to an AD-User on exchange's server.

Thanks for your time!
Martin
  • Comment on Get remotely exchange's contacts from a public folder

Replies are listed 'Best First'.
Re: Get remotely exchange's contacts from a public folder
by NetWallah (Canon) on Jul 11, 2008 at 18:02 UTC
      That's what I found out (may be it helps someone):

      (That scrip runs on a server with running outlook, gather contacts from a public folder and stores them in 2 different mssql tables.

      This complete solution solves some tricky problems, so

      - it klicks by itself on outlook security alert
      - make updates when contact already inserted
      - add a history-statement to an ntext (mssql) field
      - it uses Win32::SqlServer to manage utf8 chars

      When script finihed appears a TK box.

      Problem: you need an registered server; running as service or scheduled with taskmanager will not work!)


      _____________________________________________________
      #!/usr/bin/perl use utf8; binmode(STDOUT, ':utf8'); # utf8-Ausgabe mit print #binmode STDERR, ":encoding(cp850)"; # error messages in utf8 (disa +bled because of problems with "use threads" use CGI::Carp qw(fatalsToBrowser); use Digest::SHA1 qw(sha1_hex); use Tk; #Read Outlook Folder... use strict; use Win32::OLE; use Win32::OLE::Variant; # for date format use Win32::OLE::Const 'Microsoft Outlook'; use threads; use Win32::GuiTest qw(FindWindowLike GetWindowText SetForegroundWindow + SendKeys); use Win32::SqlServer; use Time::Local; use Mail::Sender; # my $Outlook = Win32::OLE->new(['my.machine.com', 'Program.Id']); my $Outlook = Win32::OLE->GetObject('Outlook.Application') || Win32::O +LE->new('Outlook.Application'); my $Session = $Outlook->Session; my $runError = 1; ################################################# # SETTINGS ################################################################ # List of implemented address-fields # ...fields I need my @ListContactFields = ( 'Anniversary', 'Account', 'Birthday', 'Body', 'Business2TelephoneNumber', 'BusinessAddress', 'BusinessAddressCity', 'BusinessAddressCountry', 'BusinessAddressPostalCode', 'BusinessAddressPostOfficeBox', 'BusinessAddressState', 'BusinessAddressStreet', 'BusinessFaxNumber', 'BusinessHomePage', 'BusinessTelephoneNumber', 'Categories', 'CompanyMainTelephoneNumber', 'CompanyName', 'ComputerNetworkName', 'Department', 'Email1Address', 'Email1AddressType', 'Email1DisplayName', 'Email2Address', 'Email2AddressType', 'Email2DisplayName', 'Email3Address', 'Email3AddressType', 'Email3DisplayName', 'EntryID', 'FileAs', 'FirstName', 'FTPSite', 'FullName', 'GovernmentIDNumber', 'Hobby', 'Home2TelephoneNumber', 'HomeAddress', 'HomeAddressCity', 'HomeAddressCountry', 'HomeAddressPostalCode', 'HomeAddressPostOfficeBox', 'HomeAddressState', 'HomeAddressStreet', 'HomeFaxNumber', 'HomeTelephoneNumber', 'Initials', 'ISDNNumber', 'JobTitle', 'Language', 'LastModificationTime', 'LastName', 'MailingAddress', 'MailingAddressCity', 'MailingAddressCountry', 'MailingAddressPostalCode', 'MailingAddressPostOfficeBox', 'MailingAddressState', 'MailingAddressStreet', 'MobileTelephoneNumber', 'MiddleName', 'NickName', 'OfficeLocation', 'OrganizationalIDNumber', 'OtherAddress', 'OtherAddressCity', 'OtherAddressCountry', 'OtherAddressPostalCode', 'OtherAddressPostOfficeBox', 'OtherAddressState', 'OtherAddressStreet', 'OtherFaxNumber', 'OtherTelephoneNumber', 'PagerNumber', 'PersonalHomePage', 'PrimaryTelephoneNumber', 'Profession', 'RadioTelephoneNumber', 'Suffix', 'Title', 'WebPage' ); my @ListFirmFields = @ListContactFields; #my @ListFirmFields = ( # #'Body', #'Business2TelephoneNumber', #'BusinessAddress', #'BusinessAddressCity', #'BusinessAddressCountry', #'BusinessAddressPostalCode', #'BusinessAddressPostOfficeBox', #'BusinessAddressState', #'BusinessAddressStreet', #'BusinessFaxNumber', #'BusinessHomePage', #'BusinessTelephoneNumber', #'Categories', #'CompanyMainTelephoneNumber', #'CompanyName', #'ComputerNetworkName', #'Department', #'Email1Address', #'Email1AddressType', #'Email1DisplayName', #'Email2Address', #'Email2AddressType', #'Email2DisplayName', #'Email3Address', #'Email3AddressType', #'Email3DisplayName', #'EntryID', #'FileAs', #'FTPSite', #'FullName', #'GovernmentIDNumber', #'Initials', #'ISDNNumber', #'JobTitle', #'Language', #'LastModificationTime', #'MailingAddress', #'MailingAddressCity', #'MailingAddressCountry', #'MailingAddressPostalCode', #'MailingAddressPostOfficeBox', #'MailingAddressState', #'MailingAddressStreet', #'MobileTelephoneNumber', #'OfficeLocation', #'OrganizationalIDNumber', #'PrimaryTelephoneNumber', #'RadioTelephoneNumber', #'WebPage' #); my $dbh = Win32::SqlServer::sql_init('YourDatabaseServer', 'You +rUser', 'YourPw', 'YourDatabase'); my $sqlTab = ""; my $sqlTabP = "RelatedContacts"; my $sqlTabF = "Partners"; my $OutlookCatP = "RelatedContact"; my $OutlookCatF = "ContactPartner"; my %RUseLocation; $RUseLocation{'FRA'} = 'Öffentliche Ordner/Alle Öffentlichen Ordner/Ot +herFolder/NextFolder/YourFolder'; my $LogPath = "\\\\YourServerForLogfiles\\local\$\\Login\\Logfiles" +; #my $LogPath = "\\\\YourServerForLogfiles\\local\$\\System\\Tasks\\ +Logfiles"; # No access (!) my $LogOk = $LogPath."\\folder\\Ok.log"; my $LogError = $LogPath."\\folder\\Error.log"; my $LogCount = $LogPath."\\folder\\CountAddrXXX.log"; my $MailErrorFrom = 'something@domain.com'; my $MailErrorTo = 'something@domain.com'; my $SMTP_HOST="12.34.56.789"; $SMTP_HOST="SmtpHost"; ################################################# # PROGRAM my (@ContactDatas,$Felder,$sql,$contacts,$DBScope,@ListFields,%count); $count{'P_UPDATE'} = 0; $count{'F_UPDATE'} = 0; $count{'P_INSERT'} = 0; $count{'F_INSERT'} = 0; my ($sec, $min, $h, $month_day, $month, $year, $weekday, $yearday, $so +mmertime) = localtime(time); $month++; $year+=1900; ### start thread my $thr = threads->create(\&ClickOkThread); # Get a thread's ID my $tid = $thr->tid(); while(my ($key,$val) = each %RUseLocation) { GetContacts ($Session->Folders,$key,$val); SaveContacts ($key); } ### Exit a thread # Signal the thread to terminate, and then detach # it so that it will get cleaned up automatically #$thr->kill('KILL')->detach(); ### Say so long my $myWindow = MainWindow->new; $myWindow->Label ( -text => "Update successfully completed.", -height => 3, -width => 30 ) ->pack; $myWindow->Button( -text => "close", -height => 0, -width => 18, -command => [$myWindow => 'destroy'] ) ->pack; $myWindow->Label ( -text => "" ) ->pack; MainLoop; ################################################# # SUBROUTINES ### get all contacts from public folder sub GetContacts { my ($FolderCollection,$RUseLocation,$FolderPath) = @_; $runError = 1; # This is my destination: # Öffentliche Ordner/Alle Öffentlichen Ordner/OtherFolder/NextFolder/Y +ourFolder # That's the object's structure: # $Session->Folders->{'1'}->Folders->{'2'}->Folders->{'8'}->Folders->{ +'1'}->Folders->{'3'}->Name >>> "YourFolder" my @FolderNames = split(/\//,$FolderPath); for my $Folder (in $FolderCollection) { my $i; for($i=0;$i<$#FolderNames;$i++) { if ($Folder->{Name} =~ /$FolderNames[$i]/) { GetContacts($Folder->Folders,$RUseLocation,$FolderPath); } } if ($Folder->{Name} =~ /$FolderNames[$#FolderNames]/) { # read all contacts $contacts = $Folder->{Items}; my $ncon = $contacts->{Count}; # number of contacts # read saved number of contacts and save actual number if greater +than.. &CheckNoOfContacts($ncon,$RUseLocation); # collect contacts for my $ii (1 .. $ncon) { $ContactDatas[$ii] = $contacts->Item($ii); } } } # for $runError = 0; } # sub ### check if date lies ahead sub DateIsValid { my ($Bday) = @_; # Birthday needs manipulation >>> empty Birthday stands here for 01. +01.4501! my $YearBday = substr($Bday,6,4)-1900; if(($year-1900)>$YearBday) { my $DayBday = substr($Bday,0,2)+0; my $MonthBday = substr($Bday,3,2)-1; #$timeDate=timelocal($sekunde,$minute,$stunde,$tag,$monat-1,$jahr-1 +900); my $timeBday=timelocal(0,0,0,$DayBday,$MonthBday,$YearBday); if($timeBday < time ) { return 1; } } return 0; } ### store contacts data to mssql sub SaveContacts { my ($RUseLocation) = @_; my($sqlInsKeys,$sqlInsVals,$sqlUpdPairs); $runError = 1; # Default: $dbh->{ErrInfo}{MaxSeverity} = 10; # When there is an error, we only want the line that is flagged # for the error. $dbh->{ErrInfo}{LinesWindow} = 0; # We need to save messages to see if data loaded successfully. $dbh->{ErrInfo}{SaveMessages} = 1; # Siehe: SELECT * FROM master.dbo.sysmessages $dbh->{ErrInfo}{NeverStopOn}{2601}=1; # SQL-Fehler 2601 Cannot ins +ert duplicate key row in object '%.*ls' with unique index '%.*ls'. $dbh->{ErrInfo}{NeverPrint}{2601}=1; $dbh->{ErrInfo}{NeverStopOn}{2627}=1; # SQL-Fehler 2627 Violation +of UNIQUE KEY constraint '...'. Cannot insert duplicate key.. $dbh->{ErrInfo}{NeverPrint}{2627}=1; $dbh->{ErrInfo}{NeverPrint}{3621}=1; # SQL-Fehler 3621 The stateme +nt has been terminated. for(my $n=1;$n<=$contacts->{Count};$n++) { if($ContactDatas[$n]->{Categories}=~m/$OutlookCatP/) { @ListFields = @ListContactFields; $sqlTab = $sqlTabP; $DBScope = "P"; } elsif($ContactDatas[$n]->{Categories}=~m/$OutlookCatF/) { @ListFields = @ListFirmFields; $sqlTab = $sqlTabF; $DBScope = "F"; } else { next; } $sql = ("INSERT INTO $sqlTab "); $sqlInsKeys = ""; $sqlInsVals = ""; $sqlUpdPairs = ""; foreach my $ContKey (@ListFields) { if($ContKey=~m/Birthday|LastModificationTime|Anniversary/) { $sqlInsKeys .= $DBScope.$ContKey.","; if($ContactDatas[$n]->{$ContKey} ne "" && &DateIsValid($ContactDat +as[$n]->{$ContKey})) { if($ContKey eq "LastModificationTime") { my $LastModificationTimeMSSql = substr($ContactDatas[$n]->{LastM +odificationTime},6,4)."-".substr($ContactDatas[$n]->{LastModification +Time},3,2)."-".substr($ContactDatas[$n]->{LastModificationTime},0,2). +substr($ContactDatas[$n]->{LastModificationTime},10,).".000"; $sqlInsVals .= "'".$LastModificationTimeMSSql."',"; $sqlUpdPairs .= $DBScope.$ContKey."='".$LastModificationTimeM +SSql."',"; } } else { my $tmp = substr($ContactDatas[$n]->{$ContKey},6,4)."-".substr($C +ontactDatas[$n]->{$ContKey},3,2)."-".substr($ContactDatas[$n]->{$Cont +Key},0,2); $sqlInsVals .= "'".$tmp."',"; $sqlUpdPairs .= $DBScope.$ContKey."='".$tmp."',"; } } else { # MSSQL doesn't escape single quotes with a backslash. # escapes single quotes with another single quote! $ContactDatas[$n]->{$ContKey} =~ s/\'/\'\'/g; # double quotes to entities $ContactDatas[$n]->{$ContKey} =~ s/\&quot;/\"/g; # line breakes $ContactDatas[$n]->{$ContKey} =~ s/\r\n/\\n/g; # if windows $ContactDatas[$n]->{$ContKey} =~ s/\n/\\n/g; # if unix $sqlInsKeys .= $DBScope.$ContKey.","; $sqlInsVals .= "N'".$ContactDatas[$n]->{$ContKey}."',"; $sqlUpdPairs .= $DBScope.$ContKey."=N'".$ContactDatas[$n]->{$Co +ntKey}."',"; } } # remove last commas $sqlInsKeys .= "RUseLocation"; $sqlInsVals .= "'$RUseLocation'"; $sqlUpdPairs =~ s/,$//; $sql.= ("(".$sqlInsKeys.",".$DBScope."EntryIDsha1) VALUES (".$sqlInsVals.",'".sha1_hex($ContactDatas[$n]->{'EntryID'}). +"') "); #Debugging #print $sql."<br />\n\n"; #for(my $i=0;$i<50;$i++) #{ # print $i." - ".$ContactDatas[$i]->{'FileAs'}."<br />\n"; #} #print $ContactDatas[4]->{'Body'}."<br />\n\n"; #exit; delete $dbh->{ErrInfo}{Messages}; $dbh->sql($sql,Win32::SqlServer::NORESULT); if ($dbh->sql_has_errors()) { if($dbh->{ErrInfo}{Messages}[0]{Errno} eq "2601" || $dbh->{ErrInfo} +{Messages}[0]{Errno} eq "2627") { # dataset already exists, try update $sql = ("UPDATE $sqlTab SET $sqlUpdPairs WHERE ".$DBScope."EntryIDsha1 = '".sha1_hex($ContactDatas[$n]->{'Entr +yID'})."'" ); delete $dbh->{ErrInfo}{Messages}; $dbh->sql($sql,Win32::SqlServer::NORESULT); if ($dbh->sql_has_errors()) { ### sorry for error, but no reaction from here } else { $count{$DBScope.'_UPDATE'}++; } } else { # an error occured $$Felder{'ErrorMsg'} = "INSERT failed:\n$sql\nErrInfo.Messages:\n" +; while(my ($key,$val) = each %{$dbh->{ErrInfo}{Messages}[0]}) { $$Felder{'ErrorMsg'}.= "$key: $val<br />\n"; } &LOGGING($RUseLocation." ".$$Felder{'ErrorMsg'},"error"); } } else { $count{$DBScope.'_INSERT'}++; # $sql = 'SELECT @@IDENTITY AS \'Kennummer\''; # # $result = $dbh->sql($sql,Win32::SqlServer::MULTISET); # $Felder->{'Kennummer'} = $$result[0][0]{'Kennummer'}; # # #Debugging # #print "Content-type: text/html; charset=utf-8\n\n"; # #print $$result[0][0]{'Kennummer'}."<br />\n"; # #print $res."<br />\n"; # #print $sql."<br />\n"; # #die; # # # Alle entsprechenden Einträge in A_Session löschen # $sql = ("DELETE FROM ".$sqlTab{'Session'}." # WHERE TableName = '".$sqlTab{'Domains'}."' # "); # $result = $dbh->sql($sql,Win32::SqlServer::MULTISET); } } delete $dbh->{ErrInfo}{NeverPrint}{3621}; delete $dbh->{ErrInfo}{NeverPrint}{2601}; delete $dbh->{ErrInfo}{NeverPrint}{2627}; delete $dbh->{ErrInfo}{NeverStopOn}{2601}; delete $dbh->{ErrInfo}{NeverStopOn}{2627}; $runError = 0; &LOGGING($RUseLocation." Databases \"$sqlTabP\" and \"$sqlTabF\" succ +essful updated.\n$sqlTabF INSERT: $count{'F_INSERT'} UPDATE: $count{' +F_UPDATE'}\n$sqlTabP INSERT: $count{'P_INSERT'} UPDATE: $count{'P_UPD +ATE'}\n","ok"); } ### error handling sub LOGGING { my ($Text,$scope) = @_; $runError = 1; $Text = "$year-".sprintf("%02.0f", $month)."-".sprintf("%02.0f", $mon +th_day)." ".sprintf("%02.0f", $h).":".sprintf("%02.0f", $min).":".spr +intf("%02.0f", $sec)." $Text"; if($scope eq "error") { &MailSend($MailErrorFrom,$MailErrorTo,'','Error MAPI data import pub +lic folder',$Text); open (LOGFILE, ">>$LogError") || die "No access to $LogError: $!, st +opped\n"; print LOGFILE "$Text\n\n"; close(LOGFILE) || die "Can't close file $LogError: $!, stopped\n"; } elsif($scope eq "ok") { open (LOGFILE, ">>$LogOk") || die "No access to $LogOk: $!, stopped\ +n"; print LOGFILE "$Text\n"; close(LOGFILE) || die "Can't close file $LogOk: $!, stopped\n"; } $runError = 0; } ### mail handling sub MailSend { my ($FROM,$TO,$CC,$SUBJECT,$BODY) = @_; #~ $SMTP_HOST = '123.456.78.90'; #~ $FROM = 'you@domain.de'; #~ $TO = 'you2@domain.de'; #~ $CC = 'Irgenwer@irgendwo.net, irgenwen@anders.com'; #Das leerzeic +hen hinter dem komma muss sein $TO =~ s/;/, /g; eval { my $sender = (new Mail::Sender)->MailMsg({ smtp => $SMTP_HOST, from => "$FROM", to => "$TO", #cc => "$CC", # uses "" for more than one email-address subject => $SUBJECT, msg => $BODY}); my $errMail = $sender->Close(1); }; } ### number of contacts handling sub CheckNoOfContacts { my ($ncon,$RUseLocation) = @_; my ($nconSaved); my $LogC = $LogCount; $LogC=~s/XXX/$RUseLocation/; open (COUNTFILE, '<', $LogC) || die "No read access to $LogC: $!, sto +pped\n"; $nconSaved = <COUNTFILE>; close(COUNTFILE) || die "Can't close file $LogC: $!, stopped\n"; if($nconSaved > $ncon) { &LOGGING($RUseLocation." Saved number of addresses in public folder +is greater than actual number.\n\nThat means, some addresses where de +leted or lost!\n\nIf this is correct, please write \"$ncon\" to file +$LogC and start MAPI-import again.","error"); die "Saved number of addresses in public folder is greater than actu +al number. See \"$LogError\". Program stopped.\n"; } else { open (COUNTFILE, '>', $LogC) || die "No write access to $LogC: $!, s +topped\n"; print COUNTFILE "$ncon"; close(COUNTFILE) || die "Can't close file $LogC: $!, stopped\n"; } } ### thread to click on Outlooks security window sub ClickOkThread { my (@w); my $MaxLoop = 20000; # >> 1 hour # Thread 'cancellation' signal handler $SIG{'KILL'} = sub { threads->exit(); }; my $n = 0; while (1) { @w = FindWindowLike(undef,"^Microsoft Office Outlook\$"); # title + of security window #@w = FindWindowLike(undef,"Microsoft Office Outlook"); if($w[0] ne "") { SetForegroundWindow($w[0]); #SendKeys("{LEFT}{LEFT}{SPACE}{RIGHT}{DOWN}{DOWN}{DOWN}{TAB}~"); + # select "10min access" from security alert #SendKeys("{LEFT}{LEFT}{SPACE}{RIGHT}{DOWN}{DOWN}{TAB}~"); # sel +ect "5min access" from security alert SendKeys("{LEFT}{LEFT}{SPACE}{RIGHT}{DOWN}{TAB}~"); # select + "2min access" from security alert #SendKeys("{LEFT}~"); # only click "ok" } sleep(1); #select(undef, undef, undef, 0.1); $n++; if($n>$MaxLoop){last;} } } END { if($runError){ &LOGGING("END-Block: $!, \$sql = \"$sql\", $ENV{'SCRIP +T_NAME'} stopped","error"); } } ################################################################ # Complete list of address-fields # #Application: Win32::OLE=HASH(0x1f5da64) #Class: 40 #Session: Win32::OLE=HASH(0x1eadf64) #Parent: Win32::OLE=HASH(0x1f7203c) #Actions: Win32::OLE=HASH(0x1f72030) #Attachments: Win32::OLE=HASH(0x1f72048) #BillingInformation: #Body: HYPERLINK "mailto:marcmueller@email.de"marcmueller@email.de #Categories: #Companies: #ConversationIndex: 01C8E59AFA63CE59CCBAC4154C778E52855D1F2CA50B #ConversationTopic: Marc M++ller #CreationTime: 14.07.2008 12:18:02 #EntryID: 000000001A447390AA6611CD9BC800AA002FC45A09002CA1DAB8F257D411 +B24900508B # 69347F00000000F6EA00002F7D6AD47D38D141AB1B08DB111AB467000000 +01293F0000 #FormDescription: Win32::OLE=HASH(0x1f71fd0) #GetInspector: Win32::OLE=HASH(0x1f720b4) #Importance: 1 #LastModificationTime: 14.07.2008 12:18:35 #MessageClass: IPM.Contact #Mileage: #NoAging: 0 #OutlookInternalVersion: 118206 #OutlookVersion: 11.0 #Saved: 1 #Sensitivity: 0 #Size: 672 #Subject: Marc M++ller #UnRead: 1 #UserProperties: Win32::OLE=HASH(0x1f72120) #Account: #Anniversary: 01.01.4501 #AssistantName: #AssistantTelephoneNumber: #Birthday: 01.01.4501 #Business2TelephoneNumber: #BusinessAddress: Waldfriedhofstr. 60 #81377 M++nchen #BusinessAddressCity: M++nchen #BusinessAddressCountry: Deutschland #BusinessAddressPostalCode: 81377 #BusinessAddressPostOfficeBox: #BusinessAddressState: #BusinessAddressStreet: Waldfriedhofstr. 60 #BusinessFaxNumber: #BusinessHomePage: #BusinessTelephoneNumber: #CallbackTelephoneNumber: #CarTelephoneNumber: #Children: #CompanyAndFullName: M++ller, Marc #CompanyLastFirstNoSpace: #CompanyLastFirstSpaceOnly: #CompanyMainTelephoneNumber: #CompanyName: #ComputerNetworkName: #CustomerID: #Department: #Email1Address: #Email1AddressType: #Email1DisplayName: #Email1EntryID: #Email2Address: #Email2AddressType: #Email2DisplayName: #Email2EntryID: #Email3Address: #Email3AddressType: #Email3DisplayName: #Email3EntryID: #FileAs: IT, M++ller, Marc #FirstName: Marc #FTPSite: #FullName: Marc M++ller #FullNameAndCompany: M++ller, Marc #Gender: 0 #GovernmentIDNumber: #Hobby: #Home2TelephoneNumber: #HomeAddress: #HomeAddressCity: #HomeAddressCountry: #HomeAddressPostalCode: #HomeAddressPostOfficeBox: #HomeAddressState: #HomeAddressStreet: #HomeFaxNumber: #HomeTelephoneNumber: 089-71049204 #Initials: M.M. #InternetFreeBusyAddress: #ISDNNumber: #JobTitle: #Journal: 0 #Language: #LastFirstAndSuffix: #LastFirstNoSpace: #LastFirstNoSpaceCompany: #LastFirstSpaceOnly: #LastFirstSpaceOnlyCompany: #LastName: M++ller #LastNameAndFirstName: M++ller, Marc #MailingAddress: Waldfriedhofstr. 60 81377 M++nchen #MailingAddressCity: M++nchen #MailingAddressCountry: Deutschland #MailingAddressPostalCode: 81377 #MailingAddressPostOfficeBox: #MailingAddressState: #MailingAddressStreet: Waldfriedhofstr. 60 #ManagerName: #MiddleName: #MobileTelephoneNumber: 01733105460 #NetMeetingAlias: #NetMeetingServer: #NickName: #OfficeLocation: #OrganizationalIDNumber: #OtherAddress: #OtherAddressCity: #OtherAddressCountry: #OtherAddressPostalCode: #OtherAddressPostOfficeBox: #OtherAddressState: #OtherAddressStreet: #OtherFaxNumber: #OtherTelephoneNumber: #PagerNumber: #PersonalHomePage: #PrimaryTelephoneNumber: #Profession: #RadioTelephoneNumber: #ReferredBy: #SelectedMailingAddress: 2 #Spouse: #Suffix: #TelexNumber: #Title: #TTYTDDTelephoneNumber: #User1: #User2: #User3: #User4: #UserCertificate: #WebPage: #YomiCompanyName: #YomiFirstName: #YomiLastName: #Links: Win32::OLE=HASH(0x1f786cc) #ItemProperties: Win32::OLE=HASH(0x1f78708) #LastFirstNoSpaceAndSuffix: #DownloadState: 1 #IMAddress: #MarkForDownload: 0 #IsConflict: 0 #AutoResolvedWinner: 0 #Conflicts: Win32::OLE=HASH(0x1f7872c) #HasPicture: 0
        OK, above you find my knowledge, now I need yours! :-)

        To solve the problem with registered server and running outlook now I want to gather all contacts with WebDAV.

        Remember, I need contacts from a public folder not emails.

        We use IIS, SBS 2003 and Exchange 2003 -
        may I use HTTP::Webdav?
        Is there any example script out there?

        Thank you for help!
        Martin