Link to home
Start Free TrialLog in
Avatar of pganeshkumar
pganeshkumar

asked on

VBA Maintain Outlook DL list

Hi

We are using MS Outlook 2003 and we have a distribution list (DL) for our app. we are trying to automate the process of maintaining tis DL using VBA code. as a proof of concept, we are trying to add/remove a user from this DL but so far we have had no success. We are able to list the members of the DL but get an error when trying to add to it. It says the requested operation is unsupported but the code seems to be correct since I am trying to invoke the Add method on an AddressEntries collection.
I have pasted the code as well as the o/p when we do a sample run.
Any help in putting us on the right track is most appreciated. Thanks a lot.
Function UpdateDistList(EmailAddresses As String, DistName As String) As Boolean
' EmailAddresses: a comma-delimited string literal list of valid email addresses
' DistName: a string literal name for the distribution list

On Error GoTo ErrorHandler

Dim vAddr As Variant
vAddr = Split(EmailAddresses, ",")

' get Outlook
Dim olApp As Object ' Outlook.Application
Set olApp = GetOutlookApp

' create distribution list items
Dim objNS As Object          'Outlook.Namespace
Dim olDistListItem As Object ' Outlook.DistListItem
Dim objAddrList As Object ', objDist As Object
Dim objAddrEntry As Object
Dim objNewAddrEntry As Object
Dim tempMailItem As Object ' Outlook.MailItem
Dim tempRecipients As Object ' Outlook.Recipients


    Set objNS = olApp.GetNamespace("MAPI")
    Set objAddrList = objNS.Session.AddressLists("Global Address List") '.Items
    Debug.Print "TypeName(objAddrList) = " & TypeName(objAddrList)

    Set olDistListItem = objAddrList.AddressEntries(DistName)
    
    On Error GoTo 0
    If olDistListItem Is Nothing Then
        MsgBox "Distribution List " & DistName & " doesn 't exist", vbCritical
        GoTo ErrorHandler
    End If
    
    Debug.Print "TypeName(olDistListItem) = " & TypeName(olDistListItem)

    Debug.Print "Number of members in distribution list = " & olDistListItem.Members.Count
    Debug.Print "TypeName(olDistListItem.Members) = " & TypeName(olDistListItem.Members)
       
    Dim i As Integer
    For i = 1 To olDistListItem.Members.Count
        Debug.Print TypeName(olDistListItem.Members.Item(i)) & ", " & olDistListItem.Members.Item(i).Type
        Set objAddrEntry = olDistListItem.Members.Item(i)
        Debug.Print objAddrEntry.Name, objAddrEntry.Address
    Next
    
    Dim obj As Object
    Set obj = olDistListItem.Members

    For i = 0 To UBound(vAddr)
      Debug.Print "TypeName(obj) = " & TypeName(obj) & ", Count = " & obj.Count
      On Error Resume Next
      Set objNewAddrEntry = obj.Add("EX", , vAddr(i))
      Debug.Print Err.Description
      objNewAddrEntry.Update True, False
    Next i
    
    Debug.Print "Added member(s)"
    
    CreateDistList = True
    GoTo ExitProc

ErrorHandler:
    CreateDistList = False

ExitProc:
    Debug.Print "Cleaning up the variables ..."
    
    Set obj = Nothing
    Set tempRecipients = Nothing
    Set tempMailItem = Nothing
    Set olDistListItem = Nothing
    Set objAddrList = Nothing
    Set objNS = Nothing
    
    If bWeStartedOutlook Then
      olApp.Quit
    End If
    
    Set olApp = Nothing
End Function

***** Output **********
TypeName(objAddrList) = AddressList
TypeName(olDistListItem) = AddressEntry
Number of members in distribution list = 2
TypeName(olDistListItem.Members) = AddressEntries
AddressEntry, EX
Cassidy, Michael(NYK)   /O=BMW/OU=USA/cn=Recipients/cn=cassidmi
AddressEntry, EX
Kumar, Ganesh (NYK)       /O=BMW/OU=USA/cn=Recipients/cn=kumarg
TypeName(obj) = AddressEntries, Count = 2
The requested operation cannot be completed because the operation is not supported on this object.
Added member(s)
Cleaning up the variables ...

Open in new window

Avatar of David Lee
David Lee
Flag of United States of America image

Hi, pganeshkumar.

You don't add a member to a dist list by adding tot he AddressEntries collection.  You add them by using the AddMember method of the dist list object.  Here is an example.
Sub UpdateDistList(strAddresses As String, strListName As String)
    Dim arrAddresses As Variant, _
        varAddress As Variant, _
        olkList As Outlook.DistListItem, _
        olkRecipient As Outlook.Recipient
    Set olkList = Session.GetDefaultFolder(olFolderContacts).Items.Find("[Name] = '" & strListName & "'")
    If TypeName(olkList) = "Nothing" Then
        msgbox "Could not find a list named " & strListName
    Else
        arrAddresses = Split(strAddresses, ",")
        For Each varAddress In arrAddresses
            Set olkRecipient = Session.CreateRecipient(varAddress)
            olkRecipient.Resolve
            If olkRecipient.Resolved Then
                olkList.AddMember olkRecipient
            Else
                msgbox "Could not resolve the address " & varAddress
            End If
        Next
    End If
    olkList.Save
    Set olkRecipient = Nothing
    Set olkList = Nothing
End Sub

Open in new window

Avatar of pganeshkumar
pganeshkumar

ASKER

Hi BlueDevilFan
   I tried to use your code but it gives me a runtime error saying 'The property  "Name" is unknown' when it tries to do a lookup for the particular distribution list.
   The other question I had was will your code be able to lookup a distribution list that is part of the "Global Address List"? I tried to use the attached code but it threw  error '438 saying the proprty was unsupported.
Thanks a lot.

Set olkList = Session.AddressLists("Global Address List").Items.Find("[Name] = '" & strListName & "'")

Open in new window

The question didn't mention that this was an Exchange distribution list.  The question only mentions Outlook so I assumed we were talking about an Outlook distribution list.  Does your organization have its own Exchange server or does it use a hosted solution?  Exchange distribution lists don't exist in Outlook.  They exist in Active Directory.  If you have your own Exchange server, then this might be possible.  If instead your organization is using hosted Exchange, then I'm not sure this is possible.
Hi

I did not realize that the distribution lists in the global address list are hosted on the exchange server. Sorry about not providing the accurate info. Our company hosts its own exchange server.

Thanks
Is this still an issue?
Hi darkstar3d,

Yes. This is still an open issue. Just to clarify (since my heading for the question is not really correct as pointed out by BlueDevil), the distribution list already exists in the 'Global Address List' on the Exchange Server. We need a way to programtically add to/remove from this distribution list. We are looking to have this maintenance done using Excel macros.

Thanks a lot.
Unlike Outlook 2007, the object model for Outlook 2003 does not have any methods for manipulating an Exchange distribution list.  The only way I can think of to so this is to access Active Directory directly.  That's doable, it's just a bit more complicated.  Most accounts won't have the necessary permissions to write to AD.  I can put a script together, but it may not be usable by anyone who isn't an admin.
Hi BlueDevilFan

I am allowed to add/remove members to this distribution list using the MS Outlook app installed on my desktop. Could this possibly mean that I have permissions to manipulate this distro list using Active Directory also?

Would it be possible to provide me with both the Active Dirctory solution and the Outlook 2007 solution? My company is rumored to be migrating to Outlook 2007 soon and I might be able to use this then. I migth become an initial adopter also.

Thanks a lot.
"Could this possibly mean that I have permissions to manipulate this distro list using Active Directory also?"
I don't know.  The way the list is accessed and updated is completely different.  I don't know if the access method I'm thinking about handles security in the same fashion.  In fact I don't know how Outlook handles security, so I can't even make a comparison.  

While I was writing this I thought of something I had considered before.  Are the members of the list in question internal or external to your organization?  I believe that an AD distribution list requires that all external members have a contact entry in AD.  I'll have to check on that.  If that's the case, then this just got very much harder.  It would no longer be a matter of just managing the list, it would also be a matter of managing the contacts the list is composed of.  
Hi BlueDevilFan

All the members would be internal members. They all exist already in the global address book. Our app already has their ids and email addresses stored. So it would be a matter of looking up the person in the global address book using the id or email address and then add them to the distro list.

Thanks.
BlueDevil is right about external contacts. If the input parameters are strings, why must this be in Excel? Just curious. I know that with VSTO you could do this this in Excel, but I don't have Excel 2003 installed anywhere.
Hi darkstar3d
Our company admin folks will create a global distro list for us but won't have any part in maintaiing this. As new users get added or existing users leave, our app's distro list has to be updated accordingly. This is what we are trying to automate.
We have already coded stored procedures that would give us a weekly report of the user id, email address and the action to be taken (ADD or REMOVE - distro list). We want to just put this resultset inan Excel sheet with the macors to actually update the distro list and then just loop through the list and perform the indicated action.  Please see attached snippet that represents the Excel sheet report.
Thanks
User Id	   Email	                  Action
Raj Rames	   raj.rames@abc.com	ADD
James Nair  james.nair@abc.com	REMOVE

Open in new window

I think I understand now, the output is tab delimited which opens in Excel. You simply need something that can read that output and maintain the list. If I am right about that, Excel and Outlook are both in the way.
Hi darkstar3d

You are right. The idea is that we have a list of ids/email addresses that need to be added to/removed from the list. Why do you say Excel abd Outlook are in the way? If it will be easier to accomplish this using something other than VBA, it should work fine too.

Thanks.
If you can compile C#, Microsoft has a free compiler, then this is the ticket. I could also compile it, but is not a good choice. Will be in the AM, have to close out today!
I do have have VB.Net on my machine. So I guess getting the right tools for C# would not be too very difficult.

Thanks for all your help.
Cool. I started this about an hour ago. Got a few more error conditions to handle (will still be bare bones) but almost to a solution.
ASKER CERTIFIED SOLUTION
Avatar of Stacy Spear
Stacy Spear
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi darkstar3d

You have whizzed through your part. Now I will have to do mine but I am not going to be able to get to it until later tonight or tomorrow since I am handling a couple of urgent issues. I will try this out at the earliest and update you on the outcome.

I appreciate all your help. Thanks a lot.
Hi darkstar3d

I have compiled the code and successfully added/removed 2 users. I have one question though: when you do the lookup for the user using searcher.FindAll(), you are filtering on mail. When I lookup these users' properties in Outlook, I see a whole slew of emails and they are not all the same (though they all say smtp). Which one of these emails does the program really match on?

I am leaving this question open over the weekend since I want to do some more checking over the weekend and in case I run into any issues, I will reach out to you.

Thanks a lot for all your help.
Hi darkstar3d

Sorry about the delay in getting back to you. It's been a crazy start to the week. But the one good thing so far has been code you have provided. it works as expected and now I am working on building a GUI around this code so that it can be reused for multiple distribution lists.

Even though I had one question regarding the searcher.FindAll method(detailed in my previous reply), I am closing this question at this point since this has been a long thread and I don't keep extending it any longer any necessary.

Thanks a lot for all your help.
The expert was very thorough in figuring out the problem being solved and provided a solution that worked right away once some of the environment specific parameters were changed. He also pointed out the fact this was a no frills version that needed more error handing to be added in certain cases.
Sorry, I took a long weekend with no electronic items! :)

The entry with SMTP in CAPS is the main email address. The output from the other process is most likely taking the mail attribute address from the user which doesn't have the smtp on it. The proxyAddresses field contains all the addresses a user has in no particular order, so the primary entry of each type is in all caps so that the server knows which one is THE one.

Glad it works for you!
Hi darkstar3d

Thanks for your clarification.