Friday, June 25, 2010

Bulk Import/Create Mail Enabled Contacts

Scenario: Say you have been using Public Folders in Exchange to share contacts among users or you have a master contacts database somewhere.  If you wanted to create these contacts in AD/Exchange with the least amount of effort, what would you do?  Ok…so this scenario doesn’t really come up that often.  Hopefully you can apply the below method to other processes that might come up.

First things first: We need to get the contacts in a CSV file.  I can’t really tell you how to do that, but most likely if you are in Outlook you can use the Import/Export utility built in.  Once you have the CSV file, open that file into a text editor or Excel and format the column headers.  Then save the file into a known location on the Exchange server (I saved mine in C:\Temp\contacts-imp.csv).  Here is what my example CSV file looks like:

emailcontactscsv

Now it is time to create the contacts with the information in the CSV file.  Unfortunately, you cannot do this in one step due to the limitations of the New-MailContact cmdlet.  I guess we will do it in three steps.

1) Open ESM, and first we import the CSV file into a variable that we can refer to later.

$csvinfo = import-csv "C:\temp\contacts-imp.csv"

2) Create the mail enabled contacts by reading the information from the variable.

ForEach ($line in $csvinfo) {New-MailContact -Name $line.DisplayName -FirstName $line.FirstName -LastName $line.LastName -ExternalEmailAddress $line.EmailAddress -DisplayName $line.DisplayName}

Opening up EMC shows the newly created mail enabled contacts.

emailcontactscreate

3) Now that we have our contacts created and email enabled, it is time to fill in the gaps with all the other desired attributes.  We will need to import the Active Directory module into ESM so that we can manipulate the contact objects.  Finally, we read the CSV file and fill in the values for the other attributes.

Import-Module ActiveDirectory

ForEach ($line in $csvinfo) {Set-ADObject -identity "CN=$($line.DisplayName),CN=Users,DC=lab,DC=local" -add @{company = $line.Company;l = $line.BusinessCity;st = $line.BusinessState;title = $line.JobTitle;mobile = $line.MobilePhone;telephonenumber = $line.BusinessPhone}}

That is it!  By opening the contact we see all the information that we imported and the contact is now in the GAL. 

emailcontactsprop

If you need to find out what other LDAP attributes you can manipulate, just run “CSVDE -f filename.csv” from a command prompt.  Any of these attributes can be inserted into the CSV file and used in the PowerShell script. Happy importing.

Monday, June 21, 2010

Exchange 2007 SP3 Available

SP3 for Exchange 2007 is not available for download, you can get it HERE!

Most notable inclusions are support for Windows 2008 R2 and Windows 7 Management Tools.  Note that Windows 2008 R2 support is only for new installations of Exchange 2007 using the Exchange 2007 SP3 download.

Click here for a full list of “What’s New”.

Enjoy!

Saturday, June 19, 2010

Friday, June 18, 2010

SSL Offloading in Exchange 2010

UPDATE: Note that this post is based on Exchange 2010 RTM.  Guidance has been changed slightly for SP1.  Please see the wiki post HERE.

In one of my recent Exchange 2010 deployments at a client, the design was a highly available 3-node Exchange environment with all roles (MB, CAS, HUB) installed on each server.  So we configured DAG for the 3 nodes which relies on Windows Failover Clustering service.  For a CAS array, high availability can be implemented with either Windows Network Load Balancing (NLB) or using a Hardware Load Balancer (HLB).  Windows Failover Clustering and NLB cannot be installed on the same server so that left using a HLB to load balance the CAS service. 

The weapon of choice was a Citrix Netscaler.  A great thing about using  HLB is the ability to use SSL Offloading.  This provides many benefits with the biggest being scalability by taking off the SSL processing overhead off of the Exchange servers.  So enough of that, let’s get into how to configure it and one of the gotchas that I ran into.  I am not going to talk about the Netscaler side of the configuration, just the Exchange side.

SSL Offload

First things first:

  • Configure all internal and external URLs for the CAS services
  • Configure the CAS Array for the cluster by executing: New-ClientAccessArray –Name “CASArrayName” –Fqdn “mail.domain.com” –Site “AD Site where array lives”

Outlook Anywhere (for each CAS server):

  • Server Configuration –> Client Access
  • In the action pane, Enable Outlook Anywhere
  • In the wizard, fill out the external host name, select the authentication method and check Allow secure channel (SSL) offloading
  • Finish wizard

OWA (for each CAS server):

  • Clear “Require SSL” in IIS for Default Web Site and select Accept Client Certificates
  • Clear “Require SSL” in IIS for OWA virtual directory and select Accept Client Certificates
  • Regedit: HKLM\System\CurrentControlSet\Services\MSExchangeOWA –> Create new DWORD with name value “SSLOffloaded” and set value to “1” (no quotes on values)
  • Restart IIS

 

EWS, Autodiscover, OAB, and the rest (for each CAS server):

  • Clear “Require SSL” in IIS for each virtual directory and select Accept Client Certificates (EWS, Autodiscover, etc.)
  • Edit web.config file to force HTTP for EWS (c:program files\microsoft\Exchange Server\V14\ClientAccess\exchweb\ews\)
    • Change all occurrences of the term httpsTransport to httpTransport
    • Important: this is case sensitive…I got errors when it was set to httptransport (no capital “T”)
  • Edit web.config file to force HTTP for Autodiscover (c:program files\microsoft\Exchange Server\V14\ClientAccess\exchweb\autodiscover\)
    • Change all occurrences of the term httpsTransport to httpTransport
    • Important: this is case sensitive…I got errors when it was set to httptransport (no capital “T”)

Other Important Notes:

  • Any databases created before the CAS Array is set up will need to be reconfigured to point to the CAS Array (definitely the default databases that are created)
    • Run: Set-MailboxDatabase “DBName” –RPCClientAccessServer “CASArrayName”

Monday, June 14, 2010

Media Bypass in CS “14”: What’s the big deal?

Media Bypass is a huge investment and improvement in CS “14”.  So what is Media Bypass, what does it get me, and how does it work?

What is it?

  • Media Bypass allows for Communicator clients to communicate directly with a qualified PSTN voice gateway or qualified IP-PBX without traversing the Mediation server for media transcoding
  • When clients use Media Bypass, the Communicator client uses the G.711 codec over SRTP

What are the benefits?

  • Greatly simplifies topology
    • Allows for Mediation server to collocate with Front End server or SBA because of low CPU intensity
    • Greatly reduces the amount of servers needed in deployment resulting in lower TCO
  • Optimizes media flow and quality
    • Eliminates unnecessary hops and potential points of failure
    • Saves WAN bandwidth
    • Improves voice quality with use of G.711 codec

Scenarios

Below are just a few scenarios that show the resulting behavior when Media Bypass is used.  The diagrams show the Mediation server as a separate server for clarity only, usually the Mediation server will be collocated on the Front End server.

PSTN call in main office through local gateway

PSTN Main Gateway large

PSTN call in branch office through branch gateway/SBA

PSTN Branch Gateway

PSTN call in branch office through branch IP-PBX (same scenario for IP-PBX in main office)

PSTN Branch PBX

Communicator call to PBX phone through IP-PBX

Main PBX Call

Media Bypass in CS “14” is the key to better voice quality and lower TCO for multi-site deployments of Enterprise Voice.  In future posts I will go deeper into the other new voice features of CS “14”.

Friday, June 11, 2010

Mailbox Migration to Exchange 2010 (PowerShell)

As stated in my previous post, I am no scripting guru or will I ever claim to be.  My primary purpose for creating this script is to force myself to learn about PowerShell scripting. 

I am sure that there is a more efficient or better approach here, so please leave comments and let me know.

The following script is written to migrate mailboxes (from Exchange 2003, 2007, or 2010) to an Exchange 2010 database.  This script could easily be modified if your target database was on Exchange 2007, but for now it is just written for Exchange 2010.

##########################################################################
# This script is for migrating mailboxes to Exchange 2010
# There is no warranty, use at your own risk
# Author: Tim Harrington
http://HowDoUC.blogspot.com
#
# Some of the methods in this script rely on Quest AD PowerShell Commands
# Free download at
http://www.quest.com/powershell/activeroles-server.aspx
##########################################################################

# Initial Menu to select method of selecting mailboxes to move
#
Write-Host " "
Write-Host "1 = Move mailboxes by user name"
Write-Host "2 = Move mailboxes by security group"
Write-Host "3 = Move mailboxes by database"
Write-Host "4 = Move mailboxes by OU"
Write-Host " "
Write-Host "Full Report = Run Report -> c:\temp\FullMoveReport.txt"
Write-Host "Error Report = Run Report -> c:\temp\ErrorMoveReport.txt"
Write-Host " "
$Method = Read-Host "Please select an option from the list above?"
#
# Method 1 = Move mailboxes by user name
If ($Method -eq 1)
{
Write-Host "You have choosen to migrate mailboxes by specifying the user name"
Get-MailboxDatabase
$TargetDatabaseName = Read-Host "Type the database that you want to migrate user(s) to"
$UserName = Read-Host "Type the user name that will be migrated"
Write-Host ("Moving user: " +$UserName +" to database: " +$TargetDatabaseName)
New-MoveRequest -identity $UserName -TargetDatabase $TargetDatabaseName
}

# Method 2 = Move mailboxes by security group
If ($Method -eq 2)
{
Write-Host " "
Write-Host "You have choosen to migrate mailboxes by specifying an AD security group"
Write-Host " "
Write-Host "This script relies on Quest AD PowerShell Commands"
Write-Host "Download at http://www.quest.com/powershell/activeroles-server.aspx"
Write-Host " "
Add-PSSnapin Quest.ActiveRoles.ADManagement
$ADSecGroupName = Read-Host "Enter AD security group that you want to migrate"
Get-QADUser -MemberOf $ADSecGroupName | ft
Write-Host "The above list of users will get migrated!!"
Write-Host " "
Get-MailboxDatabase | ft
$TargetDatabaseName = Read-Host "Type the database that you want to migrate user(s) to"

#Loop through each mailbox
foreach ($mailbox in (Get-QADUser -MemberOf $ADSecGroupName))
{$displayname = $mailbox.Displayname
New-MoveRequest -Identity $displayname -TargetDatabase $TargetDatabaseName}
}
#
# Method 3 = Move mailboxes by database
If ($Method -eq 3)
{
Write-Host "You have choosen to migrate mailboxes from one database to another database"
Get-ExchangeServer | ft
$SourceServer = Read-Host "What is the source server from list above?"
Get-MailboxDatabase -Server $SourceServer | ft
$SourceDatabaseName = Read-Host "What is the SOURCE database from list above? (Type exactly from list)"
Get-MailboxDatabase | ft
$TargetDatabaseName = Read-Host "What is the TARGET database from list above? (Type exactly from list)"
Write-Host ("Moving users from source database: " +$SourceDatabaseName +" to target database: " +$TargetDatabaseName)
Get-Mailbox -Database $SourceDatabaseName
New-MoveRequest -TargetDatabase $TargetDatabaseName
}
#
# Method 4 = Move mailboxes by OU
If ($Method -eq 4)
{
Write-Host " "
Write-Host "You have choosen to migrate mailboxes by specifying an AD OU"
Write-Host " "
Write-Host "This script relies on Quest AD PowerShell Commands"
Write-Host "Download at http://www.quest.com/powershell/activeroles-server.aspx"
Write-Host " "
Add-PSSnapin Quest.ActiveRoles.ADManagement
Get-QADObject -Type OrganizationalUnit | ft
$ADOUName = Read-Host "Enter AD OU that you want to migrate"
Get-QADUser -Searchroot $ADOUName -SearchScope OneLevel | ft
Write-Host "The above list of users will get migrated!! (This does not include sub-OUs)"
Write-Host " "
Get-MailboxDatabase | ft
$TargetDatabaseName = Read-Host "Type the database that you want to migrate user(s) to"

#Loop through each mailbox
foreach ($mailbox in (Get-QADUser -Searchroot $ADOUName))
{$displayname = $mailbox.Displayname
New-MoveRequest -Identity $displayname -TargetDatabase $TargetDatabaseName}
}
#
# Save off full report
If ($Method -eq "Full Report")
{
Get-MoveRequest | Get-MoveRequestStatistics | Select DisplayName, Status, TotalItemSize, TotalMailboxItemCount, PercentComplete, BytesTransferred, ItemsTransferred | Out-File -FilePath "c:\temp\FullMoveUserLog.txt" -append -noClobber
}

# Save off error report
If ($Method -eq "Error Report")
{
Get-MoveRequest | Get-MoveRequestStatistics where {$_.Status -like "*error*"} | Select DisplayName, Status, TotalItemSize, TotalMailboxItemCount, PercentComplete, BytesTransferred, ItemsTransferred | Out-File -FilePath "c:\temp\ErrorMoveUserLog.txt" -append -noClobber
}
#############################################################################

Hope this helps some folks out there.  Comments are welcome.

Thursday, June 10, 2010

PowerShell, PowerShell, PowerShell

Do I need to say it again?  If you haven't figured out by now, Microsoft is shifting from GUI administration to command-line administration.  Not saying that all GUI administration is going away, but PowerShell is the now and is the future.  With the new Microsoft wave, PowerShell is the main administration tool and even the GUI tools are written on top of PowerShell.  Active Directory 2008 R2, Exchange 2007/2010, CS 2010 (next release of OCS) will utilize PowerShell heavily!

For all the GUI Admins out there kicking and screaming (I am one of them), it is time to realize that if you want to stay ahead of the curve (of just keep up) it is time to learn and use PowerShell in your everyday work.

Here are some resources to help you get started...
Being a self-proclaimed GUI Admin, I am starting to force myself to use PowerShell for everyday tasks.  It is definitely working.  In the near future, I will be posting some of my PowerShell scripts that I have created to help myself learn.  Stay tuned...

Wednesday, June 9, 2010

Hello World...

I am new to this whole blogging thing, but have been wanting to do this for a long time.  I find the blogs that I follow so helpful in my work as a UC consultant and have inspired me to share some of my knowledge along the way.

I hope that you find this blog useful in your everyday work or at least interesting to read.