Skip to main content
E14 Exchange Uber-Geek

Mark E. Smith's Brain Dump

Go Search
Home
Capax Global Blogs
Public Document Library
  

Mark E. Smith's Brain Dump > Categories
How Microsoft IT Deployed Exchange Server 2010
Exchange Server 2010 Design and Architecture at Microsoft
 
 
Directly converting a mail-user to a mailbox without calling disable-mailuser.

 

Background:

Environment:

Appox 200,000 user objects in Lotus Notes Address Book (NAB)

Exchange 2007 SP1 running on Windows 2008 Server.

Exchange and OCS are installed in a Resource Forest (2003 forest mode)

Users authenticate into a Windows 2000 AD User forest (2000 forest mode).

Lotus Notes 6.5

ILM MA’s connecting (AD MA) Exchange Resource Forest, (AD MA) User Forest, (Domino MA) Lotus Notes NAB.

 

Domino Mailbox users are provisioned as Disabled Mail User objects in the Exchange Resource Forest rather than a contact object.

 

Issue:

We ran into a challenge of being able to provision a large amount of mailboxes in a short amount of time. Additionally the large changes to the GAL were concerning me with regard to wide spread OAB downloads.

 

Solution:

Rather than using the traditional approach of using a contact forwarding to a notes mailbox, then upon migration, provisioning the mailbox, deleting the contact and copying the legacyExchangeDN from the contact and stamping it as an X.500 on the mailbox, this approach uses a mail-user object as the “contact” forwarding to the notes mailbox. We then surgically replace the key attributes in the directory to convert a mail-user to a mailbox user WITHOUT changing its representation in the GAL/OAB e.g. legacyExchangeDN never changes.

 

Caveat:

The only issue with this approach is that it effectively removes the ability to stage mail in the mailbox prior to the date of the actual user being migrated.

 

Roll-Forward

1.  Clear targetAddress on the mail enabled user object.

2.  Set homeMDB on the mail enabled user object.

3.  Set msExchRecipientTypeDetails = 2 (see http://marksmith.netrends.com/Lists/Posts/ViewPost.aspx?ID=51 for more details on different mailbox types)

4.  Set msExchMasterAccountSid = {SID of User Forest user object}

a.  $LinkedAccountSID = ((new-object System.Security.Principal.NTAccount($UserForestAccount)).Translate([System.Security.Principal.SecurityIdentifier])).Value

b.  ILM can flow the binary value of the User Forest object’s SID in the metaverse into this property.

5.  Call powershell update-recipient {resource forest mailbox name}.

6.  Call powershell Add-Mailboxpermission {resource forest mailbox name} -User [UserDomain]\[UserID] -AccessRights FullAccess,ExternalAccount

7.  Call powershell Add-AdPermission {resource forest mailbox name} -User [UserDomain]\[UserID] -ExtendedRights Send-As

 

Roll-Back

1.  Call powershell Remove-AdPermission {resource forest mailbox name} –User [UserDomain]\[UserID] –ExtendedRights Send-As (if using linked mailbox)

2.  Call powershell Remove-Mailboxpermission {resource forest mailbox name} –User [UserDomain]\[UserID] –AccessRights FullAccess,ExternalAccount (if using linked mailbox)

3.  Clear the following attributes:

a.  homeMDB

b.  homeMTA

c.  msExchangeHomeServerName

d.  msExchangeMailboxGuid

e.  msExchMasterAccountSid (if using resource forest/linked mailbox)

f.  msExchPoliciesIncluded

g.  msExchPoliciesExcluded

                        i.   IMPORTANT: If you are not using Exchange Address Policies, {26491CFC-9E50-4857-861B-0CB8DF22B5D7} Should not be removed.

h.  msExchRecipientTypeDetails

i.  We might need to add some additional attributes if other policies are included or excluded e.g. Activesync, etc.

j.  msExchVersion

k.  msExchUserAccountControl

l.  msExchRecipientDisplayType

m.  msExchMailboxSecurityDescriptor

4.  set targetAddress = mail attribute (this should be the Notes internetAddress)

5.  call powershell update-recipient {resource forest mailbox name}

 

 

References:

http://support.microsoft.com/kb/275636

 

 

Reasoning:

The big benefit I see to this approach over the traditional migration/coexistence approach (contact object points to Notes person doc, delete contact, mailbox enable user, flow attributes from one to the other) are the following:

1.       Eliminates a number of complexities in the ILM implementation (having to manage a contact object and user object, attribute flow from one to the other, etc).

2.       Much faster provisioning of mailboxes (In my tests, I was able to do about 20,000 in 3 mins).

3.       OAB download issues. Flipping the contact object to a mailbox will result in changes to the OAB:

a.       “In pre-OAB v4 versions of the offline address book, Outlook uses a default threshold of one-eighth to determine when to not perform a differential offline address book download and instead perform a full offline address book download. If you are using Outlook 2003 SP2 and OAB v4 [OR OUTLOOK 2007], this threshold has been increased to 50 percent.”

b.      “The offline address book differential file contains an entire user record even if the changes to the record are small. For example, if the only change is the office location, the entire record including the certificates is added to the differential offline address book.”

c.       “Outlook calculates a percentage ratio of the total size of all the compressed differential offline address book files on the server to the current total size of the compressed full offline address book on the server. If the percentage ratio exceeds the threshold value, Outlook performs a full download instead of downloading the differentials.”

http://technet.microsoft.com/en-us/library/aa996241(EXCHG.65).aspx

 

This approach would mean zero OAB differential changes because we’re not adding/deleting any objects from the OAB and we’re not modifying any attributes contained within the existing objects in the OAB. For example, when we convert “John Doe” mail user to “John Doe” linked mailbox, that attributes that are updated (homeMDB, homeMTA, etc.) aren’t attributes included in the OAB.

 

The net results would be a big savings in the timing of OAB generation, CAS replication, download, and thus network traffic when we provision mailboxes.

 

Conceptual Testing (convert to mailbox user rather than linked mailbox user):

makeMailUsers.ps1 creates 20,000 mail users in a given OU.

flipMailUserToMB.ps1 flips the user object from mail user to mailbox user.

 

flipMailUsertoMB.ps1  provisions a list of users from mail users to mailboxes

 

POWERSHELL SCRIPT:  makeMailUsers.ps1

Edit the –OrganizationalUnit value to the domain and OU where the test users will be created.

When prompted for credentials, enter any username, and the password you would like to assign to the 20,000 user objects.

 

$password = get-credential

$top = 20

$ou = "domain.local/Clients/NETrends Systems/Notes DirSync/MigTest"

for ($i = 1;$i -le $top; $i++){

                $name = "DUser$i"

                $upn ="DUser$i@netrends.com"

                $targetAddress = "SMTP:$name@notes.domain.com"

                New-MailUser -Name $name -Alias $name -OrganizationalUnit "$ou" -UserPrincipalName $upn -SamAccountName $name -FirstName 'Mail' -LastName $name -Password $password.password -ExternalEmailAddress $targetAddress

}

 

POWERSHELL SCRIPT:  flipMailUsertoMB.ps1

Edit the $homeMDB variable to the DN of a mailbox database in your environment.

Edit the $ou variable to the OU you created your 20,000 mail users in makeMailUsers.ps1

 

# FQDN of GC

$gc = "GC01.domain.local"

 

# $migusers imports the csv file. Edit the filename/path in this line if necessary

$migUsers = Import-Csv .\migrationusers.csv

$curDir = get-location

 

# begin loop of users

foreach ($line in $migUsers) {

                # get the homeMDB value from the CSV file

                $homeMDB = $line.homeMDB

                # use the user object based off of the username in the csv file

                $migUser = Get-User $line.userName

                # get the AD DN of the user object

                $userDn = $migUser.DistinguishedName

                # create the ldap query

                $ldp = "LDAP://" + "$gc" + ":389/" + $userDn

                # set an ADSI object that we can edit

                $user = [ADSI]"$ldp"

                # clear the target address

                $user.putex(1, "targetAddress", 0)

                $user.setinfo()

                # set the recipient type to mailbox (note use 2 for linked mailbox and add the sid for the msexchange linked master sid in a resource forest mode)

                $user.put("msExchRecipientTypeDetails", "1")

                $user.setinfo()

                # set homeMDB

                $user.put("homeMDB", "$homeMDB")

                $user.setinfo()

 

                # call update-recipient (RUS) so exchange will stampt the missing attributes and make the user a mail-user again.

                update-recipient -identity "$userDN" -domainController "$gc"

 

                # this loop checks the status of the user object.

                # prior to RU4 there was a bug in update-recipient where the -domaincontroller argument value was not used for both the DC and GC

                # this loop runs update-recipient waits 3 seconds, if the user is still a mail user it will re-run. If it's a mailbox then it will exit.

                get-user "$userDN" -domaincontroller "$gc" > tempfile2007.txt

                [string]$userStatus = get-content tempfile2007.txt

                $counter = 0

                While ($userStatus.contains("MailUser") -AND $counter -lt 20)

                                {

                                update-recipient -identity "$userDN" -domainController "$gc"

                                if ($counter -gt 0) {start-sleep 3}

                                get-user "$userDN" -domaincontroller "$gc" > tempfile2007.txt

                                [string]$userStatus = get-content tempfile2007.txt

                                $counter = $counter + 1

                                }

                if ($counter -lt 20) {write-host "Mailbox Provisioned in: " + $counter + " update-recipient calls" + chr(10) + chr(13)}        

}}

 

Transporter KB 324705 still applies to Exchange 07 and Transporter Suite
According to Microsoft internal sources,
 
 
Still applied to Exchange 2007 and MS Transporter Suite.
Also, the link to the IBM site does not exist anymore. The text of the link is here:
 

Chapter 0-3

Known Problems, Corrections, and Additions





Introduction

This chapter lists known problems and last-minute corrections and additions.


All Platforms

The following problems exist in Lotus Notes/Domino 6.5 for all platforms. These problems are visible during C API function calls. They are not problems with the Lotus C API Toolkit for Domino and Notes itself but with the underlying Domino and Notes core routines that implement C API functions.

Future releases of Domino and Notes may fix these problems. When they are fixed (and you install the new version of Domino or Notes) your C API programs will automatically receive the fixes. You will not have to recompile your C API applications, since C API programs link to the Domino or Notes core routines at run time.

The known problems with the C API on all platforms are:

    CompoundTextAssimilateItem
    This function does not handle features of rich text that depend on special items that reside outside the rich text field specified by the "pszItemName" parameter.

    Two such features of rich text include doc links that depend on the special $Links item, and font faces that depend on the special $Fonts item. These special items in the note reside outside the specified rich text field. Therefore, when CompoundTextAssimilateItem merges a rich text field containing doc links consisting of CDLINK2 records into a Compound Text context, the doc link in the resulting compound text does not function. A work-around to this problem is demonstrated by sample program HISTORY in the RICHTEXT directory.

    Also, when CompoundTextAssimilateItem merges a rich text field containing font faces that require a font table (a $Fonts item in the note) the resulting compound text does not reflect the font face used in the original field.

    SMTP Extension Managers
    In the extension manager callback routine, SMTPCommandEMCallback, you can reject the command for the SMTPConnect event with a return STATUS value other than ERR_EM_CONTINUE and NOERROR from the EM_BEFORE notification. When you reject the MAIL command, the server prevents the client from sending mail. However, the SMTP server allows intervening commands to succeed, such as VRFY and EXPN, when it should not. This issue will be addressed in a future release.

    Note Creation Time in web.nsf
    The "Note" field in the ORIGINATORID structure for notes created in the InterNotes database web.nsf does not contain the creation date and time for the note. This database stores information about Universal Reference Locators (URLs) for Web documents. Instead, this field contains a hash key based on the URL. Applications should first check a note for the existence of the item $CREATED. If this item exists, it contains the date and time the note was created. If this item does not exist, the "Note" field of the ORIGINATORID structure contains the date and time the note was created.

    1-2-3 File Import
    Character-mode C API programs cannot use the iwske import library included with Notes to import a Lotus 1-2-3 worksheet into Notes. The import function in this DLL returns error code 0x9D0E, which is STS_DISPLAYED | PKG_IMPORT | ERR_IWKSE_USER_ABORT. The function returns this error because it cannot display a dialog box asking the user if a range or the whole file is being imported.

    FTSearch
    Using FTSearch with the multiple database search option will not work correctly if the program is not in the Domino or Notes executable directory.

    CDEVENTENTRY
    The possible values for the wActionType member of the CDEVENTENTRY structure have not been exposed in the Lotus C API Toolkit for Notes/Domino. Also, all possible values for the wEventId member have not been exposed. The values will be exposed in a future release.

    NSFNoteCopyAndEncrypt
    Calling NSFNoteCopyAndEncrypt with ENCRYPT_SMIME_IF_MIME_PRESENT may not correctly encrypt the message.
Windows 32-bit

    Compatibility Issues
MS Windows applications that were built with a 5.0.x release of the Lotus C API Toolkit for Domino and Notes and call any one of the following functions:
      • SECHashPassword
      • SECVerifyPassword
      • NSFHotSpotSign
      • StoredFormAddItems
      • StoredFormRemoveItems
    will not run on Notes and Domino 6 due to discrepancies with the ordinal values defined for these functions. This problem has been fixed in Notes and Domino 6.0.1 and later releases. MS Windows applications that were built with a 5.0.x release of the Lotus C API Toolkit for Domino and Notes and call the functions listed above will run on Notes and Domino 6.0.1 and later releases. MS Windows applications that were built with the Lotus C API Toolkit for Notes/Domino 6 and call one of the functions listed above will also run on later releases of Notes and Domino.

    MS Windows applications that were built with the Lotus C API Toolkit for Notes/Domino 6 and call the function, NSFDbOpenTemplate, will not be able to run on Notes/Domino 6.0.1 and later releases. You will need to recompile these applications with the Lotus C API Toolkit for Notes/Domino 6 .0.1.

    Windows NT Services
    Lotus C API applications for Domino and Notes can be run as a Windows NT Service. A system environment variable, NOTESNTSERVICE=1, must be set before running a C API application as a Windows NT Service. If this environment variable is not set, calls to the Domino or Notes C API which require any user authentication (for example, NSFDbOpen()) made after the user starting the service logs off will fail. For more information on Windows NT Services, please refer to the Microsoft Win32 documentation.


Unix
    AIX: Increased private memory data space available.
    The available memory, for use by API applications, has been increased in Domino release R5.0.9. An API application run on Domino R5.0.9 or greater but built under a release previous to R5.0.9 may yield the following error:
      "The process [API app name] is unable to map the required amount of shared memory. Please refer to the documentation to correct this."

    The Domino utility "dataseg" will examine your API applications and make recommendations.


      dataseg -s (sets to our default)

      dataseg -s * (checks all apps; you can supply namelist)


    * This will change only 32-bit AIX executables and change only the data segment.

    See the Release Notes: Domino/Notes database that is included in the Domino or Notes installation for further information.


    Linux Red Hat, Linux for zSeries and the gets(..) function.
    Please be advised there is a known bug in the function gets(..) under Linux Red Hat. Linux Red Hat recommends using fgets(..) instead. Our samples which use gets(..) will compile with a warning concerning the bug in gets(..). At this point in time we have not run into any problems with our samples that use the gets(..)function. We anticipate the bug to gets(..) will be resolved in a newer version of Linux Red Hat.



Sample Programs

    Chapter 2-3 of this User Guide lists the sample programs included in this toolkit and the planned supported platforms.

    tracker
      Tracker should be removed from the notes.ini file before returning to normal use of Domino or Notes.

      Tracker does not check the OpenFlags parameter for the OPEN_CANONICAL flag in its TrackerNoteOpen routine. Tracker assumes that the entire note has not been opened with the OPEN_CANONICAL flag. This assumption is true as long as the note's item information is not transmitted over a network. If a database hook driver accesses a note's item over a network, it should check the OPEN-CANONICAL flag in its NoteOpen routine and, if set, use ODSReadMemory to convert any canonical data to host data.
    ragents
      Currently when attempting to execute a Java Agent using the Lotus C API for Domino and Notes, Java console errors are displayed. For this reason the ragents sample has not been enhanced to include execution of the Java Agent. Instead, the Java Agent is executed manually from the Notes UI.
    ftsearch
      Be sure to check for 0 in the parameter retNumDocs (i.e. no document returned) after calling the FTSearch API. When there is no document returned, the value of the parameter rethResults will be NULLHANDLE, and trying to do OSLock on a NULLHANDLE will cause a crash.
    sel_rep, namelook, uiaddin, iedit, xedit, and xview
      These samples require a Notes client and are not supported on server-only platforms (UNIX).
    backup
      The "dbrecs" sample may fail when run with the "RECOVER" option and given a root directory as an input file (i.e. "dbrecs RECOVER e:\").
----------------------------------------------------------------------------------------------------------