Script: Export-Groups.vbs – For Exchange Cross Forest migrations

I’ve been doing Exchange cross forest migrations now for about 15 years, since Exchange 5.0! With each major version of Exchange the procedures would changed a bit and the scripts would be updated or recreated as needed. Without 3rd party tools there are many steps that are not covered by the built-in cmdlet or scripts provided by Microsoft.

Microsoft include the Prepare-MoveRequest.ps1 script, starting with Exchange 2010 RTM, which is used to create Mail Enabled Users (MEU) in the target Exchange 2010/2013 environment. The script will create the MEU, copy the SMTP and x500 addresses (include the LegacyExchangeDN), GAL attributes, and a few others attributes. Then New-MoveRequest can be used to migrate the mailbox from Exchange 2003, 2007, 2010, or 2013 in another forest to Exchange 2010/2013. New-MoveRequest will create a mailbox for the user, replace the MEU with a Mailbox enabled user, and replace the Mailbox enabled user in the source environment with a Mail Enabled User. So the Prepare-MoveRequest script and the New-MoveRequest are all that’s normally needed to migrate mailboxes across forest.

But this does address Groups, Contacts, or Public Folders. All of which have properties, mainly SMTP & x500 addresses, that must be migrated also to ensure correct mail-flow and prevent NDRs when users reply to existing messages, meetings, or when using the Nickname cache.

So I’m going to start a series of blog post that will cover the key scripts I used, and created, to handle the other objects. I have several other scripts that I use to find and address many issues that come up when doing a cross forest migration and probably won’t go into all of these.

Export-Group.vbs – Yes this is a VBScript, but I wanted one script that will work when migrating from Exchange 2003, 2007, 2010, and 2013. So I created this script, actually I had a couple of other scripts I used to use before this one but this one has superseded them now.

This script will export SMTP, x500 (including LegacyExchangeDN), and group membership to two CSV files. It assumes the groups have already been created, which can be done via ADMT or via LDIFDE (which I’ve found quicker and easier than using ADMT in smaller environments). It does not export disabled members, since Prepare-MoveRequest doesn’t support disabled mailboxes either, but this can be easily changed.

It will generate two files: GroupAddressess.csv & GroupMembers.csv. GroupAddressess.csv will have one each line per SMTP or x500 address, in the format of:  mailNickName, samAccountName, proxyAddress. GroupMembers.csv will have one line per member in the format of  mailNickName, samAccountName, member mailnickname, and member primary e-mail address. I include samAccountName in the export file but don’t actually use it since some groups may not be security enabled or members by be other non-security groups or contacts.

 

Source: Export-Groups.vbs

Related Import scripts, to be covered in another blog post very soon:
Import-GroupMembers.ps1
Import-GroupAddresses.ps1

'
' This script will export the SMTP, x500, & LegancyExchangeDN address and members of all groups with e-mail addressess to GroupSMTP.csv & GroupMembers.csv
' 	Output file can be used to import members by http://izzy.org/scripts/Exchange/Migration/Import-GroupAddresses.ps1
' 	Output file can be used to addresses by http://izzy.org/scripts/Exchange/Migration/Import-GroupMembers.ps1
'
' Created 3/1/2012 by Jason Sherry (izzy@izzy.org) http://jasonsherry.org
'	Source: http://izzy.org/scripts/Exchange/Migration/Export-Groups.vbs
' Last Updated: 8/29/2013
'		05/09/2012 Added legacyExchangeDN export support and fixed SMTP case issue
'		08/28/2013 Added support to export members (disabled users skipped), logging to file for WARNING & ERROR events
'		08/29/2013 Added x500 export support

Option Explicit

Dim strDomainDN, strBase, strFilter, strAttrs, strScope, rootDSE
Dim objCmd, objConn, objRS, objLogFile
Dim proxyaddresses, proxyaddress
Dim objAddressFile, objfs, GroupAddressFile, GroupMemberFile, objMemberFile
Dim name, mailNickName, samAccountName, legacyExchangeDN, adspath
Dim member, members, objMember, membermailNickname, membermail, membername, memberSamAccountName, userAccountControl
Const ADS_UF_ACCOUNTDISABLE = 2
GroupAddressFile= "GroupAddressess.csv"
GroupMemberFile= "GroupMembers.csv"

Set rootDSE = GetObject("LDAP://rootDSE")
'strDomainDN = "dc=company,dc=local" #Required if the script needs to get data from a domain other than the one it is being run in
strDomainDN = rootDSE.Get("defaultNamingContext")

strBase   =  "
strFilter = "(&(mailNickName=*)(proxyAddresses=*)(objectCategory=group));"
strAttrs  = "name,adspath,mailNickName,proxyaddresses,legacyExchangeDN,samAccountName,member;"
strScope  = "subtree"

Set objfs = CreateObject ("Scripting.FileSystemObject")
Set objAddressFile = objfs.CreateTextFile (GroupAddressFile, True)
Set objMemberFile = objfs.CreateTextFile (GroupMemberFile, True)
Set objLogFile = objfs.CreateTextFile ("Export-Groups.log", True)

Set objConn = CreateObject ("ADODB.Connection")
objConn.Provider = "ADsDSOObject"
objConn.Open "Active Directory Provider"

Set objCmd = CreateObject ("ADODB.Command")

objCmd.ActiveConnection = objConn
objCmd.CommandText = strBase & strFilter & strAttrs & strScope
objCmd.Properties ("Page Size") = 5000

Set objRS = objCmd.Execute
objRS.MoveFirst

objAddressFile.WriteLine "mailNickName,samAccountName,ProxyAddress"
objMemberFile.WriteLine "mailNickName,samAccountName,membermailNickname,membermail"

while Not objRS.EOF
	'Wscript.Echo "name = " & objRS.Fields(0).Value
	name = objRS.Fields(0).Value
	adspath = objRS.Fields(1).Value
	mailNickName = objRS.Fields(2).Value
	proxyaddresses = objRS.Fields(3)
	legacyExchangeDN = objRS.Fields(4).Value
	samAccountName = objRS.Fields(5).Value
	members = objRS.Fields(6)

	WScript.Echo "Processing group: [" & samAccountName & "]"
WScript.Echo "  Path: " & adspath
	WScript.Echo "  SMTP, x500, & legacyExchangeDN addresses:"
' Get SMTP & x500 addresseses
	For Each proxyaddress in proxyaddresses
If UCase(Left(proxyaddress,4)) = "SMTP" Then
			WScript.Echo "    Address: " & Replace(proxyaddress,"smtp:","",1,-1,1)
			objAddressFile.WriteLine mailNickName & "," & samAccountName & "," & Replace(proxyaddress,"smtp:","",1,-1,1)
	  End If
If UCase(Left(proxyaddress,4)) = "x500" Then
			WScript.Echo "    Address: " & Replace(proxyaddress,"x500:","",1,-1,1)
			objAddressFile.WriteLine mailNickName & "," & samAccountName & "," & Replace(proxyaddress,"x500:","",1,-1,1)
	  End If
	Next
' Get legacyExchangeDN
'	WScript.Echo vbtab & vbtab & "Address: " & legacyExchangeDN
	objAddressFile.WriteLine mailNickName & "," & samAccountName & "," & legacyExchangeDN

'	Get Group Members
	If TypeName(members) = "Variant()" Then
		WScript.Echo "  Members:"
		For Each member in members
			Set objMember = GetObject("LDAP://" & member)
			membermailNickname = objMember.mailNickname
			membermail = objMember.mail
			membername = objMember.name
			memberSamAccountName = objMember.samAccountName
			If memberSamAccountName  "" Then
				userAccountControl = objMember.userAccountControl
				If userAccountControl  and ADS_UF_ACCOUNTDISABLE Then
					WScript.Echo "    User: [" & memberSamAccountName & "] is disabled, this user will not be exported"
					objLogFile.WriteLine "WARNING: User: [" & memberSamAccountName & "] is disabled, this user will not be exported"
					membermail = ""
				End If
			End If
			If membermail  "" Then
				If membermailNickname = "" Then
					WScript.Echo
					WScript.Echo "**** Unexpected data found ****"
					WScript.Echo "Empty field for : [" & Replace(membername,"CN=","") & "] mailNickName: [" & membermailNickname & "] mail: [" & membermail & "]"
					objLogFile.WriteLine "ERROR: Empty field for : [" & Replace(membername,"CN=","") & "] mailNickName: [" & membermailNickname & "] mail: [" & membermail & "]"
				Else
					WScript.Echo "    Name: [" & Replace(membername,"CN=","") & "] mailNickName: [" & membermailNickname & "] mail: [" & membermail & "]"
					objMemberFile.WriteLine mailNickName & "," & samAccountName & "," & membermailNickname & "," & membermail
				End If
			End If
		Next
	End If
	objRS.MoveNext
Wend

objAddressFile.Close
Posted in Exchange, Technical | Tagged , | 13 Comments

Check out the IIS ARR series on the Exchange Team Blog

Application Request Routing (AAR) is an optional feature of IIS on Windows 2008+ that allows IIS to act as a reverse proxy and URL re-writer. With this support you can have an Windows 2008+ server in your DMZ, it does not have to be domain joined, that all external clients connect to, then it will proxy their request to Exchange.

So it basically is a light weight replacement for TMG, but it does not support advanced rules, pre-authentication, DoS detection, etc, etc.

Part 1: Reverse Proxy for Exchange Server 2013 using IIS ARR – Setting up a basic AAR config
Part 2: Reverse Proxy for Exchange Server 2013 using IIS ARR – Advanced setup, with service level availability and how to handle co-existence with Exchange 2007 & 2010
Part 3: Reverse Proxy for Exchange Server 2013 using IIS ARR – Tracing, Logging, & Best Practices

Posted in Exchange, Technical | Tagged | Leave a comment

Exchange 2013 CU2v2 (KB2859928-x64-v2 |Build 712.024) released

8/1/13 Update: Exchange Team blog post added: http://blogs.technet.com/b/exchange/archive/2013/07/29/now-available-updated-release-of-exchange-2013-rtm-cu2.aspx

The 1st release of CU2 was posted on 7/9/2013 and on 7/12 Microsoft posted that there was an issue where Public Folder permissions were lost when a Public Folder mailbox was moved. I posted about it on 7/12 also, once it was made public, here: https://blog.jasonsherry.net/2013/07/12/dont-move-your-pf-mailbox-exchange-2013-cu2/

CU2v2 fixes this issue with Public Folders, I think this might be the only issue that it fixes. CU2 redux is not officially be called CU2v2 it seems, but the download file is KB2859928-x64-v2.exe and in the past five or so re-releases they have been called v2/v3 so I’m sure everyone will be calling this CU2v2.

Like CU1 and CU2, CU2 build 712.024 is a full download and “upgrade”, so there is no uninstall. You CAN install CU2v2 over RTM, RTM CU1, RTM CU2 (build 712.022).

Even if you aren’t using Public Folders in 2013 you still need to upgrade to CU2V2 since future security updates and IUs will be based on CU2v2.

I’m also tracking known issues (those that I know of at least) with Exchange 2013 CU2 here: https://blog.jasonsherry.net/2013/07/09/exchange-2013-rtm-cu2-released/

Posted in Exchange, Technical | Tagged , | 1 Comment

Exchange 2013 book out by my friends

This book just came out this week and I just ordered my copy!

Microsoft Exchange Server 2013: Design, Deploy and Deliver an Enterprise Messaging Solution
http://www.amazon.com/Microsoft-Exchange-Server-2013-Enterprise/dp/1118541901

Authors:
– Nathan Winter – AD, Exchange, & Lync Consutlant | Blog | Amazon Profile | @nathanwinters
– Neil Johnson – Microsoft Exchange Team | Blog | @jonnokid
– Nicolas Blank – Exchange MVP & Consutlant | Blog | Website@nicolasblank

While this might not be the 1st book that came out for Exchange 2013 it is one based on the release version. Many books that come out on technology right when that technology is released must be based on the alpha or beta versions and therefore likely has many things in it that are incorrect. This is due the fact that once the writers are done with the book it can take 3-6 months for the book to be release. So to ship at the same time requires they write based on the beta version of the product.

So it’s best to wait at least six months before buying a book on any major software release, also a good policy to follow when installing\upgrading it!

Posted in Exchange, Technical | Tagged , | Leave a comment

Exchange 2013 Jetstress Field Guide 2.0 released

Quick post for now, I’ll come back later and update it with more details after I read it 🙂

When doing any install of Exchange I always insist on running JetStress to make sure the storage is working as expected. About half the time it is not, most of these are where the client has a new iSCSI infrastructure setup. There are many factors that can affect performance with iSCSI, but the most common that I’ve seen are old\incorrect drivers and incorrect network configurations.

So always run JetStress to make sure the storage is delivering the IOPS needed and the I/O latency is below 20ms on average and has no peaks over 50ms. With JetStress 2010 you had to de-tune JetStress manually so it only generated a similar number of IOPS as what the Exchange Storage Calculator recommends.

Posted in Exchange, Microsoft, Technical | Tagged , | Leave a comment

Don’t move your PF mailboxes after upgrading to Exchange 2013 CU2! (FIXED)

7/29/13 Update: Microsoft pulled CU2 a couple of days ago and release CUv2 (but it doesn’t say this anywhere). The new build of CU2 is 15.00.0712.024. Download it here!

More details here: https://blog.jasonsherry.net/2013/07/29/exchange-2013-cu2v2-build-712-024-released/

I’ve updated this blog post with a bit more info: https://blog.jasonsherry.net/2013/07/09/exchange-2013-rtm-cu2-released/

Quick post on this issue due to the severity, all PF permission can get lost and will default to Authenticated Users have access to all of them.

See this EHLO Blog post for much more details: http://blogs.technet.com/b/exchange/archive/2013/07/12/e2013-rtm-cu2-issue-public-folder-permissions-loss-after-pf-mailbox-move.aspx

I’m also tracking a list of “known” issue with Exchange 2013 CU2 on this blog post: https://blog.jasonsherry.net/2013/07/09/exchange-2013-rtm-cu2-released/

Posted in Exchange, Technical | Tagged , | 2 Comments

Exchange 2013 RTM CU2 released (Again on 7/29) & Known Issues

12/4/13 Update: Exchange 2013 CU3 is now out and I’ve started a new Known Issues list on it here: http://wp.me/p1qPTK-be

11/25/13 Update: Exchange 2010 SP3 RU2 release: https://blog.jasonsherry.net/2013/11/25/exchange-2010-sp3-ru3-2013-cu3-release/ (I will move my “Known Issues” list to this blog post once I have some to list)

7/29/13 Update: Microsoft pulled CU2 a couple of days ago and release CUv2 (but it doesn’t say this anywhere). The new build of CU2 is 15.00.0712.024. Download it here!

7/12, 7/22, 9/2, 9/19 Updates: New issues added to list
7/10/13 Update: Added list of known\possible issues at the end

Download (1.3GB) | EHLO Blog Post on CU2
KB2859928 (not much here) | Release Notes (READ!)

 Today Exchange 2013 RTM CU2 was release, build version 15.0.712.22! Given the new servicing model, that started with Exchange 2013 RTM, this build should have been running in Office 365 for at least a few weeks now. So any major issues should have already been discovered and resolved before the release today. (7/12 So much for that idea, see this post on issues with Public Folder permissions lost: https://blog.jasonsherry.net/2013/07/12/dont-move-your-pf-mailbox-exchange-2013-cu2/ or this one by Tony Redmond: http://windowsitpro.com/blog/new-servicing-model-hiccups-exchange-2010-rtm-cu2-public-folder-permissions-bug-appears)

Given the fixes to OWA SSO and that two major updates have been released  I will now be telling my clients it’s time to upgrade to 2013! If you want help upgrading or doing a cross forest migration to Exchange 2013 contact me!

As with all Cumulative Updates (CUs) this is a FULL BUILD, so when you install you are upgrading the Exchange server to CU2. This build can also be used for fresh installs. There is no UNINSTALL support with CUs, so make sure you TEST, TEST, and RETEST any add-ons and 3rd party applications in your lab before installing!

Key Notes

  1. Updates the Schema, so plan accordantly with your AD team to have /PrepareSchema run
  2. Updates the AD settings (RBAC roles have been updated, for example) , so /PrepareAD will need to be run again

New features & improvements:

  1. OWA FBA single sign-on redirection improved\fixed
    • Issued fixed from RTM and CU1:
      • Same site: Exchange 2013 and 2007: Users authenticate against Exchange 2013, then are prompted for authentication a second time when redirected to Exchange 2007 CAS, if their mailbox was on Exchange 2007
        • SSO now works, silently redirected and authenticated to 2007 CAS
    • Mixed Site: Exchange 2013 and 2007 in Internet facing site A, user’s mailbox on 2007 in Site B
      • Used to fail with HTTP 500 error, now will silently redirected and authenticate users
    • Cross site: Exchange 2013 in Site A, 2007, 2010, or 2013 in Site B: Users with mailboxes on 2007, 2010, or 2013 prompted to re-authentication when redirected to E12/14/E15 CAS
      • SSO now works, silently redirected and authenticated
    • Note: Make sure your Exchange 2010 server is running SP3 UR1 or higher, there is a known issue with request proxied to a Exchange 2010 SP3. See the Release Notes for more info.
  2. Support for 100 databases per server (Enterprise Edition only)
    • 2013 RTM and CU1 only supported 50 database. Due to customer request and changes made in CU2 this has been increased to 100.
    • CPU and RAM requirements will probably limit the number of database to less than 100 on most mailbox servers
    • Exchange 2013 Storage Calculator has been updated to support 100 database also
  3. DAG Management Service
    • Adds a new service, MSExchangeDAGMgmt, which will offload the Replication Service by providing information on health status and logging events in the same location MSExchangeRepl used to, i.e. Application Eventlog using the same Crimson channel, but still using MSExchangeRepl as source.
  4. OWA Search improvements
    • Previously searching for keywords within OWA did not give indications of the location of the keyword.  Exchange 2013 RTM CU2 improves OWA’s search results highlighting feature:
      • Auto-expand conversation items that have hits in them
      • Auto-scroll to the first search hit
      • Hit navigation within a conversation
  5. Managed Availability improvements
    • In addition to improvements in various probes and monitors, there have been changes to the responder throttling framework
  6. Updateable Shell Help
    • Introduces the capability for administrators to get updates to Exchange Management Shell cmdlets without needing to deploy a new service pack or cumulative update
  7. Coming soon: Witness Server in Azure Cloud
    • For Azure clients this will allow them to deploy a FSW on an Azure server, which allow organizations with two datacenters to enable automated failover between their two sites.

Known\Possible Issues
Below are a list of issues reported by my peers in the Exchange MVP community and elsewhere. This is NOT an official list from Microsoft by any means. If you have run into issues that only started after installing CU2 please post a comment on this blog post. Also include a link to where you’ve posted the issue on the TechNet forms.

Read the Release Notes, it list multiple officially known issues!

  1. Important: Install fails with the following error: (7/10)
    • The following error was generated when “$error.Clear();
      & $RoleBinPath\ServiceControl.ps1 EnableServices Critical
      ” was run: “AuthorizationManager check failed.”.
      AuthorizationManager check failed.
    • Cause: A GPO or the local policy sets the Windows PowerShell Execution policy to a status other than Undefined.
    • Workaround:
      • Disable the GPO\policy before installing CU2
      • If you already started and it failed:
        1. Disable GPO\policy and to a GPUPDATE /Force on the server
        2. Recover the server 1st using RTM or CU1:
          Setup /m:RecoverServer /IAcceptExchangeServerLicenseTerms
        3. Then install CU2
    • See KB2668686 (For Exchange 2010 SP2) for more details
    • 7/11: A note has been added to the EHLO blog post on CU2 about this issue:
      • To prevent issues during the installation or upgrade of Exchange 2013 RTM CU2, you should ensure that the Windows PowerShell Script Execution Policy is set to “Unrestricted”. Failure to do so could cause the Exchange 2013 server to be in an unusable state and some downtime could occur. To verify the policy settings, run the Get-ExecutionPolicy cmdlet from PowerShell on the Exchange 2013 Server(s). If the policies are NOT set to Unrestricted you should use the resolution steps in the following article to adjust the settings KB 981474.
  2. CRITICAL: BSOD being caused by Health Monitoring (8/18)
    • Per this TechNet thread the Health Monitoring service can BSOD a server after installing CU2
    • I have not seen this issue on the two servers I run in production or the four at one of my clients running Exchange 2013 CU2
    • Quick Fix: Disable the “Microsoft Exchange Health Manager” service on all 2013 CU2 servers
    • Fixed in CU3
  3. CRITICAL: Public Folder permissions are loss after moving a PF mailbox (7/12)
  1. Important: DNS Lookup issues may prevent or delay message delivery or cause items to sit in OWA Drafts folder (7/22)
    • I’ve been following a thread on this since CU1\April but just now getting around to post it here, sorry for the delay if you’ve hit this issue
    • Tony Redmond’s also covered this on his blog here: http://thoughtsofanidlemind.wordpress.com/2013/03/25/exchange-2013-dns-stuck-messages/
    • In some environment message delivery will fail with the following error or be delayed by many seconds or minutes.
      451 4.7.0 Temporary server error. Please try again later. PRX5
    • Threads on MS TechNet Forums: http://bit.ly/14A1JQY & http://bit.ly/13UG1ks
    • Quick Fix:
      • Option A: Set the NIC to use for “External DNS lookups” in EAC under Servers
      • Option B: Set ExternalDNSAdapterEnabled and InternalDNSAdapterEnabled to $false and set DNS servers on ExternalDNSServers and InternalDNSServers with the  Set-FrontendTransportService command
      • Others have used a host file with the Exchange 2013 servers in it, but the above method is easier to manage
  2. Minor: OWA authentication gets set to FBA after during the upgrade (7/12)
    • Heard of this one today on a mailing list I’m on. Haven’t confirmed it, but if you have a solution like TMG doing pre-authentication this may affect it.
    • Quick Fix: Turn FBA off, on, and back off per one persons post. Just turning it off doesn’t seem to take.
    • 8/1: KB2871485 covers this, it says just to disabled FBA using these three steps below:
      • Set-OwaVirtualDirectory -Identity “EXCH3\owa (Default Web Site)” -FormsAuthentication $false -WindowsAuthentication $true
      • Set-EcpVirtualDirectory -Identity “EXCH3\ECP (Default Web Site)” -FormsAuthentication $false -WindowsAuthentication $true
      • IISRESET
  3. Minor: Transport Server must be restarted after taking server out of maintenance mode (7/10)
    • Per peers after putting a server in maintenance (StartDagServerMaintenance.ps1) and then taking it out (StopDagServerMaintenance.ps1) the Front-End Transport server must be restarted before mailflow will resume to that server
  4. Minor: MSDiagnostics Event Error 1006 (9/2)
    • From: http://edwardvbs.wordpress.com/2013/08/22/207/
    • Event ID 1006 gets logged with performance counter errors about free space
      • The performance counter ‘\\SERVER\LogicalDisk(HarddiskVolume1)\Free Megabytes’ sustained a value of ’45,297.00′, for the ’15′ minute(s) interval starting at ’7/21/2013 5:41:00 AM’. Additional information: None. Trigger Name:DatabaseDriveSpaceTrigger. Instance:harddiskvolume4
    • Quick fix: Disable this monitor
      1. Edit “…\ExchangeServer\V15\Bin\Microsoft.Exchange.Diagnostics.Service.exe.config”
      2. Change this value to have “False” instead of “True”
        <add Name=”Microsoft.Exchange.Diagnostics.Service.ExchangeJobs.Triggers.DatabaseDriveSpaceTrigger” Assembly=”Microsoft.Exchange.Diagnostics.Service.ExchangeJobs.dll” Enabled=”False” Role=”Mailbox” />
      3. Restarted the MS Exchange Diagnostics Service
  5. Minor: Error when forwarding a calendar (9/2)
    • From: http://edwardvbs.wordpress.com/2013/08/08/exchange-2013-cu2-error-when-forwarding-a-calendar/
    • “…users have come back to me saying they get errors when trying to forward a calendar, here is the error:This message could not be sent. Try sending the message again later, or contact your network administrator. Error is [0x80070005-00000000-00000000]MS have advised this is a know bug and will be fixed in CU3. You can check if you get the same error on OWA as well. CU3 is scheduled to be released in about 3 months time.”
  6. Important: On Windows 8.1 or 2012 R2 OWA comes up in Lite mode (9/19)
    • This is a known issue with IE11, which comes with Windows 8.1 and 2012 R2
      • Workaround: Use Firefox or Chrome
      • 2010 SP3 RU3 & 2013 CU3 should fix this issue
  7. Minor: Setup incorrect request .NET Framework 4.0
    • .NET Framework 4.5 is required, not 4.0, you do NOT need to install 4.0
  8. Minor: Exchange XML application configuration files are overwritten during cumulative update installation
    • Any customized per-server settings you make in Exchange XML application configuration files, for example, web.config files on Client Access servers or the EdgeTransport.exe.config file on Mailbox servers, will be overwritten when you install an Exchange Cumulative Update (CU). Make sure that you save this information so you can easily re-configure your server after the install. You must re-configure these settings after you install an Exchange CU.
    • From Release notes page

For community based support goto TechNet forums: http://social.technet.microsoft.com/Forums/exchange/

Posted in Exchange, Technical | Tagged , , | 14 Comments

Script: Create-Mailbox.ps1 – Copy an existing user and create a mailbox

8/22/14 Update: I’ve made some improvements to the script, make sure you get the latest version from: http://izzy.org/scripts/Exchange/Admin/Create-Mailbox.ps1

One of the most common tasks for Exchange admin is creating mailboxes. This can easily be done with the GUI (EMC\EAC) but some settings can’t be set using the creation wizard or in the GUI at all. So I always recommend my clients automate the creation of mailboxes to ensure that they are created with the correct attributes. So I’ve decided to share my mailbox creation script with everyone!

This script will not only create a mailbox, but it will also copy an existing user and some of their attribute (using New-ADUser -Instance $objSourceUser) and optionally send them a “Welcome” e-mail. When creating the mailbox the script will get the smallest database, by size, that matches a filter provided and finally set the retention and arching policy on it.

The latest source of this script should always be here: https://gallery.technet.microsoft.com/Script-Excahnge-Copy-an-1b7f1553

Usage example: .\Create-Mailbox.ps1 -NewUserID “JoeSales” -GivenName “Joe” -Surname “Sales” -SourceUserID “_SalesTemplate” -CustomAttrib “Team 1”

The example above will create a new user account for “Joe Sales” based on the “_SalesTemplate” account. By default it will copy the following attributes from the template: MemberOf, Description, Company, Department, Office, Title, streetAddress, City, State, PostalCode, Country. In addition, it will optionally set CustomAttribute10 to “Team 1”; this is  handy if you have EAPs that use a custom attribute.

The script has some basic error handling and by default will continue the mailbox creation process if the new user ID already exist.

The following lines should be customized for your environment:

$Group = ‘Mail Users’ # Only used if $AddToGroup = $True

$Password = “P@ssW0rD!”
$UPNSufix = “@izzy.org”

$SMTPServer = “mail.altered.com”
$From = “ExchangeAdmins@company.com”
$MsgSubject = “Welcome to the Company!”
$MsgBody = Get-Content “D:\Tools\Welcome.htm”(Example here: http://izzy.org/scripts/Exchange/Admin/Welcome.htm)

# This script create a new mailbox on the smallest mailbox database that matches a filter and set other attributes

# Created by Jason Sherry (izzy@izzy.org) 4/20/2012
# Last Updated: 8/22/2014
#	5/24/12: Added support to add user to a group & set CustomAttribute10
# 7/8/13: Added support to copy a template user account, including a list of attributes and group membership
# 7/23/13: Fixed an issue with $Null detection for parameters
# 8/22/14: Added error handling for when no databases are returned, when no other name values are provided, & when source member of is empty

# Source: https://gallery.technet.microsoft.com/Script-Excahnge-Copy-an-1b7f1553
#	 Partial code source: http://powershell.com/cs/media/p/3981.aspx

param(
	[Parameter(Mandatory = $true)][String]$NewUserID,
	[String]$SourceUserID = $Null,
	[String]$DisplayName = $Null,
	[String]$GivenName = $Null,
	[String]$Surname = $Null,
	[String]$CustomAttrib = $Null,
	[String]$SendWelcome = $True)

$DBFilter = "Primary*" # Limit databases to only those that start with "Primary"
$RetentionPolicy = "Default Archive and Retention Policy"

$ContiuneOnExist = $True # Option good for testing

$CopyAttributes = "MemberOf","Description","Company","Department","Office","Title","streetAddress","City","State","PostalCode","Country"
# List of properties: http://social.technet.microsoft.com/wiki/contents/articles/12037.active-directory-get-aduser-default-and-extended-properties.aspx

$AddToGroup = $False
$Group = 'Mail Users'

$Password = "P@ssW0rD!"
$UPNSufix = "@izzy.org"

$SMTPServer = "mail.altered.com"
$From = "ExchangeAdmins@company.com"
$MsgSubject = "Welcome to the Company!"
$MsgBody = Get-Content "D:\Tools\Welcome.htm" | out-string

Function Get-SmallestDB {
	Try {
		$MBXDbs = Get-MailboxDatabase | ? {$_.Identity -like $DBFilter } 
		$MBXDBCount = $PSSessions.Count
	}
	Catch {
		$MBXDBCount =  0
	}
	
	If (!$MBXDbs) {ExitScript "find databases with a name that matches a filter of [$DBFilter]." $False}

	# Loop through each of the MBXDbs
	ForEach ($MBXDB in $MBXDbs)	{
		# Get current mailboxes sizes by summing the size of all mailboxes and "Deleted Items" in the database
		$TotalItemSize = Get-MailboxStatistics -Database $MBXDB | %{$_.TotalItemSize.Value.ToMB()} | Measure-Object -sum
		$TotalDeletedItemSize = Get-MailboxStatistics -Database $MBXDB.DistinguishedName | %{$_.TotalDeletedItemSize.Value.ToMB()} | Measure-Object -sum
#XXX		$TotalDeletedItemSize = Get-MailboxStatistics -Database $MBXDB| %{$_.TotalDeletedItemSize.Value.ToMB()} | Measure-Object -sum
		#Get-MailboxDatabase and the DatabaseSize property was not used since it does not return a value in some environments  as of 2010 SP2
		
		$TotalDBSize = $TotalItemSize.Sum + $TotalDeletedItemSize.Sum
		# Compare the sizes to find the smallest DB
		If (($TotalDBSize -lt $SmallestDBsize) -or ($SmallestDBsize -eq $null)) {
			$SmallestDBsize = $DBsize
			$SmallestDB = $MBXDB }}
	return $SmallestDB }

Function ExitScript ($ErrorText,$ShowFullError) {
	Write-Host "`nAn error occurred when trying to $ErrorText, exiting script`r`n"  -ForegroundColor Red
	If ($ShowFullError) {
		Write-Host "Error: " $error[0] -ForegroundColor Red
	}
	Break }

Function CopyUser ($SourceUser,$NewUser,$GivenName,$Surname,$DisplayName) {

	Import-module ActiveDirectory

	If ($DisplayName -eq "") {
		If ($GivenName -eq "" -And $SurName -eq "") {
			$DisplayName = $NewUserID
		}
		Else {
			$DisplayName = "$GivenName $SurName" # Set DisplayName if it's blank
		}
		$DisplayName = $DisplayName.Trim() # Removes the leading & trailing spaces
	}

	Write-Host "New user account will be based on user: [$SourceUser]" -ForegroundColor Green
	Try {$UserTemp = Get-User $SourceUser -ErrorAction SilentlyContinue}
	Catch {ExitScript "run [Get-User $SourceUser], confirm user ID exist" $False}

	$UserTemp = $Null
	$UserTemp = Get-User $NewUser -ErrorAction SilentlyContinue
	If ($UserTemp -and !$ContiuneOnExist) {
		Write-Host "User ID $NewUser already exist, script exiting." -ForegroundColor Red
		Exit
	}
	ElseIf ($UserTemp -and $ContiuneOnExist) {
		Return
	}

	$SecurePassword = convertto-securestring $Password -asplaintext -force

	Try {$objSourceUser = Get-ADUser -Identity $SourceUser -Properties $CopyAttributes -ErrorAction Stop}
	Catch {ExitScript "run [Get-ADUser $SourceUser], confirm user ID exist" $False}

	$OUPath = $objSourceUser.DistinguishedName.Replace("CN=$($objSourceUser.Name),","")

	Write-Host "`tCreating user -> DisplayName: [$DisplayName] GivenName: [$GivenName] SurName: [$SurName] `n`tCreating in OU: [$OUPath]" -ForegroundColor Cyan

	New-ADUser -Instance $objSourceUser -UserPrincipalName "$NewUser$UPNSufix" -SAMAccountName $NewUser -Name $DisplayName -DisplayName $DisplayName -AccountPassword $SecurePassword -GivenName $GivenName  -Surname $Surname -Path $OUPath
	Set-ADUser -Identity $NewUser -Enabled $True # I've seen the accounts randomly not being enabled without this
	# -Instance required Windows 2008 R2 DCs: http://technet.microsoft.com/en-us/library/dd378959(v=ws.10).aspx
	Sleep 1 # Delay to prevent object not found error with below command
	If ($objSourceUser.memberOf) {
		Get-ADUser -Identity $NewUser | Add-ADPrincipalGroupMembership -MemberOf $objSourceUser.memberOf
	}
}

If ($SourceUserID){
	CopyUser $SourceUserID $NewUserID $GivenName $Surname $DisplayName }
Else {
	Write-Host "SourceUserID not specified, script will assume user [$NewUserID] already exist and will Mailbox enabled it only." -ForegroundColor Yellow
}

Try {$UserTemp = Get-User $NewUserID -ErrorAction Stop}
Catch {ExitScript "run [Get-User $NewUserID], confirm user ID exist" $False}

Write-Host "`nGetting smallest Exchange DB that matches filter [$DBFilter]..." -ForegroundColor Green -NoNewLine
$TargetDB = Get-SmallestDB
Write-Host " Found, [$TargetDB] will be used." -ForegroundColor Green 

Write-Host "`nCreating mailbox for [$NewUserID] on [$TargetDB]" -ForegroundColor Cyan
Try {Enable-Mailbox $NewUserID -Database $TargetDB -ErrorAction Stop}
Catch {
	If ($_.Exception.Message -like '*is of type UserMailbox*') {
		Write-Host `t "[$NewUserID] already has a mailbox, continuing to next step " -ForegroundColor Yellow}
	Else {ExitScript "run [Enable-Mailbox $NewUserID -Database $TargetDB]" $True}}

Write-Host "Enabling retention policy and single item recovery" -ForegroundColor Cyan
Try {Set-Mailbox  $NewUserID  -RetentionPolicy $RetentionPolicy -SingleItemRecoveryEnabled $true  -CustomAttribute10 $CustomAttrib -ErrorAction Stop}
Catch {ExitScript "run [Set-Mailbox  $NewUserID  -RetentionPolicy $RetentionPolicy -SingleItemRecoveryEnabled $true]" $True}

If ($AddToGroup) {
	Try {Add-DistributionGroupMember -Identity $Group -Member $NewUserID -BypassSecurityGroupManagerCheck -ErrorAction Stop}
	Catch {
		If ($_.Exception.Message -like '*already a member of the group*') {
			Write-Host `t "Object [$NewUserID] is already in [$Group]" }
		Else {ExitScript "run [Add-DistributionGroupMember -Identity $Group -Member $NewUserID]" $True}}
}

If ($SendWelcome) {
	$objNewUser = Get-ADUser $NewUserID -Properties "EmailAddress"
	$EmailAddress = $objNewUser.EmailAddress
	If ($EmailAddress -eq $Null) {
		Write-Host "New user [$NewUserID] not found, waiting 5 seconds and retying..."
		Start-Sleep -s 5
		$objNewUser = Get-ADUser $NewUserID -Properties "EmailAddress"
		$EmailAddress = $objNewUser.EmailAddress
		If ($EmailAddress -eq $Null) {
			Write-Host "New user still not found, Welcome e-mail not sent. Exiting."
			Exit
		}
	}
	Write-Host "`nSending Welcome message to [$EmailAddress], waiting 10 seconds for mailbox creation process to finish" -ForegroundColor Cyan
	start-sleep 10 # This delay is sometimes needed

	# See http://www.thegenerationv.com/2012/01/using-rich-html-with-send-mailmessage.html for Send-Mail HTML examples
	Try {Send-MailMessage -From $From -To $EmailAddress -Subject $MsgSubject -Body $MsgBody -SmtpServer $SMTPServer -BodyAsHtml}
	Catch {ExitScript "run [Send-MailMessage -From $From -To $EmailAddress -SmtpServer $SMTPServer]" $True}
 }
Posted in Exchange, Script, Technical | Tagged , , | 10 Comments

Need help with your AD or Exchange design or migration? Contact me!

Last year was the biggest year for me, consulting business wise, but this year has started off very slow. I’m guess there are lots of organizations out there waiting for Exchange 2013 SP1, well no need to wait for that CU2 is out and fixes the last few co-existence issues that have prevented me from recommending it to my clients.

My rates vary based on three factors: 1) Length of project, >3 months or >500 hours = lower rate; 2) on-site vs. remote, remote = lower rate; 3) Complexity; architecture and cross-forest migration being the highest rate.

I can assure you that there are very few people in the world with my level of expertise on AD and Exchange.  I am one of less than 20 Exchange MVPs in the US, have been working with Microsoft AD and Exchange since 1996. In this time I have worked on over a 100 migrations and helped manage and migrate over a million users over the last 17 years.

While I would prefer to continue to work for Pro Exchange, a small consulting firm run by my good friend of 15+ years, I am open to full time opportunities. So if you know any good firms that need someone like me (resume & bio link) have them contact me. I’m not interested in relocating, I love CO too much. For the last three years I’ve done 98% of my work remote and would highly prefer to continue to work remote, but would be willing to travel up to 40% for the right project. If you work for a consulting firm and have some projects that you lack the resources in house for, I also do a lot of C2C work and would be happy to put your company hat on when working with your clients.

Of course, if you or an organization you know of is looking to migrate to Exchange 2010 or 2013 or plans on doing an AD migration reach out to me. I can assure you that the project will be done more efficiently than working with one of the big consulting firms and I only bill my clients for the hours I work. So if you have someone on staff that can carry out tasks I delegated to them, which I provide very detailed documentation for, then the hours for doing the implementation and/or migration will be much less.

Posted in Exchange, Microsoft, Personal, Technical | Tagged , , | Leave a comment

Exchange 2010 SP3 RU1 is out

Quick post, more to come later once I have it installed and tested.

EHLO Blog post: Released: Update Rollup 1 for Exchange 2010 SP3

Download SP3 RU1

I’ve updated my list of “Known Exchange 2010 SP3” issues, RU1 fixes one of the three issues I have listed. The fixed issue is where soft deletes fail in Outlook & OWA in on-line mode if they contain certain type of attachments that were generated in a certain way. There are several other issues that it fixes too of course.

Known SP3 RU1 Issues
From EHLO Blog post: Update Rollup 1 for Exchange Server 2010 SP3

Issue with HTML messages and disclaimer transport rules:

There is an  an issue where the messages stick in poison queue and transport continually crashes after this rollup is applied. Error event ID 4999 with source MSExchange Common will be generated with Dr Watson report.

The issue is caused by a transport rule (disclaimer) attempting to append the disclaimer to the end of HTML formatted messages.   When this occurs, messages will be placed in the poison queue and the transport service will crash with an exception.

Workaround: Disable disclaimer transport rule or uninstall RU1

6/26 Update: There is a hotfix for this issue, you must call PSS and reference KB2859596

Issue with installing RU1:

You cannot install or uninstall Update Rollup 1 for Exchange Server 2010 SP3 on the double-byte character set (DBCS) version of Windows Server 2012 if the language preference for non-Unicode programs is set to the default language.

Workaround: Change Language setting:

  1. In Control Panel, open the Clock, Region and Language item, and then click Region.
  2. Click the Administrative tab.
  3. In the Language for non-Unicode programs area, click Change system locale.
  4. On the Current system locale list, click English (United States), and then click OK.

After you successfully install or uninstall Update Rollup 1, revert this language setting, as appropriate.

We have identified the cause of this problem and plan to resolve it in a future rollup, but did not want to further delay the release of RU1 for customers who are not impacted by it.

Posted in Exchange, Microsoft, Technical | Tagged , , | 3 Comments