Changing Security Groups to Distribution Groups

In Exchange Server 2010, you cannot create a new Distribution Group that is not a Universal group. If your Exchange 2010 installation was upgraded from a prior release of Exchange Server, you may find Distribution Groups created in those earlier versions of Exchange that are not Universal. As I’ve discussed in Exchange Server 2007 and Universal Groups, Exchange simply Works Better ™ with Universal Groups.

Just kidding on the ™ – but it does work better.

So, I’ve got customers who have a large investment in vbscript automation. Of course, I feel that PowerShell is a better solution, but ripping-and-replacing thousands of lines of vbscript takes quite a while. One of the customer’s vbscript applications created distribution lists in Exchange 2003 (as you may or may not be aware, as long as a few key attributes were set on an object, in Exchange 2003 the Recipient Update Service would process that object automatically – such is not true in Exchange 2007). But that application does not work properly in Exchange 2007 or Exchange 2010.

Instead of re-writing a thousand-line vbscript, with all the testing and debugging that that would’ve entailed, it seemed prudent to simply “fix the problem”. In this case, there were two problems:

[1] Sometimes, a global group is created instead of a universal group, and

[2] The group needs to be mail-enabled.

This can be done, in true PowerShell fashion, in a “one-liner”. But it’s a LONG one-liner, and much easier to read when split up. This is a technique that may come in handy for you.

##
## Fix-Security-groups.ps1
## Michael B. Smith
## September 30, 2010
##
## Examine each group present in the Groups OU. If the group is a security
## group, then ensure that it is a Universal group and mail-enable it to become
## a distribution group.
##
get-group -organizationalUnit sub.example.com/Accounts/Groups |?  `
        {$_.RecipientType -eq 'Group'} |% { `
        if( $_.GroupType -match 'Global' ) `
        { `
                set-group $_.Identity -Universal; `
        } `
        Enable-DistributionGroup $_.Identity; `
}

Until next time…

If there are things you would like to see written about, please let me know.


Follow me on twitter! : @EssentialExch

Generating a report on Distribution Groups and their Membership

A common request is to get a list of all distribution groups and the members contained in that distribution group. The question came up on a mailing list I frequent today, and my initial response was a PowerShell “one-liner” (actually five lines, but all a single PowerShell statement).

The one-liner worked, but it had a couple of limitations: it wasn’t very pretty (that is, the output was formatted poorly) and if there were than one user set to manage the distribution group, that would be reportedly incorrectly. It was also slower than it had to be.

Note: a distribution group may also be a security group. From an Exchange Server perspective, the important thing is whether the group is mail-enabled or not.

So, I took that five-liner, cleaned it up, fixed the ManagedBy reporting bug, and sped it up (by using an embedded pipeline to report on the members contained in a distribution group). That turned it into a 50+ line script (which includes 10 lines of comments!). As I said on the mailing list – you can generate quick results with PowerShell. That’s good enough for most admins. But if you want it pretty and “production quality” then it’s going to take a little more time.

You can take this report and pipe it to out-string in order to save the output to a disk file. Then you can inspect the file later, email it, copy-n-paste it, whatever you want.

Here is the script:

 

##
## Report-DistributionGroupsAndMembers.ps1
## v1.1

##
## Michael B. Smith
## http://TheEssentialExchange.com
## August, 2010
##
## Requires Exchange Management Shell
## Should work with either PowerShell v1 or v2
## Tested on both Exchange 2007 and Exchange 2010

##

function formatManager($formatstring, $manager)
{
	$formatstring -f $manager.Name, ($manager.Parent.ToString() + "/" + $manager.RDN.ToString().SubString(3))
}

Get-DistributionGroup -ResultSize Unlimited |% {
	$group = $_
	"Group Name & Identity: {0}, {1}" -f $group.Name, $group.Identity
	$managedBy = $group.ManagedBy
	if( $managedBy -is [Microsoft.Exchange.Data.Directory.ADObjectId] )
	{
		formatManager "Group manager: {0}, {1}" $managedBy
	}
	elseif( $managedBy.Count -gt 1 )
	{
		[bool]$first = $true
		foreach( $manager in $managedBy ) 
		{
			if( $first ) 
			{
				formatManager "Group managers: {0}, {1}" $manager
				$first = $false
			}
			else
			{
				formatManager "                {0}, {1}" $manager
			}
		}
	}
	elseif( $managedBy.Count -gt 0 )
	{
		formatManager "Group manager: {0}, {1}" $managedBy[0]
	}

	"Members:"
	Get-DistributionGroupMember -Identity $group.Identity -ResultSize Unlimited |% {
		foreach( $member in $_ )
		{
			"`t$($member.Name)"
		}
	}
	"---"
}

 

Until next time…

If there are things you would like to see written about, please let me know.

–Edit on August 20, 2010
The original script would not display ManagedBy on Exchange 2007 (I’m running Exchange 2010). This is because ManagedBy in Exchange 2010 always returns an array-type object (it can contain multiple users). In Exchange 2007, the ManagedBy value is always a singleton. The required changes to the script are in red.

Michael B.


Follow me on twitter: @EssentialExch

Using PowerShell to determine your elevation status (UAC)

On a mailing list recently, SBS author and PowerShell MVP Charlie Russel posted how he used PowerShell to check whether a given PowerShell session was elevated. He also used that information to change the background color of the session (elevated shells are dangerous things!).

I took Charlie’s code and expanded it a bit and “made it mine”. I often need to know whether I’m running as an administrator, a server operator, and/or a backup operator. This is because I write lots of Exchange PowerShell scripts (which often require server operator or local administrator privileges) and backup PowerShell scripts (which require the user running the script to be a backup operator). The same technique Charlie used can also be used to determine those things. The key element here is the IsInRole() method of System.Security.Principal.WindowsPrincipal. For detailed information about that .Net class, google/bing for System.Security.Principal.WindowsPrincipal.

The IsInRole() method operates against a WindowsIdentity object. This is obtained from the current process.

The script is pretty self-explanatory. It is designed to be dot-sourced so the functions can be used within your current script. I’ve also included Charlie’s functionality for changing the background of an elevated shell session.

Without further ado….

##
## IsProtectedRole.ps1
##
## Contains functions for identifying protected roles the current user has tokens for.
##
## Intended for dot-sourcing.
##
## based on code from Charlie Russell (www.scribes.com).
##

$identity  = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object System.Security.Principal.WindowsPrincipal( $identity )

##
## Starting with Vista/Server2008, if UAC is enabled, then a user who has either direct
## or indirect membership in the BuiltIn\Administrators group is assigned not one but
## TWO security tokens. One of those tokens has the administrator privilege, and one
## does not. In order for you to have administrator privilege in PowerShell, you must
## start the PowerShell session from: Angel another elevated shell (either PowerShell or
## cmd.exe), or Beer elevate the session when you start the shell (i.e., "Run As Administrator").
##

function IsAdministrator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator )
}

function IsUser
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::User )
}

function IsPowerUser
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::PowerUser )
}

function IsGuest
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Guest )
}

function IsAccountOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::AccountOperator )
}

function IsSystemOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::SystemOperator )
}

function IsPrintOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::PrintOperator )
}

function IsBackupOperator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::BackupOperator )
}

function IsReplicator
{
	$principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Replicator )
}

function MarkAdministratorShell
{
	If (IsAdministrator)
	{
		$script:effectivename = "Administrator"
		$host.UI.RawUI.Backgroundcolor = "DarkRed"
		$host.UI.RawUI.Foregroundcolor = "White"
	}
	else
	{
		$script:effectivename = $identity.name
		$host.UI.RawUI.Backgroundcolor = "White"
		$host.UI.RawUI.Foregroundcolor = "DarkBlue"
	}

	clear-host
}

# write-host 'Administrator' (IsAdministrator)
# write-host 'User' (IsUser)
# write-host 'PowerUser' (IsPowerUser)
# write-host 'Guest' (IsGuest)
# write-host 'AccountOperator' (IsAccountOperator)
# write-host 'SystemOperator' (IsSystemOperator)
# write-host 'PrintOperator' (IsPrintOperator)
# write-host 'BackupOperator' (IsBackupOperator)
# write-host 'Replicator' (IsReplicator)

Until next time…

If there are things you would like to see written about, please let me know.

 


Follow me on twitter: @EssentialExch

Exchange Email Address Template Objects in PowerShell

Exchange has a very rich set of objects which are used and created by the various Exchange cmdlets. Unfortunately, these objects (excepting those used by Exchange Web Services) are poorly documented – and the documentation which is available is often incorrect or misleading.

I ran into that problem this past week.

To understand my particular issue, let’s review a little history. Exchange 2000 and Exchange 2003 didn’t have the concept of individual “accepted domains”. Instead, you usually used Recipient Policies to identify the accepted domains. Recipient Policies were also used to create and manage Mailbox Manager policies.

In Exchange 2007, all of the capabilities of Recipient Policies were split into multiple features: Accepted Domains, E-mail Address Policies, and Managed Folder Mailbox policies. In Exchange 2010, Managed Folder Mailbox policies have been deprecated and replaced by Retention Policies.

However, some capabilities of these features are not available in the Exchange 2007/2010 GUI (but were in the Exchange 2000/2003 GUI). One of these hidden features is to have both enabled and disabled address templates in an E-Mail Address Policy. In the case of a disabled address template, a particular e-mail address domain can be manually assigned to a given Exchange object but that e-mail address domain will not be automatically assigned even if the object otherwise meets the requirements of the recipient filter assigned to the E-Mail Address Policy (such as a company name, a conditional attribute, group membership, etc.).

Whew.

So what happens when you need to disable an existing e-mail address template?

Well, you do it in PowerShell. (Long lead up to an obvious response, right?) And you do it with the obvious PowerShell cmdlet: Set-EmailAddressPolicy.

What would seem to make sense that the command would be something like:

Set-EmailAddressPolicy ‘Default Policy’ -Add -DisabledEmailAddressTemplates ‘@example.com’

…but that doesn’t work. Aside from the fact that there is no Add or Remove parameter to Set-EmailAddressPolicy, you will eventually figure out that whatever value is provided to the EnabledEmailAddressTemplates and the DisabledEmailAddressTemplates parameters overwrite the values previously there. Well, ain’t that a kick?

To change an address template collection, you must modify the existing collection and resubmit the modified value to Set-EmailAddressPolicy.

So what’s the problem? The problem is the type of the required argument. The EnabledEmailAddressTemplates and DisabledEmailAddressTemplates parameters take a parameter of type Microsoft.Exchange.Data.ProxyAddressTemplateCollection. This is an enumerated collection (a fancy name for an array that you can use with a foreach(), or index it, or use the Item() method to access elements of the collection). Individual items of the collection are of type Microsoft.Exchange.Data.ProxyAddressTemplate or Microsoft.Exchange.Data.SmtpProxyAddressTemplate.

To add or remove items from the collection, you use the normal methods available to collections – that is, the Add() and Remove() methods. However, to use the Add() or Remove() methods, you need to have an object of type Microsoft.Exchange.Data.ProxyAddressTemplate or of type Microsoft.Exchange.Data.SmtpProxyAddressTemplate.

How the heck do you get one of those?

In general, with .Net objects, you create objects using a constructor. In PowerShell, that translates to the New-Object cmdlet. So my normal process is to begin by using Google/Bing to search for the object name. The first or second hit is usually the MSDN web page that describes the class. Then, I read the page, find the appropriate constructor and bam! I am done. This is the method I followed in an earlier article: More Multi-valued Parameters in PowerShell (SourceTransportServers in Set-SendConnector).

But it doesn’t always work. I refer you back to the first paragraph. Many Exchange objects are poorly documented and the documentation that is present is often wrong. As an exercise, I invite you to Google/Bing the objects we are interested in today: Microsoft.Exchange.Data.ProxyAddressTemplate or Microsoft.Exchange.Data.SmtpProxyAddressTemplate. Read the MSDN web pages for the class, especially the page on constructors.

Once you’ve done that reading, you’ll try this:

$template = New-Object Microsoft.Exchange.Data.ProxyAddressTemplate(‘smtp’, ‘@example.com’)

which will not work. Then you’ll try:

$template = New-Object Microsoft.Exchange.Data.ProxyAddressTemplate(‘smtp:@example.com’)

which also will not work. Then you’ll try to get a raw object:

$template = New-Object Microsoft.Exchange.Data.ProxyAddressTemplate

which again will not work.

Then, if you are like me, you’ll spend the next couple of hours banging your head against the wall getting nowhere. After sleeping on the problem, I did come up with a very unsatisfying work-around. Since, in this case, we are trying to take a “currently enabled” object and make it disabled, we should be able to use a reference to the existing object. That solution looks like the below:

	$template = '@example.com'

	$policy = Get-EmailAddressPolicy 'Default Policy'

	$EnabledAddresses  = $policy.EnabledEmailAddressTemplates
	$DisabledAddresses = $policy.DisabledEmailAddressTemplates

	$objTemplate = $null

	foreach ($addr in $EnabledAddresses)
	{
		if ( $addr.AddressTemplateString -ieq $template )
		{
			"found $template"
			$objTemplate = $addr
			break
		}
		"skipped " + $addr.AddressTemplateString
	}

	if ( $objTemplate )
	{
		$EnabledAddresses.Remove( $objTemplate )
		$DisabledAddresses.Add( $objTemplate )

		$policy |
			Set-EmailAddressPolicy -EnabledEmailAddressTemplates $EnabledAddresses `
					       -DisabledEmailAddressTemplates $DisabledAddresses
	}

That, however, is a kludgey hack. In the above solution, we are using a reference to an existing object to change the policies. That will not work in many use-cases; for example where you want to add a new address template, whether enabled or disabled. You will find that you can’t modify the objects returned from Get-EmailAddressPolicy – they are marked read-only.

So, I asked some people who know a lot more about PowerShell than I. Shay Levy, a PowerShell MVP, pointed out that I was making it too hard and that this works:

$objTemplate = [Microsoft.Exchange.Data.ProxyAddressTemplate]’smtp:@example.com’

So, I slapped myself upside the head and said “Of course! ::Parse() is also a hidden constructor!” What that means, in English, is that the above statement is equivalent to:

$objTemplate = [Microsoft.Exchange.Data.ProxyAddressTemplate]::Parse( ‘smtp:@example.com’ )

and to:

$objTemplate = ‘smtp:@example.com’ -as [Microsoft.Exchange.Data.ProxyAddressTemplate]

PowerShell has a built-in capability, using a static method on an object, to take a string and attempt to coerce that string into the named object. In this case, a Microsoft.Exchange.Data.ProxyAddressTemplate. That static method must be named Parse() for PowerShell to automatically use the capability. You can see the static methods on this class using the below command:

[Microsoft.Exchange.Data.ProxyAddressTemplate] | Get-Member -static

Oisin Grehan, another PowerShell MVP, also pointed out that this is a perfect opportunity to use a filter. A filter is a PowerShell feature, somewhat uncommonly used, for processing objects in the pipeline. For example, to define a couple of useful filters:

	filter ConvertTo-ProxyAddressTemplate
	{
		$_ -as [Microsoft.Exchange.Data.ProxyAddressTemplate]
	}

	filter ConvertTo-SmtpProxyAddressTemplate
	{
		$_ -as [Microsoft.Exchange.Data.SmtpProxyAddressTemplate]
	}

These filters would take input from the pipeline and convert the pipeline input into the desired objects. For example:

	[PS] C:\S>'@example.com', '@sub1.example.com', '@sub2.example.com' | ConvertTo-SmtpProxyAddressTemplate

	AddressTemplateString      : @example.com
	ProxyAddressTemplateString : smtp:@example.com
	Prefix                     : SMTP
	IsPrimaryAddress           : False
	PrefixString               : smtp

	AddressTemplateString      : @sub1.example.com
	ProxyAddressTemplateString : smtp:@sub1.example.com
	Prefix                     : SMTP
	IsPrimaryAddress           : False
	PrefixString               : smtp

	AddressTemplateString      : @sub2.example.com
	ProxyAddressTemplateString : smtp:@sub2.example.com
	Prefix                     : SMTP
	IsPrimaryAddress           : False
	PrefixString               : smtp

So, given what we know now, what does the script look like? There are some similarities, but now it doesn’t feel like a hack and it is much easier to read and understand:

	$objTemplate = '@example.com' | ConvertTo-SmtpProxyAddressTemplate

	$policy = Get-EmailAddressPolicy 'Default Policy'

	$EnabledAddresses  = $policy.EnabledEmailAddressTemplates
	$DisabledAddresses = $policy.DisabledEmailAddressTemplates

	$EnabledAddresses.Remove( $objTemplate )
	$DisabledAddresses.Add( $objTemplate )

	$policy |
		Set-EmailAddressPolicy -EnabledEmailAddressTemplates $EnabledAddresses `
				       -DisabledEmailAddressTemplates $DisabledAddresses

So, what is the lesson learned? Don’t forget about ::Parse()! And, as almost always, in PowerShell there is often more than one way to skin a cat.

Until next time…

If there are things you would like to see written about, please let me know.


Follow me on twitter: @EssentialExch

Office 2010 Filter Pack for Exchange 2007 and Exchange 2010

One of the prerequisites for both Exchange 2007 and Exchange 2010 is to install the “filter packs”. The filter packs are responsible for “filtering” the content of Microsoft Office documents and passing those contents back to the Indexing Service (ok, it’s not called the Indexing Service anymore – it’s Microsoft Search – and Exchange 2010 uses a slightly customized version of Microsoft Search called “Microsoft Search (Exchange)”).

In Exchange 2003 and before, creating a full-text search index was optional – and “expensive”. Beginning with Exchange 2007, it became cheap (due to Exchange’s use of the much improved Microsoft Search engine) and required. All Outlook Web App (Outlook Web Access) searches and all Outlook (online) searches use that index.

So, with the release of Office 2010, Microsoft has also released an update to the filter packs that support Office 2010 (plus a few other document types). The new filter packs can be installed on Exchange 2007 and Exchange 2010 (and it seems likely that they will be required for Exchange 2010 SP1). Filters are built-in for the following formats:

Legacy Office Filter (97-2003; .doc, .ppt, .xls)
Metro Office Filter (2007 and 2010; .docx, .pptx, .xlsx)
Zip Filter
OneNote filter
Visio Filter
Publisher Filter
Open Document Format Filter

You can download the Microsoft Office 2010 Filter Packs here.

However, you may notice that a common file format is missing! PDF. In order to scan and index PDFs, you need to install a filter available from Adobe, the Adobe PDF iFilter 9 for 64-bit platforms. That will work with both Exchange 2007 and Exchange 2010.

Bharat Suneja, an ex-Exchange MVP who is now working for Microsoft, provides additional information about index generation and scanning on his blog Exchangepedia.(He gave you some stuff I didn’t – and I’ve given you some stuff he didn’t. It all works out!) 🙂

Until next time…

If there are things you would like to see written about, please let me know.


Follow me on twitter: @EssentialExch

Simplifying Life for Exchange Authors

Another Exchange MVP, Pat Richard, posted on Facebook yesterday: It would be nice to be able to import a list of all Exchange related PowerShell cmdlets into the Word and Outlook dictionaries.

Being the helpful guy that I am, I responded: You can do that in one-line of PowerShell.

(That being a famous quote from Jeff Snover, one of the main men behind PowerShell at Microsoft.)

Then I started thinking about it. And well, you CAN do it in one line of PowerShell. It just depends on how clever you want to get and how long a line you are willing to type! Regardless, you should only have to do it once.

Now, be aware, I’m running Office 2010 – file locations might be somewhat different for you.

Let’s build that one liner.

First thing was to find where Word 2010 stored custom words added to the dictionary. F1 (Help) in Word gave me that – CUSTOM.DIC.

Second was to locate the physical file:

PS C:\Users\Administrator> cd \
PS C:\> cmd /c dir custom.dic /s
Volume in drive C has no label.
Volume Serial Number is D888-0076

Directory of C:\Users\Administrator\AppData\Roaming\Microsoft\UProof

05/10/2010 08:50 AM 11,902 CUSTOM.DIC
1 File(s) 11,902 bytes

Total Files Listed:
1 File(s) 11,902 bytes
0 Dir(s) 77,055,504,384 bytes free
PS C:\>

Ah…good. So the filename is:

join-path C:\Users\Administrator\AppData\Roaming\Microsoft\UProof CUSTOM.DIC

or just

C:\Users\Administrator\AppData\Roaming\Microsoft\UProof\CUSTOM.DIC

If we examine the file, we see it’s a simple Unicode file containing one token/symbol per line.

How do we get the list of Exchange commands? Get-ExCommand, of course. But…if you aren’t running the command on an Exchange server or on a workstation where the Exchange Management Tools are installed (e.g., you are using remote PowerShell to connect to an Exchange server), you won’t have Get-ExCommand. It’s a non-exported function. However, you WILL have the Exchange module you can use. So, to get the Exchange commands:

Get-Command -module $global:importresults

Note that $global:importresults can potentially contain more than just the Exchange module. It is a list of all imported modules.

We notice that this returns more than we want. We really just want imported functions and cmdlets that have valid names. So:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” }

That gives us our valid Exchange cmdlets and functions! However, all we are interested in is the name of the function; not all the other garbage:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” } |
Select Name

Excellent. Now we have the names we want and we know where we want them to go! So let’s save them:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” } |
Select Name |
Out-File -Append C:\Users\Administrator\AppData\Roaming\Microsoft\UProof\CUSTOM.DIC

or, since we know that’s the per-user AppData folder:

PS C:\> $env:AppData
C:\Users\Administrator\AppData\Roaming
PS C:\>

we can also say:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” } |
Select Name |
Out-File -Append (join-path $env:AppData Microsoft\UProof\CUSTOM.DIC)

And there you have it. A LONG one-liner, but a one-liner nonetheless.

This does assume that you are running this on the same workstation where the custom dictionary resides.

This procedure should be generalizable (is that a word?) for any module.

Pat and I both worked on this going back and forth on FB. An interesting way to develop a script!

Until next time…

If there are things you would like to see written about, please let me know.

P.S. Pat went on and further developed the script to automatically choose an Exchange server, connect to it, and update the CUSTOM.DIC. To see that, visit his website.


Follow me on twitter: @EssentialExch

Exchange 2010 Gotcha – #4

Public Folder Contacts Can’t Replicate

If you have a public folder contact that includes an e-mail address, there is also an e-mail address type field that is associated with every e-mail address.

Note: You cannot see this e-mail address type field by default – but it’s still there. To view it, go to a Contacts folder in Outlook and create a custom view. In that view, add “Full Name”, then select “E-Mail Address Fields” and add “E-Mail Address” and “E-Mail Address Type”. Now, examine the Contacts in the folder using the custom view. You’ll see e-mail address types such as “SMTP” for external Internet contacts, “EX” for internal organization e-mail contacts, “FAX” if you have a fax connector installed, etc.

Now, Exchange 2003 (and perhaps Exchange 2007 – I have not checked in my lab) allowed two differerent e-mail address types to indicate “SMTP”. I believe this to be a hold-over from Outlook 97, although I have no documented proof of that (but in Outlook 97 we had “Internet mode” and “Corporate or Workgroup mode” – so it makes sense). The two different types are “SMTP” and “POP3/INTERNET”.

“POP3/INTERNET” is not valid in Exchange 2010. If you attempt to replicate a public folders to Exchange 2010 that contains this e-mail address type, the replication will abort. Thankfully, you do receive an event log error message that provides SOME clues about this occurring. The error looks like this:

Event Type:      Error
Event Source:    MSExchange Store Driver
Event Category:  (1)
Event ID:        1020
Date:            5/11/2010
Time:            10:00:43 AM
User:            N/A
Computer:        exchmb2.example.com
Description:
The store driver couldn't deliver the public folder replication message "Folder Content Backfill Response (exchmb1-IS@example.com)" because the following error occurred: Property validation failed. Property = [{00062004-0000-0000-c000-000000000046}:0x8082] Email1AddrType Error = The length of the property is too long. The maximum length is 9 and the length of the value provided is 13... For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

What you will have to do is, using Outlook, obtain a list of all the affected contacts as described above, and also using Outlook, change the address type to SMTP.

In Outlook 2010, you can directly edit this field. In Outlook 2007, you will need to open each contact, right click on the e-mail address in the default display, and select Properties. Then, for the Address Type field, click the “Internet” button (this changes the e-mail address type to “SMTP” – the button will now display “Custom”). Then “Save and Close” the updated contact.

In my migrations, I’ve only had a maximum of about 150 of these. If you have thousands, you will probably need to consider writing a webdav application/script to run against the Exchange 2003 server(s).

Until next time…

If there are things you would like to see written about, please let me know.


Follow me on twitter: @EssentialExch

Exchange 2010 Gotcha – #3

The TrustedInstaller – Isn’t.

Generally, when applying patches (whether service packs or hotfixes or rollups), the installation process will automatically acquire all the necessary permissions – if the user executing the process CAN acquire those permissions. This is especially relevant under Server 2008 and Server 2008 R2, where an interactive logged in user has their access token artificially limited, even if UAC is disabled.

However, the Exchange 2010 update installer either drops administrative permissions too early or never acquires all of the permissions that are necessary. When applying update rollups, binaries are updated just fine – but OWA source files are not.

This commonly leads to a patch application that appears successful – but it isn’t. When testing OWA after an update-rollup appliction, a common error is “syntax error in flogon.js at 1, 1.” This is an indication that the patch was NOT installed with administrative permissions.

Reapply the patch with administrative permissions.

Note: I have heard reports that this begins to affect Exchange 2007 AFTER the application of service pack 2, when Exchange 2007 is installed on Windows Server 2008.

This has (at this writing) been seen to affect Exchange 2010 UR1, UR2, and UR3.

To properly ensure that an application of an update-rollup has adequate permissions, do one of the following:

  • Right-click on the patch (filename.msp) and click on “Run as Administrator”
  • Open an elevated command prompt and then start the patch (just enter filename.msp). To open an elevated command prompt, click Start, then enter “cmd” into the search area, right click on the cmd.exe that appears in the results area and click on “Run as Administrator”.
  • Open an elevated PowerShell session and then invoke the patch (enter “ii filename.msp“). The open an elevated PowerShell session, click Start, then enter “PowerShell” into the search area, right click on the “Windows PowerShell” that appears in the results area and click on “Run as Administrator”.

Until next time…

If there are things you would like to see written about, please let me know.


Follow me on twitter: @EssentialExch

Exchange 2010 Gotcha – #2

Incoming e-mail CAN’T come in!

This issue is not exclusive to Exchange 2010 – it also exists in Exchange 2007.

The default receive connector created by the Exchange setup process does not include permissions to include “Anonymous users” on the default server permission group. Microsoft assumes that you will be using their Edge Server product (which isn’t Anonymous, but Authenticated).

Of course, most people (? – at least my customers!) will not be using the Microsft Edge Server product, but some other gateway e-mail product.

Therefore, you will need to set the “Anonymous users” permission on the default server permission group.

Otherwise – incoming Internet e-mail will bounce!

Until next time…

If there are things you would like to see written about, please let me know.

[Edit on April 15, 2010 to spell “Authenticated” correctly.]


Follow me on twitter: @EssentialExch

The ms-Exch-Store-Admin permission

In last week’s blog post, Exchange 2010 Gotcha – #1, I use the Add-AdPermission PowerShell cmdlet to add a set of permissions to each mailbox database. One of those permissions was the ms-Exch-Store-Admin permission.

If you’ve ever installed any BlackBerry software before, or ever installed Cisco’s Unity line of products before, you’ve seen this permission mentioned. This permission was introduced in Exchange 2000 and provides the capability of “administering an information store”. That’s a pretty non-specific permission, but that’s really all the available Microsoft documentation says about it. See, for example, here.

It’s worthwhile to note that, by itself, this permission does little. But when combined with the View-Only Organization Management permission (for example) and the Send-As permission, it allows a grantee the capability of doing a Send-As for any user within an information store for which they have that right – without knowing the password of the user who owns the mailbox. When combined with the Modify Permission permission, it allows the grantee to change Full Control assignments for a given mailbox, etc. When combined with the Server Administrator permission, it allows the grantee the capability of mounting and dismounting databases, moving mailboxes, etc.

That is, the ms-Exch-Store-Admin permission has some pretty hefty powers and should not be granted lightly.

Unfortunately, there is no available public documentation that fully defines this permission and/or what capabilities it may allow. Suffice it to say that you should carefully consider whether granting this permission is an appropriate choice for any arbitrary user account or group. The answer is “probably not”.

Thanks to Ross Smith, IV and Bill Long for answering a question of mine that led to this post.

Until next time…

If there are things you would like to see written about, please let me know.


Follow me on twitter: @EssentialExch