views:

1983

answers:

2

I'm trying to rename a user programically and can't figure out the mailbox piece(proxyAddresses). Any help is appreciated...

Working code below...

Public Shared Function renameUser(ByVal curUsername As String, ByVal newUsername As String) As Boolean
    Dim emailSuffix As String = "@here.com"
    Dim userPrincipalSuffix As String = "@here.now"

    Dim user As New DirectoryEntry
    Dim oSearcher As DirectorySearcher = Nothing
    Dim oRoot As DirectoryEntry = Nothing
    Dim oResult As SearchResult
    Try
        oRoot = New DirectoryEntry("LDAP://" & "ldapserver" & _
                  "/" & "OU=OUWithUsersToChange,OU=Site Users,DC=here,DC=now")
        oSearcher = New DirectorySearcher(oRoot)
        oSearcher.SearchScope = SearchScope.Subtree

        oSearcher.Filter = "(&(objectCategory=person)(sAMAccountName=" & curUsername & "))"
        oSearcher.PropertiesToLoad.Add("uid")
        oSearcher.PropertiesToLoad.Add("mail")
        oSearcher.PropertiesToLoad.Add("mailNickname")
        oSearcher.PropertiesToLoad.Add("userPrincipalName")
        oSearcher.PropertiesToLoad.Add("sAMAccountName")
        oSearcher.PropertiesToLoad.Add("proxyAddresses")
        oSearcher.PropertiesToLoad.Add("textEncodedORAddress")
        oSearcher.PropertiesToLoad.Add("legacyExchangeDN")

        oResult = oSearcher.FindOne
        user = oResult.GetDirectoryEntry

        Dim lNewList As New List(Of String)
        For Each sAddress As String In user.Properties("proxyAddresses")
            lNewList.Add(sAddress.Replace(curUsername, newUsername))
        Next
        Dim sTextEncodedORAddress As String = user.Properties.Item("textEncodedORAddress").Value
        Dim sLegacyExchangeDN As String = user.Properties.Item("legacyExchangeDN").Value

        user.Properties.Item("uid").Value = newUsername
        user.Properties.Item("mail").Value = newUsername & emailSuffix
        user.Properties.Item("mailNickname").Value = newUsername
        user.Properties.Item("userPrincipalName").Value = newUsername & userPrincipalSuffix
        user.Properties.Item("sAMAccountName").Value = newUsername
        user.Properties("proxyAddresses").Value = lNewList.ToArray
        user.Properties.Item("textEncodedORAddress").Value = sTextEncodedORAddress.Replace(curUsername, newUsername)
        user.Properties.Item("legacyExchangeDN").Value = sLegacyExchangeDN.Replace(curUsername, newUsername)

        user.CommitChanges()
        user.Rename("CN=" & newUsername)

        Return True
    Catch ex As Exception
        Return False
    Finally
        user.Dispose()
        oRoot.Dispose()
        oSearcher.Dispose()
        oResult = Nothing
    End Try
End Function
+1  A: 

If I remember correctly, proxyAddresses is actually an array, not a single value. It is also prefixed with information about the kind of address it is...

Warning: Ugly code ahead!

This is some code that I had used before so change the primary e-mail address for user accounts and keep previous addresses (as in switching primary domain names). This might help you make your changes

Dim lNewList As New List(Of String)
sPrimaryAddress = sPrimaryAddress.Split("@")(0) & "@" & "example.com"
lNewList.Add("SMTP:" & sPrimaryAddress)
For Each sAddr As String In lPrevList
    lNewList.Add(sAddr) 'which will be a list of values like "smtp:[email protected]"'
Next

Dim oUser As DirectoryEntry = oResult.GetDirectoryEntry()
oUser.Properties("mail").Value = sPrimaryAddress
oUser.Properties("ProxyAddresses").Value = lNewList.ToArray()
oUser.CommitChanges()

lPrevList was a list of the e-mail addresses the user already had attached to their profile. Their primary address starts with SMTP: while the others start with smtp: (lowercase). You might run unto other values like x400, etc..

Make sure you treat each value with care. You do not want to write a script and then run it across your domain and blow up all the accounts

Hugoware
Correct in that it is an array, I have thought about using the add method but was hoping I was missing a simple rename method (like when renaming cn). I'll test out the following adding in the code to delete the old smtp/x400 addresses and post back if it works. Thanks....While browsing the user LDAP parameters with adsiedit I noticed two others that should be changed (don't have info on hand, will repost). Would love a simple rename method, if nothing is native to .Net I'll repost what I come up with.
Your code worked great, final code is above. I had to also change legacyExchangeDN and textEncodedORAddress.
A: 

If you're using the .Net Framework 3.5 or better, you're probably better off using System.DirectoryServices.AccountManagement. That makes it a matter of getting the correct UserPrinciple, altering the Name property, and calling the Save method. It might look something like this:

Dim pc As New PrincipalContext(ContextType.Domain, "COMPANY")
Dim up As UserPrincipal = UserPrincipal.FindByIdentity(pc, curUsername)
up.Name = newUsername
up.Save
Jacob Proffitt
Thanks I'll give this a shot. If it does what the above is doing with System.DirectoryServices then I think this will be great. I ran into some problems with DS.AccountManagement where it only enumerated enabled users and I couldn't figure out how to limit queries between current OU and sub OUs so I stayed away from it on this task. Thanks again.
Sure. Hope it works out. I haven't had the same need so I can only vouch that it *should* according to the documentation.
Jacob Proffitt