Thursday, September 23, 2010

Exchange 2010 Migration Routing Issue

I am seeing more and more migrations from Exchange 2003 to Exchange 2010 every day. Most migrations are being properly tested to discover issues. One of the most common mail flow issues I come across is messages cannot be delivered between Exchange 2003 and Exchange 2010. There are many potential causes for this to break, but I am going to focus on mail flow from Exchange 2003 fails to deliver messages to Exchange 2010. The reason for this focus is because I have seen many Exchange 2003 configurations that do not follow best practices which results in this failure.

Here is a quick summary of how messages are sent between Exchange 2003 and Exchange 2010. When the first Exchange 2010 hub transport server is installed, the installation wizard prompts for an existing Exchange 2003 server to use as a bridgehead server for a new routing group connector. All Exchange 2010 servers belong to the same routing group and leverage AD sites for routing. Once this first Exchange 2010 hub transport server is in place mail flow between Exchange 2003 and 2010 should work thru the routing group connector. Now let’s review the main cause of why messages do not route properly from Exchange 2003 to Exchange 2010.

More and more organizations are using SMTP gateway devices to protect their internal Exchange environment. They are no longer having Exchange route outbound messages using DNS, but instead use a smart host (edge transport, third party appliance, hosting solution, etc). When the Exchange 2003 server was configured to route mail using the smart host it also broke SMTP communications with Exchange 2010. How? The configuration was done quickly by modify the properties of the Default SMTP Virtual Server for the Exchange server.


Exchange 2003 will attempt to deliver all SMTP messages using the smart host under this configuration, even internal messages where the mailbox is on Exchange 2010. Fortunately there is a simple solution to this dilemma.

The first step is to create a new SMTP connector for the routing group.


On the General tab you need to give the connector a name, enable the connector to “Forward all mail through this connector to the following smart host” using the smart host value from your Default SMTP Virtual Server, and add your Default SMTP Virtual Server as a local bridgehead for your connector.


On the Address Space tab you need to add an SMTP address space of * with an associated cost (the lower the cost the higher the priority for the connector) and select whether this connector should be used for the entire organization or just the routing group it is being created within.


You can review the other tabs and determine if you need to update any other settings. For example the Content Restrictions tab has the maximum message size setting.

Once you create this SMTP connector you must go back into your Default SMTP Virtual Server settings and remove the smart host configuration. Then test outbound mail flow from an Exchange 2003 mailbox to the Internet and to an Exchange 2010 mailbox. After mail flow has been validated you have one more decision to make. Your Exchange 2010 hub transport server must have a Send Connector added before the migration is complete. You could create the new Send Connector and test sending a message to the Internet. When the Send Connector is operational, the SMTP connector in the Exchange 2003 routing group you created can be removed. All Internet mail flow for Exchange 2003 will then route thru the routing group connector and out the Send Connector.

Friday, September 17, 2010

Managing Distribution Groups

Managing distribution groups always seems to be changing from one version of Exchange to the next. In Exchange 2003 you would modify the properties of the group by updating the Managed By tab and enabling the Manager can update membership list. To allow additional managers to the distribution list you needed to manually update the Active Directory security settings for the group.


You granted users permission to modify distributions groups in 2007 by running the following: Get-DistributionGroup DGName Add-AdPermission –User manager –AccessRights WriteProperty –Properties Member. Adding additional managers became a simple task. You could also add a manager within the Exchange Management Console by modifying the properties of the distribution group on the Group Information tab.


Exchange 2010 introduced the new RBAC (Role Based Access Control) model. Anyone who has already migrated or began migrating mailboxes may have experienced the issue where users cannot modify groups they could previously. There is an excellent article that describes the cause and solution for this issue on the Exchange Team site. You may have most of your users working after running the script, while others still get the dreaded error.


As an administrator you may get the following error when you run the Add-DistributionGroupMember cmdlet: You don't have sufficient permissions. This operation can only be performed by a manager of the group.

Why do you as an administrator get that error when trying to add members? Why do your users still get an error trying to update their groups? If you open the properties of the distribution group and look at the Group Information tab, you will notice that the appropriate users are not present under the managed by list. One reason they are missing is the script used to grant users permission to modify groups in Exchange 2007 did just that and only that. Exchange 2007 also does not add anyone when the group is created (Exchange 2010 automatically adds the group creator).



Organizations that have many distribution groups and assigned permissions to modify these groups to several users have a daunting task to resolve this issue. Unless there was a way to script a solution…

The first step for resolving this issue is identifying the groups that have had their permissions modified to allow users to update group membership. To do this we want to identify all groups where there are permissions that are not inherited (we added the permission using the Add-AdPermission cmdlet), the access right is WriteProperty, and the Properties include Member (everything that was used in Exchange 2007 to grant permissions).

$groups = Get-DistributionGroup | Get-ADPermission | where { $_.Isinherited -eq $false -and $_.AccessRights -like "WriteProperty" -and $_.Properties –like “Member” }

Now our variable $groups contains a list of permissions that includes the group name and the user. We need to process each entry converting the User attribute value into a usable string variable and then using that value to update the group’s ManagedBy value. If anyone has updated a user’s email addresses using the shell you will see the similarity here. The script takes the adds our new entry into the ManagedBy array and then updates the group's ManagedBy attribute with the updated array.

foreach($g in $groups) { $user = $g.user.tostring().substring($g.user.tostring().indexof("\") + 1);
$group = Get-DistributionGroup $g.identity;
$group.ManagedBy += ( Get-Mailbox $user).distinguishedName; Set-DistributionGroup $group -ManagedBy $group.ManagedBy }


I recommend testing this script prior to running it in production. If you do not have a lab environment, you can create test distribution groups in a separate organizational unit and update the Get-DistributionGroups to include the –OrganizationalUnit switch.

Tuesday, September 7, 2010

Exchange AutoDiscover and Web Services

One of the most commonly seen question/issue around Exchange 2007 and 2010 is the AutoDiscover service and the Exchange Web Services. These two components of Exchange must be configured properly, otherwise many features within Outlook 2007 or later clients will not function properly (Out of office, free/busy information, etc). The goal of this article is to give you a better understanding of how to design and configure Exchange for your environment. It is not possible to cover every possible scenario, but this should provide a baseline for your decisions.

The most critical piece of deploying Exchange is DNS. I know you’ve heard a countless number of times how important DNS is for deploying Microsoft products, but it is the truth. Without knowledge of how your DNS zones are configured both internally and externally, you cannot successfully deploy Exchange. You must decide what FQDN(s) your Exchange environment utilizes based on the DNS configuration. You must decide upon the URL(s) that your environment will utilize so that you can request the proper certificate for your Client Access Server.

Before we begin looking at possible design configurations, let’s quickly review how these two features are integrated and why DNS is so important:

When the Outlook client is started it will query for a service connection point for the AutoDiscover service. The AutoDiscover service will provide the Outlook client with the URL values for the Exchange Web Services. These web service URL values provide the Outlook client access to the Out of Office scheduler, Offline Address Book download, and free/busy information.

Internally the client randomly select this SCP within the Configuration container in Active Directory (CN=Configuration,CN=Services,CN=Microsoft Exchange,CN=ExOrgName,CN=Administrative Groups,CN=Exchange Administrative Group,CN=Servers,CN=ExServerName,CN=Protocols,CN=Autodiscover). This piece is important when you have CAS servers in multiple Active Directory sites. You do have some control into which SCP is used by setting the AutoDiscoverSiteScope value for the CAS server. Clients within the site specified by the AutoDiscoverSiteScope will default to using one or more of those SCPs. (Note: When all CAS servers are configured with the same URL the AutoDiscoverSiteScope value becomes dependent on your DNS configuration).

Right now you might be thinking “what is this service connection point” and “how do you configure it”. The SCP is the AutoDiscover URL for the Client Access Server. The default value for this URL is https://servername.contoso.com/Autodiscover/Autodiscover.xml. You can modify this default value by using the Set-ClientAccessServer -AutoDiscoverServiceInternalURI.

The Outlook client’s behavior is different when it is located outside the local network. In this scenario it will attempt to contact the AutoDiscover service by using the URLs https://contoso.com/Autodiscover/Autodiscover.xml and https://autodiscover.contoso.com/Autodiscover/Autodiscover.xml.

Let’s look at the possible DNS configurations that you may encounter and how you can deploy the Autodiscover service accordingly.

External DNS = Internal DNS
In this configuration both your external DNS server(s) and internal DNS server(s) have a forward lookup zone for your domain (contoso.com). This does not mean that your Active Directory domain name matches your public domain name. It simply means your internal DNS server contains a forward lookup zone that matches your public domain name. Typically the external DNS server contains only records for external resources and the internal DNS server contains records for both internal and external resources. There are a couple deployment scenarios with this DNS setup and they are dependent on the type of certificate you choose to obtain.

Single name certificate (mail.contoso.com)
Yes, you can use a single name certificate with Exchange 2007/2010. In this deployment you utilize a single URL for the entire Exchange configuration. Your users will utilize this URL for Outlook Web Access/App (internally and externally) and for ActiveSync. This scenario utilizes either:
1. An Outlook Anywhere configuration that uses an SSL certificate with redirection
2. If your external DNS server is capable of hosting SRV records you can create an SRV record for autodiscover that points to your FQDN of mail.contoso.com (http://support.microsoft.com/kb/940881).

The following example provides the cmdlets that can be used to configure a client access server in this deployment:

##Enable Outlook Anywhere for your CAS server
Enable-OutlookAnywhere EXCAS -ExternalHostname mail.contoso.com -ClientAuthenticationMethod Basic -SSLOffloading:$False

##Configure the SCP for internal Outlook clients
Set-ClientAccessServer EXCAS –AutoDiscoverServiceInternalUri https://mail.contoso.com/Autodiscover/Autodiscover.xml

##Configure the offline address book settings
Set-OabVirtualDirectory EXCAS\OAB* -ExternalUrl https://mail.contoso.com/OAB -InternalUrl https://mail.contoso.com/OAB

##Configure the web services which include OOF and free/busy information
Set-WebServicesVirtualDirectory EXCAS\EWS* -ExternalUrl https://mail.contoso.com/EWS/Exchange.asmx -InternalUrl https://mail.contoso.com/EWS/Exchange.asmx -BasicAuthentication:$True-WindowsAuthentication:$True

##Configure the unified messaging settings
Set-UMVirtualDirectory EXCAS\Unified* -ExternalUrl https://mail.contoso.com/UnifiedMessaging/Service.asmx -InternalUrl https://mail.contoso.com/UnifiedMessaging/Service.asmx -BasicAuthentication:$True -WindowAuthentication:$True


The DNS configuration for this scenario is shown in the following table:
Hostname Record Internal DNS External DNS
mail.contoso.com A 10.1.1.100 66.55.44.33
autodiscover.contoso.com A 10.1.1.200 66.55.44.32
_autodiscover._tcp.contoso.com SRV mail.contoso.com mail.contoso.com

Note: The A record is using an SSL certificate with redirection.

SAN certificate (mail.contoso.com and autodiscover.contoso.com)
This deployment is almost exactly the same as the single name certificate scenario. Once again your users will be required to know only a single URL to access their mail. Only the CAS server will utilize a the second subject name for the SCP used by Outlook. Your SAN certificate can also include the FQDN of your CAS servers which would reduce the number of settings you would need to update.

The following cmdlets can be used to configure a client access server in this deployment:

##Enable Outlook Anywhere for your CAS server
Enable-OutlookAnywhere EXCAS -ExternalHostname mail.contoso.com -ClientAuthenticationMethod Basic -SSLOffloading:$False

##Configure the SCP for internal Outlook clients
Set-ClientAccessServer EXCAS –AutoDiscoverServiceInternalUri https://autodiscover.contoso.com/Autodiscover/Autodiscover.xml

##Configure the offline address book settings
Set-OabVirtualDirectory EXCAS\OAB* -ExternalUrl https://mail.contoso.com/OAB -InternalUrl https://mail.contoso.com/OAB

##Configure the web services which include OOF and free/busy information
Set-WebServicesVirtualDirectory EXCAS\EWS* -ExternalUrl https://mail.contoso.com/EWS/Exchange.asmx -InternalUrl https://mail.contoso.com/EWS/Exchange.asmx -BasicAuthentication:$True-WindowsAuthentication:$True

##Configure the unified messaging settings
Set-UMVirtualDirectory EXCAS\Unified* -ExternalUrl https://mail.contoso.com/UnifiedMessaging/Service.asmx -InternalUrl https://mail.contoso.com/UnifiedMessaging/Service.asmx -BasicAuthentication:$True -WindowAuthentication:$True


The DNS configuration for this scenario is shown in the following table:
Hostname Record Internal DNS External DNS
mail.contoso.com A 10.1.1.100 66.55.44.33
autodiscover.contoso.com A 10.1.1.100 66.55.44.33
cassrv.contoso.com A 10.1.1.100 N/A


External DNS <> Internal DNS
In this configuration your external DNS server is configured with a forward lookup zone for your public domain name (contoso.com) and your internal DNS server is configured with a forward lookup zone for your internal domain name (contoso.local). With this type of DNS configuration you only have one option (without the use of a reverse proxy such as Forefront Threat Management Gateway) and that is to use a SAN certificate. The reason you need a SAN certificate is because your DNS requires unique URLs for external and internal access.

At a minimum your certificate will require the following subject names:
Mail.contoso.com
Autodiscover.contoso.com
Mail.contoso.local

Right now you might be looking at the above list and thinking, wait… you forgot autodiscover.contoso.local. Remember, this is the minimal names required to make this configuration work. You can add autodiscover.contoso.local and values for your CAS servers (excas.contoso.local), but they are not needed and may only add cost to your certificate.

Now that we know what the minimum certificate requirements are, let’s look at the cmdlets for configuring the CAS server:

##Enable Outlook Anywhere for your CAS server
Enable-OutlookAnywhere EXCAS -ExternalHostname mail.contoso.com -ClientAuthenticationMethod Basic -SSLOffloading:$False

##Configure the SCP for internal Outlook clients
Set-ClientAccessServer EXCAS –AutoDiscoverServiceInternalUri https://mail.contoso.local/Autodiscover/Autodiscover.xml

##Configure the offline address book settings
Set-OabVirtualDirectory EXCAS\OAB* -ExternalUrl https://mail.contoso.com/OAB -InternalUrl https://mail.contoso.local/OAB

##Configure the web services which include OOF and free/busy information
Set-WebServicesVirtualDirectory EXCAS\EWS* -ExternalUrl https://mail.contoso.com/EWS/Exchange.asmx -InternalUrl https://mail.contoso.local/EWS/Exchange.asmx -BasicAuthentication:$True-WindowsAuthentication:$True

##Configure the unified messaging settings
Set-UMVirtualDirectory EXCAS\Unified* -ExternalUrl https://mail.contoso.com/UnifiedMessaging/Service.asmx -InternalUrl https://mail.contoso.local/UnifiedMessaging/Service.asmx -BasicAuthentication:$True -WindowAuthentication:$True


The DNS configuration for this scenario is shown in the following table:
Hostname Record Internal DNS External DNS
mail.contoso.com A N/A 66.55.44.33
autodiscover.contoso.com A N/A 66.55.44.33
mail.contoso.local A 10.1.1.100 N/A

Internal DNS Only
It is a possible to deploy Exchange for internal access only, but this is not a common scenario. Deployments that meet this DNS design can utilize the same configuration steps as the Single name certificate (External DNS = Internal DNS). This design allows you to deploy an internal certificate authority and acquire your certificate through it. You can create a group policy object that adds your internal CA to the Trusted Root Certificate Authorities for all machines in the domain.

Multiple Domain Names
At this point we have covered the simplest of scenarios where your organization only has one external facing domain name. Now we need consider environments that have multiple domain names (ex. contoso.com and fabrikam.com). These scenarios must still use the same concepts discussed earlier regarding DNS, then decide what the user experience will be. In the situation where contoso.com is the parent company and fabrikam.com was an acquisition, you may want all users to utilize a single URL (single-name certificate). Or these might be two unique business units within your organization and you need each business unit to use a separate URL (SAN certificate). In the end it all comes down to how your DNS is configured and what URL(s) you users will use that determine your certificate requirements and your Exchange configuration.

Non-Internet Facing Client Access Server
The last topic we should consider is the configuration on a CAS server that is non-internet facing, or a CAS server that cannot be directly accessed via the Internet. The first thing you must note for this type of CAS server is that the ExternalUrl values for the virtual directories will be blank. This is required so that the Internet facing CAS server can proxy the request appropriately. (Note: The owa and ActiveSync virtual directories on the non-Internet facing CAS must have Windows Integrated authentication enabled as well for the proxy to work)

Now we need to determine our certificate needs for this configuration. This is once again determined by the DNS design, but the non-Internet facing CAS server throws a wrench into it. Yes, it isn't that simple, but it isn't that much more complex either. There are two easy solutions 1. Utilize a SAN certificate and include the FQDN of the non-Internet facing server or 2. Utilize two certificates where the certificate installed on the Internet facing server(s) is from the third-pary CA and the other is from an internal CA and only has the FQDN of you non-Internet facing CAS server. Either way, your users could remember a single URL and be directed to the appropriate CAS server.

For more information on Client Access proxy and redirection check out this article by Microsoft. (http://technet.microsoft.com/en-us/library/bb310763.aspx)

Conclusion
It is important to understand how the Outlook client connects to the AutoDiscover service and what URL values Outlook uses for the Web Services. Knowing that allows you to ensure you have the proper DNS configuration for Exchange and the correct domain names associated with your Exchange certificate. In this article I provided a few possible deployment scenarios and how you can configure Exchange for each one. These are not the only possible configuration methods, but are basic scenarios that should give you a roadmap to your solution.

Key points to remember:
1. The ExternalHostname value from Get-OutlookAnywhere is the URL used by the Autodiscover service to autoconfigure an Outlook profile
2. The AutoDiscoverServiceInternalURI value is the service connection point used by Outlook
3. External clients will attempt to connect to the Autodiscover service using contoso.com and autodiscover.contoso.com by default
4. Internal clients should not get any certificate warnings/errors or be prompted for a password when browsing to an InternalURL value for the web services

Please send any questions, comments and/or suggestions to my email address jim at endital dot com. Thanks.

For more detailed information on the Autodiscover service please visit the Whitepaper on Microsoft's site (http://technet.microsoft.com/en-us/library/bb332063(EXCHG.80).aspx)

Set Outlook Folder Permissions using Powershell

As an Exchange Administrator, I have been asked numerous times "grant this person access to my folder and all of its subfolders". Prior to Exchange 2010 there was no simple way to assign MAPI permissions to all of these Outlook folders. Exchange 2010 has added the Add-MailboxFolderPermission cmdlet which allows an administrator to now complete this task from the Exchange Management Shell.

You may also notice that Exchange 2010 provided another cmdlet, Get-MailboxFolder. When I saw this I thought "Wow! I can run the Get-MailboxFolder and pipe the Add-MailboxFolderPermission and I'm done." Did you really think it would be that easy? The Get-MailboxFolder cmdlet only runs against the currently logged in user. Yes, you can't run this cmdlet against another mailbox. Take a look at the management role where this cmdlet is available.

Get-ManagementRole -Cmdlet Get-MailboxFolder


Okay. Then how can we use the Add-MailboxFolderPermission to run against a root folder and all of its subfolders? Looking at all the parameters available for the cmdlet there is no recurse (wouldn't that be nice). I was able to accomplish this task in two steps:

1. Get a list of folders from the mailbox
2. Add the permission to the folder

Get-MailboxFolderStatistics

The first thing we need to obtain is the list of folders that we will apply permissions. We can utilize the Get-MailboxFolderStatistics cmdlet for this purpose. The result we want is the FolderPath value that is returned in the format "/Folderpath".

Get-MailboxFolderStatistics owner | Where { $_.FolderPath.Contains("FolderName") -eq $true }

Add-MailboxFolderPermission
Then we can use the Add-MailboxFolderPermission cmdlet to assign the permissions. The format for the folder name is "Mailbox:FolderPath" so we will need to modify the result from earlier to accomodate the expected value. The following example illustrates the example where Jane's manager John wants her to access his Clients folder and all of its subfolders.

ForEach($f in (Get-MailboxFolderStatistics John | Where { $_.FolderPath.Contains("/Clients") -eq $True } ) ) {
$fname = "John:" + $f.FolderPath.Replace("/","\");
Add-MailboxFolderPermission $fname -User Jane -AccessRights Reviewer
}


Conclusion
This is only an example of how you can accomplish this task. Use this with caution and always test prior to running against a production mailbox. The one known issue is the possible results when using the Get-MailboxFolderStatistics cmdlet. You need to adjust your where clause appropriately so that you don't get unwanted results.

Please send me any questions, comments, and/or suggestions to jim at endital dot com. Thanks.

Friday, July 2, 2010

Exchange 2010 Public Folders and the NT User Permission

I am currently working on a transition from Exchange 2007 to 2010. I like to use these types of projects to work on cleaning up the current environment before performing the upgrade. In this post I am going to talk about something every Exchange administrator loves... public folders. Why does everyone cringe when this topic comes up? We should be happy that Microsoft didn't build their replication technology for mailbox databases off of public folder replication. That would have been the end of Exchange. Back to the point. Everyone who has ever checked permissions on a public folder has seen this:



Well, now the question becomes: how can I easily remove these zombie accounts (terminology from back in the Exchange 5.5 days)? You could manually use either Outlook or PFDavAdmin to remove these permissions. But what if you had thousands of folders to process? I doubt any of us have that kind of time or patience. Exchange 2007 introduced Powershell, so let's look there. Here I have an example folder with its current folder permissions:




Thanks to PowerShell this task is going to be really simple. You just need to run the following command against this folder to remove the zombie account permissions from the parent and all subfolders:

Get-PublicFolder "\Folder1" -Recurse Get-PublicFolderClientPermission Where { $_.User.ToString().Contains("NT User:") -eq $true } Remove-PublicFolderClientPermission -Confirm:$False

Then when you check your folder permission it should look like the following:



Just a word of caution is the amount public folder replication traffic that this process may cause is dependent on the number of public folders and the number of permissions that were removed. The sample script above will also remove accounts that had their mailboxes removed. These accounts would appear as "NT User:DOMAIN\Username".

Friday, June 25, 2010

Exchange 2010 Recovery Database and Backup Exec 2010

Tonight I finally got around to testing the restore of an Exchange 2010 database. The server has only been online two weeks. The process was so simple I thought I would share it with everyone.

  1. The first thing I did was create the restore database using the New-MailboxDatabase cmdlet: New-MailboxDatabase -Recovery -Name RDB -Server Ex2010
  2. Then I selected New job under the Restore Tasks in Backup Exec 2010
  3. Selected the database to restore under Selections
  4. Selected to Redirect Exchange sets, Redirect using Volume Shadow Copy Service snapshot provider, and entered the server name under Restore to Database or Recovery Database
  5. Selected Commit after restore completes and Mount database after restore under Settings/Microsoft Exchange

That was it. The restore took about 15 minutes to complete and when it was finished the database appeared in the console as mounted. I can now sleep peacefully knowing this database is protected.

D9Z9A3XVCWF5

Monday, July 13, 2009

NDR message caused by delegate

One question that comes up often is why did I get this undeliverable message (NDR) when I send a meeting request to this user? Even better than the question is tracking down the answer. Well, I always like to script common tasks like this and I developed the following script. The script requires the a copy of the NDR message.

$start = Read-Host "Enter the start time"
$subject = Read-Host "Enter the message subject"
$start = [datetime]$start
$end = $start.AddMinutes(10)
$hub = Read-Host "Enter the transport server"
$mbx = Read-Host "Enter the mailbox server"
$mid = Read-Host "Enter the message ID"

$messages = Get-MessageTrackingLog -Server $mbx -Start $start -End $end -MessageSubject $subject -MessageId $mid -ResultSize unlimited Where { $_.SourceContext.Contains("MessageClass:IPM.Schedule.Meeting.Request") -eq $True -And $_.Server.Hostname -ieq $hub }
foreach($m in $messages)
{ $startChar = $m.SourceContext.IndexOf("Mailbox:") + 8;
$mbx = $m.SourceContext.Substring($startChar,36);
Get-Mailbox $mbx
}

You can reduce the lines of code, but I expanded it so that it is easier to follow what each line accomplishes.