Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm using Exchange 2003, Outlook 2007/2003. Is there a way to push a set of contacts to users? I would prefer to not use the GAL and I really don't want to send csv files for them to import.

Any help is appreciated.


If someone has a great method of managing contacts with a mobile workforce, I'd love to hear that as well.

share|improve this question
up vote 0 down vote accepted

This is an extremely mangled vbscript I've been using to push a sub-folder of contacts from one user to a list of users provided in a text file:

snServername = "exchange"
mnMailboxname = ""
mndestmailbox = ""

Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
    ("c:\scripts\users.txt", ForReading)
Do Until objTextFile.AtEndOfStream
    mndestmailbox = objTextFile.Readline

    wscript.echo ""
    wscript.echo mndestmailbox

SourceURL = "http://" & snServername & "/exchange/" & mnMailboxname & "/contacts/folder to copy/"
DestinURL = "http://" & snServername & "/exchange/" & mndestmailbox & "/contacts/folder to copy/"
set req = createobject("microsoft.xmlhttp")

set CDOSession = CreateObject("MAPI.Session")
strProfile = snServername & vbLf & mnMailboxname
CDOSession.Logon "",,, False,, True, strProfile
set RDOSession = CreateObject("Redemption.RDOSession")
set cfCalendarFolder1 = RDOSession.GetSharedDefaultFolder(mndestmailbox, 10)
For Each fld In cfCalendarFolder1.Folders
    If = "folder to copy" Then 
    	Set cfCalendarFolder = fld 
    End if

colbblob = Collabblobget()
wscript.echo colbblob

wscript.echo "Done"


Sub QueryMailbox(colbblob)

strQuery = "<?xml version=""1.0""?><D:searchrequest xmlns:D = ""DAV:"" xmlns:R=""""><R:repl><R:collblob>" & colbblob & "</R:collblob></R:repl>"
strQuery = strQuery & "<D:sql>SELECT ""DAV:href"", ""urn:schemas:httpmail:subject"", """","""" "
strQuery = strQuery & " FROM scope('shallow traversal of """
strQuery = strQuery & SourceURL & """') Where NOT ""urn:schemas:calendar:instancetype"" = 2 AND NOT ""urn:schemas:calendar:instancetype"" = 3 AND ""DAV:ishidden"" = False AND ""DAV:isfolder"" = False "
strQuery = strQuery & "</D:sql></D:searchrequest>" "SEARCH", SourceURL, false, "", ""
req.setrequestheader "Content-Type", "text/xml"
req.setRequestHeader "Translate","f"
req.send strQuery
If req.status >= 500 Then
   wscript.echo "Status: " & req.status
   wscript.echo "Status text: An error occurred on the server."
ElseIf req.status = 207 Then
   wscript.echo "Status: " & req.status
   wscript.echo "Status text:  " & req.statustext
   set oResponseDoc = req.responseXML
   set oNodeList = oResponseDoc.getElementsByTagName("d:collblob")
   For i = 0 To (oNodeList.length -1)
    set oNode = oNodeList.nextNode
        colblob =  oNode.Text
   set idNodeList = oResponseDoc.getElementsByTagName("f:x0fff0102")
   set replidNodeList = oResponseDoc.getElementsByTagName("d:repl-uid")
   set replchangeType = oResponseDoc.getElementsByTagName("d:changetype")
   for id = 0 To (idNodeList.length -1)
    set oNode1 = idNodeList.nextNode
    set oNode2 = replidNodeList.nextNode
    set oNode3 = replchangeType.nextNode
    select case oNode3.text
    	case "new" call Copyapt(Octenttohex(oNode1.nodeTypedValue),oNode2.text)
    	case "delete" wscript.echo oNode3.text
    		      wscript.echo oNode2.text
    	case "change" Wscript.echo "Change"
    		      call DeleteContact(oNode2.text)
    		      call Copyapt(Octenttohex(oNode1.nodeTypedValue),oNode2.text)
    end select
   wscript.echo "Status: " & req.status
   wscript.echo "Status text: " & req.statustext
   wscript.echo "Response text: " & req.responsetext
End If

End Sub

function Collabblobget()

xmlreqtxt = "<?xml version='1.0'?><a:propfind xmlns:a='DAV:' xmlns:cp='" & SourceURL & "'><a:prop><cp:collblob/></a:prop></a:propfind>" "PROPFIND", DestinURL, false, "", ""
req.setRequestHeader "Content-Type", "text/xml; charset=""UTF-8"""
req.setRequestHeader "Depth", "0"
req.setRequestHeader "Translate", "f"
req.send xmlreqtxt
set oResponseDoc = req.responseXML
set oCobNode = oResponseDoc.getElementsByTagName("d:collblob")
For i1 = 0 To (oCobNode.length -1)
   set oNode = oCobNode.nextNode
   Collabblobget = oNode.Text   

End function

Sub Collabblobset(colblob)
xmlstr = "<?xml version=""1.0""?>" _
& "<g:propertyupdate " _
& "    xmlns:g=""DAV:"" xmlns:e=""""" _ 
& "    xmlns:dt=""urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"" " _
& "    xmlns:cp=""" & SourceURL & """ " _
& "    xmlns:header=""urn:schemas:mailheader:"" " _
& "    xmlns:mail=""urn:schemas:httpmail:"">  " _
& "    <g:set>  " _
& "        <g:prop>  " _
& "            <cp:collblob>" & colblob & "</cp:collblob>  " _
& "        </g:prop>  " _
& "    </g:set>  " _ 
& "</g:propertyupdate>" "PROPPATCH", DestinURL, False
req.setRequestHeader "Content-Type", "text/xml;"
req.setRequestHeader "Translate", "f"
req.setRequestHeader "Content-Length:", Len(xmlstr)

end sub

Sub CopyApt(messageEntryID,ReplID)
set objapt = CDOSession.GetMessage(messageEntryID)
set objCopyapt = objapt.copyto(cfCalendarFolder.EntryID)
objCopyapt.Unread = false
objCopyapt.Fields.Add "0x8542", vbString, ReplID,"0820060000000000C000000000000046"
Set objCopyapt = Nothing
wscript.echo objapt.subject

end Sub

Sub CopyContact(messageEntryID,ReplID)
set objcontact = objSession.getmessage(messageEntryID)
set objCopyContact = objcontact.copyto(pfPublicFolderID,objpubstore.ID)
objCopyContact.Unread = false
objCopyContact.Fields.Add "0x8542", vbString, ReplID,"0820060000000000C000000000000046"
Set objCopyContact = Nothing
wscript.echo objcontact.subject

end Sub

Sub DeleteContact(replUID)

strQuery = "<?xml version=""1.0""?><D:searchrequest xmlns:D = ""DAV:"">"
strQuery = strQuery & "<D:sql>SELECT ""DAV:Displayname"""
strQuery = strQuery & " FROM scope('shallow traversal of """
strQuery = strQuery & DestinURL & """') Where ""{00062008-0000-0000-C000-000000000046}/0x8542"" = '" & replUID & "' AND ""DAV:isfolder"" = False "
strQuery = strQuery & "</D:sql></D:searchrequest>" "SEARCH", DestinURL, false
req.setrequestheader "Content-Type", "text/xml"
req.setRequestHeader "Translate","f"
req.send strQuery
wscript.echo req.responsetext
If req.status >= 500 Then
   wscript.echo "Status: " & req.status
   wscript.echo "Status text: An error occurred on the server."
ElseIf req.status = 207 Then
   wscript.echo "Status: " & req.status
   wscript.echo "Status text:  " & req.statustext
   set oResponseDoc = req.responseXML
   set oNodeList = oResponseDoc.getElementsByTagName("a:href")
   For i = 0 To (oNodeList.length -1)
    set oNode = oNodeList.nextNode
    wscript.echo oNode.text "DELETE", oNode.text, false
    wscript.echo "Status: " & req.status
   wscript.echo "Status: " & req.status
   wscript.echo "Status text: " & req.statustext
   wscript.echo "Response text: " & req.responsetext
End If

end Sub

Function Octenttohex(OctenArry)  
  ReDim aOut(UBound(OctenArry)) 
  For i = 1 to UBound(OctenArry) + 1 
    if len(hex(ascb(midb(OctenArry,i,1)))) = 1 then 
        aOut(i-1) = "0" & hex(ascb(midb(OctenArry,i,1)))
    aOut(i-1) = hex(ascb(midb(OctenArry,i,1)))
    end if
  Octenttohex = join(aOUt,"")
End Function

I can't remember where I found the initial script, but I will post if I find it. I think this one will only work on Exchange 2003. Also, for this to work properly, the user must have the folder to copy already in the correct place (but empty).

share|improve this answer
I'll try this out and see if it works. This might do the trick. – Dayton Brown Jul 16 '09 at 19:11
You only should need to edit some of the parameters at the beginning. Please forgive the messiness, this script sort of evolved over time and has not been reworked for distribution. Some parameters to edit: exchange server name, user to copy from, text file of users to copy to, the text file must have 1 username per line, and do a find/replace for "folder to copy". – moshen Jul 16 '09 at 19:17

You could have somebody code up a script to copy all of the contacts from a public folder (CSV file, etc) into a "Contacts" folder in each user's mailbox as one possible method. (A script that accesses the mailboxes through WebDAV would be fairly easy to do this with.) I'm not aware of an off-the-shelf product that does that.

If you don't want to go to that level of work, consider putting the contacts into a public folder and either asking the users to mark it a "Favorite" or asking them to copy the contacts into their mailboxes. Obviously, this isn't a "push".

share|improve this answer
Option #1 might be the best solution. I'm trying to figure out if I really want to go to those lengths though. – Dayton Brown Jul 15 '09 at 17:39

What about just emailing the contacts to the users? I guess they would probably need to add them using Outlook, but it seems like it would be pretty easy to just email them to the users.

share|improve this answer
In a normal environment that is exactly what I would do. Unfortunately, these users are mostly mobile, mostly non-technical, and need extreme assistance levels. Just trying to make it as easy as possible for them. – Dayton Brown Jul 16 '09 at 13:38
Ahh, my favorite kind. – Russ Warren Jul 16 '09 at 14:01

I don't know if this is one would apply to your problem but you could set up a eGroupware system.

This is free and open source. You can sync it with a lot of diffrent mobile phones and of course with any outlook or exchange. You then have to sync your system with the installation to get your contact online. Then every user needs to configure a client for syncing. As mentioned there are a lot of different plugins for mobile phones.

All contacts then get pushed to your clients phones. You can group them and set global permissions. Maybe this would help. But be warned, it's still hard to get eGroupware running and set up correctly.

share|improve this answer

Don't push them out, share them...

I found this article that has a decent explanation of how to share contacts through a Public Folder. And this other article with a little more information, plus more on what can be done with public folders.

Once it is setup works great.

share|improve this answer

protected by Michael Hampton Jan 12 '14 at 1:33

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.