Wednesday, March 2, 2011

Exchange Server 2007: Bulk creation of mailboxes using Exchange Management Shell

Bulk creation of mailboxes (and the accompanying user accounts) in Exchange Server 2003/2000 involved some elaborate scripting effort. This task can now be done fairly effortlessly, thanks to the Exchange Management Shell (EMS). The Shell can very easily import/use CSV files saved from a spreadsheet or text editor and create the mailbox-enabled users. Here’s how.

Step 1 Create a spreadsheet

Create a spreadsheet (you can also use a standard text editor such as Notepad to create a CSV file) with the following columns. You can add more fields if you wish:
Alias,Name,UPN
Add data for new accounts in following lines/rows. Here’s what it’ll look like:
Alias,Name,UPN
User_One,User One,userone@yourUPNsuffix.com
User_Two,User Two,usertwo@yourUPNsuffix.com
User_Three,User Three,userthree@yourUPNsuffix.com
Save the file as CSV – let’s call it CreateRecipients.csv

Step 2 Enter a password

Now fire up the Shell (EMS) and issue the following command:
$Password=Read-Host “Enter Password” -AsSecureString
This will prompt you for a password. The same password will be used as the initial password for all your mailbox-enabled users.

Step 3 Import the CSV and create mailboxes

Next, issue the following command to import the CSV file and create the user accounts and mailboxes:
Import-CSV CreateRecipients.csv | ForEach {New-Mailbox -Alias $_.alias -Name $_.name -userPrincipalName $_.UPN -Database “Mailbox Database” -OrganizationalUnit Users -Password $Password}

How the Shell interprets the command

Here’s how the shell interprets the above command:
  • Import-csv CreateRecipeints.csv gets data from the CSV file.
    If you’re providing the complete path with spaces, you must enclose it in quotes. For example: “c:\My Scripts\CreateRecipients.csv”.
    - If you’re not running the command from the same directory (folder) where the CSV file is located, you will need to provide the complete path to the file.
  • - The | pipes the data from the CSV to the next command.
  • - foreach parses through each line in your CSV file, using the first row as a header. All the column headings/names get treated as field names.
  • - The New-Mailbox command, as you may already know by now, creates a new mailbox-enabled user.
  • - For each variable, you either enter a value at the command line (for instance, we’re using the value “Mailbox Database” for the Store), or you can pick up the value from your CSV file provided you have a column for it with a heading. For instance, for the -alias field, we use $_.alias – which tells the script to look for the column called alias in your CSV file and pick up the value from the current row or line.
    If you’re running the command on the same server where you want to create the mailboxes, you can simply use the Store name, e.g. “Mailbox Store”. To create mailboxes on another server’s Store(s), you can use either ServerName\Store, or ServerName\StorageGroup\Store, or even the GUID of the Store. How do you get those??? Use the Get-MailboxDatabase cmdlet.
  • - The -OrganizationalUnit field stands for (Active Directory) OU (or Container) you want to create the accounts in. If all the accounts you create from the CSV file will reside in the same container or OU, you can provide this at the command-line, as we did in the example above. Alternatively, you can include the OU/Container name in your spreadsheet/CSV file in a field – let’s say OU – and modify your command to say: -org $_.OU
    Note: Luckily you do not need to provide the distinguishedName of the OU or Container – simply the name of the OU or Container works.
  • - The -password field picks up the password from the variable called $password that we created earlier.
The New-Mailbox cmdlet allows you to enter a lot of attributes for each mailbox-enabled user. These are documented in the New-Mailbox cmdlet reference docs (Exchange 2007 | Exchange 2010), and also in the Exchange 2007/2010 online help. For each attribute you want to populate, add it to your spreadsheet/CSV file.

To create new mailboxes with settings based on an existing mailbox, use the TemplateInstance parameter, as shown in the following commands:
$Template = Get-Mailbox “Template Mailbox”
Import-CSV CreateRecipients.csv | foreach {new-mailbox -alias $_.alias -name $_.name -userPrincipalName $_.UPN -database “Mailbox Database” -org Users -Password $Password -templateinstance $Template}

NOTE: The TemplateInstance parameter is not supported in Exchange 2010

Reference:

http://exchangepedia.com/2006/11/exchange-server-2007-bulk-creation-of-mailboxes-using-exchange-management-shell.html

Adding Users to Sharepoint

Adding Users from Active-Directory into Sharepoint is done in 2 steps. First we will need to Get the information required from Active-Directory and then we need to Add the informtaion into Sharepoint.
Lets start with Active-Directory. Below is an image of the Active-Directory Design in this example:
active-directory-01
Since we want to Get the User information we need to connect to the correct OU through ADSI. The Connection string to the User OU that we want to access would look like this
LDAP://OU=Site1 Users,OU=Site1,OU=Sites,DC=BPA,DC=CORP
Here’s how to connect to the OU through PowerShell:
PS > $ConnectionString = "LDAP://OU=Site1 Users,OU=Site1,OU=Sites,DC=BPA,DC=CORP"
PS > $AD = [adsi]$ConnectionString
PS > $AD
distinguishedName
-----------------
{OU=Site1 Users,OU=Site1,OU=Sites,DC=bpa,DC=corp}
This shows that we have connected to the correct OU. To retrieve information about the Users in the OU we have to access the children within the object.
PS > $AD.PsBase.Children
distinguishedName
-----------------
{CN=user1,OU=Site1 Users,OU=Site1,OU=Sites,DC=bpa,DC=corp}
{CN=user2,OU=Site1 Users,OU=Site1,OU=Sites,DC=bpa,DC=corp}
{CN=user3,OU=Site1 Users,OU=Site1,OU=Sites,DC=bpa,DC=corp}
{CN=User4,OU=Site1 Users,OU=Site1,OU=Sites,DC=bpa,DC=corp}
Now that we have all the Users in the OU we can start collecting the information. But first let’s check what we need. The User items in WSS 3.0 have a couple of settable values and not all values are available Properties in Active-Directory.
sharepoint-05
Sharepoint actually looks up Department and Job Title if they exist in Active-Directory so we dont have to bother about that. What we do need is the Users loginname, mail and name.
To retrieve the information, we will create a filter that takes the information from Active-Directory.
PS > filter UserProperties {
     $_ | select @{ name='sAMAccountName'; Expression={$_.sAMAccountName} },
     @{ name='mail'; Expression={$_.mail} },
     @{ name='displayName'; Expression={$_.displayName} }
 }
Next we will run through all Child objects in the OU and filter them into a new Custom Object.
PS > $User = $AD.PsBase.Children | UserProperties
PS > $User
sAMAccountName                          mail                                    displayName
--------------                          ----                                    -----------
user1                                   user1@mail.com                          user1
user2                                   user2@mail.com                          user2
user3                                   user3@mail.com                          user3
user4                                   user4@mail.com                          User4
Now that we have the User information stored in a PowerShell object, we can use it to create the users in Sharepoint. When adding users to Sharepoint, we have to consider which Role ther Users should have. there are a few available roles to choose from. We can get a list of all roles through the Roles Property.

ps > [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

PS > $SPSite = New-Object Microsoft.SharePoint.SPSite("http://wss"); $OpenWeb = $SpSite.OpenWeb(); $OpenWeb.Roles | Select Name, Description; $OpenWeb.Dispose(); $SPSite.Dispose()


Name                                                        Description
----                                                        -----------
Full Control                                                Has full control.
Design                                                      Can view, add, update, delete, approve...
Contribute                                                  Can view, add, update, and delete.
Read                                                        Can view only.
Limited Access                                              Can view specific lists, document libraries...
In this example, we will use the Read Role. To add the users to Sharepoint we use a function.


function Add-SPUser([string]$url, [string]$Role, [string]$Domain, [string]$sAMAccountName, [string]$Mail, [string]$DisplayName) {

  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

  $SPSite = New-Object Microsoft.SharePoint.SPSite($url);
  $OpenWeb = $SpSite.OpenWeb(); $OpenWeb.Roles | Select Name, Description; $OpenWeb.Dispose(); $SPSite.Dispose()

  $OpenWeb.Roles[$Role].AddUser(
    $Domain + $sAMAccountName,
    $Mail,
    $DisplayName,
    ""
  )
  $OpenWeb.Dispose()
  $SPSite.Dispose()
}

PS > $User | foreach-object {
  Add-SPUser -url http://wss -Role Read -Domain bpa -sAMAccountName $_.sAMAccountName -Mail $_.Mail -DisplayName $_.DisplayName
}

Now the users are added to Sharepoint. Note that Job Title and Department are added automatically, if the values exist in Active-Directory.
sharepoint-06

Reference:
http://www.powershell.nu/2009/01/06/adding-users-to-sharepoint/

Tuesday, March 1, 2011

Exchange and Autodiscover

Using the Exchange Management Console you configure the Client Access Server, or you use the Exchange Management Shell using the following commands.

Set-OWAVirtualDirectory –Identity ServerName\OWA (default web site) -ExternalURL https://webmail.inframan.nl/OWA

Set-OABVirtualDirectory –Identity ServerName\OAB (default web site) -ExternalURL https://webmail.inframan.nl/OAB

Set-WebServicesVirtualDirectory –Identity ServerName\EWS (default web site) -ExternalURL https://webmail.inframan.nl/ews/exchange.asmx

Set-ActiveSyncVirtualDirectory –Identity X2007SRV\Microsoft-Server-ActiveSync (default web site) -ExternalURL https://webmail.inframan.nl/Microsoft-Server-ActiveSync

If you are running Exchange Server 2010, this setting is needed as well:

Set-ECPVirtualDirectory –Identity 2010CAS\ECP (default web site) -ExternalURLhttps://webmail.inframan.nl/EC


Reference:
http://www.msexchange.org/articles_tutorials/exchange-server-2010/management-administration/exchange-autodiscover-part2.html
Now these are for the External URL. When Outlook connects to the Client Access Server it determines whether it is an internal or an external connection. So we also have to configure the internalURL property.

By default the internalURL is configured with the local servername, like https://ServerName.e2010.local/OAB, for example.

This is caused by the fact that the internal server name is returned from the SCP. The Outlook client tries to access this internal servername using HTTPS (remember it is a web service after all) but the internal name is not in the certificate.

You can solve this by changing the internalURL property with the value of the externalURL. You can do this using the Exchange Management Console and changing the properties of the Client Access Server:


You can also use the Exchange Management Shell to change these settings by entering the following commands:

Set-OWAVirtualDirectory –Identity X2007SRV\OWA (default web site) -InternalURL https://webmail.inframan.nl/OWA

Set-OABVirtualDirectory –Identity X2007SRV\OAB (default web site) -InternalURL https://webmail.inframan.nl/OAB

Set-WebServicesVirtualDirectory –Identity X2007SRV\EWS (default web site) -InternalURL https://webmail.inframan.nl/ews/exchange.asmx

Set-ActiveSyncVirtualDirectory –Identity X2007SRV\Microsoft-Server-ActiveSync (default web site) -InternalURL https://webmail.inframan.nl/Microsoft-Server-ActiveSync

And again, this setting is only valid for Exchange Server 2010:

Set-ECPVirtualDirectory –Identity 2010CAS\ECP (default web site) -InternalURLhttps://webmail.inframan.nl/ECP

Now the Client Access Server will always use the external URL webmail.inframan.nl, whether the request comes from the internal network or from the outside (the Internet).

DNS

How do you prevent internal Outlook clients to connect to the Internet (i.e. webmail.inframan.nl) instead of the internal side of the Client Access Server? Normally webmail.inframan.nl resolves to 83.161.229.15, but internally you want it to resolve to internal address, for example to 10.0.0.207 which is the internal IP address of the Client Access Server.

To accomplish this you have to implement something which is known as ‘split DNS’. Besides the external DNS, you create an internal DNS zone named ‘inframan.nl’ and point the servers to the internal servers. In this case both the webmail.inframan.nl and the autodiscover.inframan.nl are resolved to 10.0.0.207 instead of 83.161.220.15


So, you have configured everything the way you want it to be, but still you get this error message as shown in Figure 1. It is a certificate warning, so you can check the IIS Log File on the Client Access Server.

Outlook 2007/2010 checks the autodiscover configuration every 15 minutes for changes in the infrastructure. And again you have the InternalURL property. But this time it’s not on the Autodiscover Virtual Directory. When you check the Autodiscover Virtual Directory details you’ll see that both the InternalURL as well as the ExternalURL property are empty:

Changing these properties doesn’t have the desired effect. For changing the internalURL settings you have to modify the Client Access Server properties. Enter the following command in an Exchange Management Shell:

Get-ClientAccessServer –Identity X2007SRV | Set-ClientAccessServer
–AutodiscoverServiceInternalUrihttps://autodiscover.inframan.nl/autodiscover/autodiscover.xml


Everything should be fine now.


CAS ARRAY

And what role does the CAS Array play in the Autodiscover story? The CAS Array is implemented when you have multiple Client Access Servers in a load balanced scenario. Outlook clients connect to a Client Access Server instead of a Mailbox Server for retrieving Mailbox information. This is achieved using the RPC protocol and not using the HTTPS protocol. Think about Outlook 2003 which doesn’t use HTTPS at all. The CAS Array is also used as a ‘backlink’ from the Mailbox Databases to the Client Access Servers. Mailbox Databases have a RPCClientAccessServer property which links a Mailbox Database to a CAS Server. This is also based on the RPC protocol.

The first step is to create a NLB cluster on your Client Access Server and give the cluster a name, for example nlb.labs.local. If you are using Client Access Servers running on Hyper-V (or VMWare) you have to be aware of the MAC address issue. Hyper-V has a range of MAC addresses being used by Virtual Machine. When you create an NLB cluster a random MAC address for the NLB address is generated, and this MAC address is not recognized by the Hyper-V Servers. More information on how to configure this can be found in Microsoft knowledge base article 953828.
Now you can add the CAS Array to the Exchange configuration, and the only option is to use the Exchange Management Shell. Enter the following command:

New-ClientAccessArray -FQDN webmail.inframan.nl -Name CAS_Arrary

The CAS Array will be added to the Exchange configuration, and it Fully Qualified Domain Name is “webmail.inframan.nl”. Your Outlook clients can now use “webmail.inframan.nl” as the Exchange Server using RPC.

Newly created Mailbox Databases will use the CAS Array as the RPC Proxy, but existing Mailbox Database will use the individual Client Access Servers as the RPC Proxy. To change the –RPCClientAccessServer property on all Mailbox Database in one time, open the Exchange Management Shell and enter the following command:

Get-MailboxDatabase | Set-MailboxDatabase –RPCClientAccessServer “webmail.inframan.nl”