Exchange 2003 Mailbox Powershell Report

Right, this will probably be so horrifically out-of-date for some people, but recently I’ve been doing a few Exchange 2003 migrations and have realised the importance of getting all the data you need before performing these migrations is quite high.

Sure, you can export the data you find in Exchange System Manager but what if you want other details like PrimarySMTPAddress or whether Email Address Policy is enabled for the user, or what their quotas are?

This is where this script comes in.

This script will give you a CSV report showing all mailboxes hosted on the Exchange 2003 server along with plenty of other details to aid in your migrations.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
################################################################################
################# Exchange 2003 Mailbox Report by Matt Ellis ###################
################################################################################
 
# Contact Me
# ----------
 
# Web: http://mattellis.me
# Twitter: http://twitter.com/ellismessaging (@ellismessaging)
 
# Syntax
# ------
 
# The script has two switches, one of which is mandatory:
 
# 1. -ServerName (mandatory)
# For example: .\Get-Exchange2003MailboxReport.ps1 -ServerName EX2K3SRV01 
 
# 2. -ReportPath (optional)
# For example: .\Get-Exchange2003MailboxReport.ps1 -ServerName EX2K3SRV01 -ReportPath "D:\Temp\"
 
Param (
	[Parameter(Mandatory = $True)]
	$ServerName,
	[Parameter(Mandatory = $False)]
	$ReportPath
)
 
$Date = Get-Date -format "yyyyMMdd"
 
If ($ReportPath) {
	If ($ReportPath[-1] -ne "\") {
		$ReportPath += "\"
	}
	$OutFileTemp = "$ReportPath$ServerName-$Date.txt"
	$OutFile = "$ReportPath$ServerName-$Date.csv"
} Else {
	$OutFileTemp = "$ServerName-$Date.txt"
	$OutFile = "$ServerName-$Date.csv"
}
 
"Alias" + "^" + "DisplayName" + "^" + "MailboxSizeMB"  + "^" + "ServerName" `
+ "^" + "Database" + "^" + "PrimarySMTPAddress" + "^" + "EmailAddressPolicyEnabled" `
+ "^" + "HiddenFromGAL" + "^" + "UseDatabaseQuotaDefaults"  + "^" + "IssueWarningQuota" `
+ "^" + "ProhibitSendQuota" | Out-File $OutFileTemp -Force
 
$Users = Get-WmiObject -ComputerName $ServerName -Namespace root\MicrosoftExchangeV2 -Class Exchange_Mailbox
 
ForEach ($User in $Users) {
	$GM = Get-Mailbox -Identity $User.MailboxGUID
	If ($GM) {
		$MailboxSizeMB = "{0:N0}" -f ([decimal]$User.Size/1024)
		#$MailboxSizeGB = "{0:N2}" -f ([decimal]$MailboxSizeMB/1024)
		$LastLogon = $User.ConvertToDateTime($User.LastLogonTime)
 
		$GM.Alias + "^" + $GM.DisplayName + "^" + $MailboxSizeMB  + "^" + $GM.ServerName `
		+ "^" + $GM.Database + "^" + $GM.PrimarySMTPAddress + "^" + $GM.EmailAddressPolicyEnabled `
		+ "^" + $GM.HiddenFromAddressListsEnabled + "^" + [bool]$GM.UseDatabaseQuotaDefaults `
		+ "^" + $GM.IssueWarningQuota + "^" + $GM.ProhibitSendQuota | Out-File $OutFileTemp -Append
	}
}
 
Import-Csv $OutFileTemp -Delimiter "^" | Export-Csv -Path $OutFile -NoTypeInformation -Force
Del $OutFileTemp
Write-Host -NoNewline "Report file created:" (Resolve-Path $OutFile).Path
09
Nov 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 0 Comments
TAGS

Enable or Disable Outlook Anywhere based on Group Membership

Lets face it – security guys HATE Outlook Anywhere. So, it is highly likely you’ve stumbled onto this page because you’ve been asked to disable it outright or only enable it for the trusted few. In that case, this will hopefully help.

The script below will enable or disable Outlook Anywhere based on the membership of a distribution group. It will then give you a CSV output of everything it’s done.

Note: The script doesn’t currently recurse groups, so nested groups will not work.

Also Note: The script runs a Get-CASMailbox across all your mailboxes with no limit on ResultSize. If you want to limit this or customize this  in any way you should change the $Users variable on Line 17.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
################################################################################
#### Enable or Disable Outlook Anywhere Based on Allow Group by Matt Ellis #####
################################################################################
 
# Contact Me
# ----------
 
# Web: http://mattellis.me
# Twitter: http://twitter.com/ellismessaging (@ellismessaging)
 
# Start Variables
$ReportPath = "D:\Temp\OA-Report.csv"
$GroupName = "sec_OutlookAnywhere_Allow"
# End Variables
 
$Global:AllMembers = @()
$Users = Get-CASMailbox -ResultSize Unlimited | Select Identity, SamAccountName, ServerName, MAPIBlockOutlookRpcHttp
$Allow = Get-DistributionGroupMember -Identity $GroupName -ResultSize:Unlimited | Select SamAccountName
 
Function InsertObject {
	$obj = New-Object psObject
	$obj | Add-Member -Membertype noteproperty -Name "Name" -Value $User.Identity
	$obj | Add-Member -Membertype noteproperty -Name "User4x4" -Value $User.SamAccountName
	$obj | Add-Member -Membertype noteproperty -Name "Server" -Value $User.ServerName
	$obj | Add-Member -Membertype noteproperty -Name "BlockOA" -Value $User.MAPIBlockOutlookRpcHttp
	$obj | Add-Member -Membertype noteproperty -Name "InAllowGroup" -Value $InAllowGroup
	$obj | Add-Member -Membertype noteproperty -Name "Result" -Value $Result
	$Global:AllMembers += $obj
}
 
ForEach ($User in $Users) {
	ForEach ($Username in $Allow) {
		If ($Username -match $User.SamAccountName) {
			[bool]$InAllow = $true
			Break
		} Else {
			[bool]$InAllow = $false
		}
	}
	If ($InAllow -and !$User.MAPIBlockOutlookRpcHttp) {
		$InAllowGroup = "Yes"
		$Result = "Already Enabled"
		# Do Nothing
	} ElseIf (!$InAllow -and $User.MAPIBlockOutlookRpcHttp) {
		$InAllowGroup = "No"
		$Result = "Already Disabled"
		# Do Nothing
	} ElseIf ($InAllow -and $User.MAPIBlockOutlookRpcHttp) {
		$InAllowGroup = "Yes"
		$Result = "To Be Enabled"
		# Enable OA
		Set-CASMailbox -Identity $User.Identity -MAPIBlockOutlookRpcHttp:$False
	} ElseIf (!$InAllow -and !$User.MAPIBlockOutlookRpcHttp) {
		$InAllowGroup = "No"
		$Result = "To Be Disabled"
		# Disable OA
		Set-CASMailbox -Identity $User.Identity -MAPIBlockOutlookRpcHttp:$True
	} Else {
		$Result = "Hell, I dunno!"
	}
	InsertObject
}
$Global:AllMembers | Export-CSV $ReportPath -NoTypeInformation -Force
13
Sep 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 0 Comments
TAGS

Exchange CCR Health Script

Download the script here: Get-CCRHealth Script

If you administer a multi CCR cluster environment then it’s useful to know the specific state of your server without having to go and look for it. I find monitoring screens that offer a quick glance on health really useful, so for the purpose of this blog I have cleaned my script up a bit and have adapted it to offer 3 output types.

First of all, I need to stress that you need to run this script from a server with Windows Failover Clustering feature installed. Unfortunately, there is no way round this that I have found so far. I’m pretty sure you’ll also need PowerShell 2.0 for this to run successfully.

Before you start running this script you’ll need to change a few variables at the top of the script:

# Variables
$ReportPath = "C:\Scripts\CCRHealth.htm"
$EmailSubject = "Exchange CCR Health Report"
$FromAddress = "donotreply@domain.com"
$RecipientAddress = "your.name@domain.com"	# Comma separate for more than one.
$SMTPServer = "your.email.relay.here"		# Hostname or IP Address.

First off, we have the normal shell view. You can run the script with no switches and it will automatically query every CCR cluster in your estate and give you the health on the screen.

Console output for Get-CCRHealth.ps1

Second, we have the -Email switch. This will send you an HTML formatted email with the details.

Email output for Get-CCRHealth.ps1

Third, we have the -Report switch which will create an HTML report. The path of the output can be configured in the variables section of the script. This is what I use for my monitoring screen, as I can schedule this to run every 5 or 10 minutes and have a browser auto refresh the report. You have no idea how many times this has saved my life and reported stuff before SCOM has bothered to tell me.

HTML report output for Get-CCRHealth.ps1

Fourth, we have the -Alert switch which can be used in conjunction with the  -Report or -Email switch. I use this with the -Report switch and it means that if any CCR clusters fall into a ‘Failed’ state I get an email alert telling me.

I hope someone finds this script useful. Please feel free to modify and let me know if you manage to do anything really cool with it. As a point of note, you may want to change the values at which copy queue length and replay queue length change colour. This logic can be found around line 192.

Download the script here: Get-CCRHealth Script

08
Aug 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 6 Comments
TAGS

Exchange SCR Health Script

Download the script here: Get-SCRHealth.ps1

In the same way that Standby Continuous Replication (SCR) has to be configured using the Exchange Management Shell, it can also only be managed and monitored through the Shell too.

I’m not sure how many people this will help as Exchange 2007 isn’t the latest and greatest but I’ve created a script to keep me updated with the state of my storage groups configured with Standby Continuous Replication (SCR).

The script should work out of the box in any 2007 environment as it finds the SCR replicas using the Get-StorageGroup cmdlet:

Get-StorageGroup | ? {$_.StandbyMachines} | Select * -Expand StandbyMachines

The script output can be presented in three ways; at the console, in an email and in an HTML report.

To run the script and just show the output at the command line just run the script:

[PS] D:\Scripts .\Get-SCRHealth.ps1

SCR Health Check Script running from the Shell...

Two switches are available in the script to push the output out in an email or in an HTML file. The HTML file can be used on a monitoring screen for example:

-Email $true|$false
-Report $true|$false

The two switches can be run together to get the output at the console, in an email and in an HTML report concurrently.

So for example:

[PS] D:\Scripts .\Get-SCRHealth.ps1 -Email $true -Report $true

Email:

SCR Health Check Script Email...

Report:

SCR Health Check Script Report...

Once you’ve downloaded the script you’ll need to change a few variables for your environment. They can be found near the top of the script:

# Variables
$ReportPath = "D:\Temp\Report.htm"
$EmailSubject = "Exchange SCR Report"
$FromAddress = "donotreply@domain.com"
$RecipientAddress = "yourname@domain.com" # Comma separate for more than one.
$SMTPServer = "your.mail.relay.com" # Hostname or IP Address.

Download the script here: Get-SCRHealth.ps1

12
Jul 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 6 Comments
TAGS

Exchange RPC Client Access service won’t start…

I was asked to go and look at a new Exchange 2010 implementation today as they couldn’t get Outlook to connect. It was a single server implementation with all roles on one box but the first thing I noticed was that the Exchange RPC Client Access service was not started. Starting it just resulted in it stopping immediately.

After looking in the Application log I found an error with Event ID 1002 MSExchangeRPC:

Failed to register service principal name ExchangeMDB. Failed with error code Access is denied (5).

After a bit of googling I found the following ExpertsExchange article (http://ellis.li/PMLtUM) and it led to the following Powershell command which resolved the issue:

Add-ADPermission -Identity "CN=ServerName,OU=OUName,DC=Domain,DC=Local" 
-User "ServerName$" -AccessRights WriteProperty -Properties "Validated-SPN"

Note: Remember to put the ‘$’ after the ServerName for the -User attribute.

Also, when trying to perform this command in the Exchange shell it gave me an “Access Denied” error. To get it to correctly apply I had to do this:

1. Load up the regular Powershell command-line console.
2. Type ImportSystemModules and hit Enter. This will load a crap load of system libraries.
3.  Then type the command above and it should allow you to run it.

11
Jul 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 2 Comments
TAGS

Export FullAccess & SendAs permissions for Shared Mailboxes…

Ever been asked to get an export of all the assigned permissions to a group of mailboxes? With this script you’ll be able to export the Full Access and & Send As permissions for whatever group of mailboxes you wish. This script works on Exchange 2007 but there’s no reason why it won’t work for Exchange 2010 either.

You can customise the $Mailboxes query to gather whatever mailboxes you wish to export the details for. This is just a Get-Mailbox query. The export will be in the form of a txt file but the results will be delimited with a ^ symbol. Just import this to Excel to make it pretty.

$OutFile = "C:\Temp\PermissionExport.txt"
"DisplayName" + "^" + "Alias" + "^" + "Full Access" + "^" + "Send As" | Out-File $OutFile -Force
 
$Mailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize:Unlimited | Select Identity, Alias, DisplayName, DistinguishedName
ForEach ($Mailbox in $Mailboxes) {
	$SendAs = Get-ADPermission $Mailbox.DistinguishedName | ? {$_.ExtendedRights -like "Send-As" -and $_.User -notlike "NT AUTHORITY\SELF" -and !$_.IsInherited} | % {$_.User}
	$FullAccess = Get-MailboxPermission $Mailbox.Identity | ? {$_.AccessRights -eq "FullAccess" -and !$_.IsInherited} | % {$_.User}
 
	$Mailbox.DisplayName + "^" + $Mailbox.Alias + "^" + $FullAccess + "^" + $SendAs | Out-File $OutFile -Append
}

Ta ta for now.

01
Jun 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 4 Comments
TAGS

How to set your default domain in Office 365…

There are two ways in which to do this; one is the administration portal for your Office 365 deployment and one is using the Microsoft Online Services Module for PowerShell. The first is a bit boring and straight forward. The second at least gets you inside the management shell so helps you to start learning how to harness the power of PowerShell with Office 365.

Office 365 Administration Portal

  1. Login to your Administration portal at https://portal.microsoftonline.com/
  2. Click on your company name in the top left right above where it says ‘Admin Overview’.
  3. Click the Edit button.
  4. Change the Primary Verified Domain using the dropdown box.
  5. Click OK and then Close. Done.

Microsoft Online Services Module for PowerShell

  1. First of all you need to install the Office 365 CmdLets. Go here and follow the instructions to install the modules based on your OS:
    http://onlinehelp.microsoft.com/en-us/office365-enterprises/2b09b6a8-ad7e-446f-b7f0-273856beed70#BKMK_install
  2. Load up the Microsoft Online Services Module or import the module to your current PowerShell session using the instructions here:
    http://onlinehelp.microsoft.com/en-us/office365-enterprises/2b09b6a8-ad7e-446f-b7f0-273856beed70#BKMK_connect
  3. Type the following and hit Enter.
    Connect-MSOLService
  4. Type your Office 365 credentials in the box that pops up and hit Enter.
  5. Type the following and hit Enter.
    Set-MsolDomain -Name mattellis.me -IsDefault
  6. Done
05
Apr 2012
POSTED BY
DISCUSSION 1 Comment
TAGS

Import-CSV Error…

I had to create a crap load of contacts earlier for a migration using an import from an Excel file. I saved the Excel spreadsheet as a CSV file and went to run my script against it.

I got this error:

Import-Csv : Cannot process argument because the value of argument “name” is invalid. Change the value of the “name” argument and run the operation again.

Confused me for a bit until I realised that I had an empty column in the CSV file. It was trying to read in the column but it had no header name. I removed the column and the import worked perfectly.

A bit more of a descriptive error would be nice…?

31
Jan 2012
POSTED BY
POSTED IN PowerShell
DISCUSSION 0 Comments
TAGS

Setting Distribution Group Delivery Restrictions via PowerShell…

Adjusting the delivery restrictions on distribution groups is quite a common task. The more members a group has the more of a problem this ends up being in big organisations.

Setting the permissions in the Exchange Management Console (EMC) is simple enough when you have one or two people/groups to add to the allowed list. When you have many user/groups needing to be added across a massive range of groups then this is something your going to need to script.

Now this is where it doesn’t quite work as expected. It’s easy enough to create a shell command to add multiple users to the -AcceptMessagesOnlyFrom attribute on the DL object but when doing this you’ll find that only the last one in the list has been added. This is because the attribute is an array. You can view this using the following command.

Get-DistributionGroup -Identity "GROUP-NAME-HERE" | Select -expand AcceptMessagesOnlyFrom | ft Name</em>

To add a new user to this list you have to call the already existing list and then add the new user to the end of it. Because PowerShell is so, well, powerful you can do this quite easily with one one-liner:

Set-DistributionGroup "GROUP-NAME-HERE" -AcceptMessagesOnlyFrom((Get-DistributionGroup "GROUP-NAME-HERE").AcceptMessagesOnlyFrom + "IDENTITY-OF-USER-OR-GROUP-HERE")

The identity of the new group or user can be in the form of the following attributes:

  • Distribution Name (DN)
  • Canonical Name
  • GUID
  • Name
  • Display Name
  • Alias
  • Exchange DN
  • Primary SMTP Email Address

Now, that’s all very well, but what if you’d like to add multiple users to multiple groups? Here you go – just stick the groups you’d like to amend and the users to be applied to those groups in the text files.

$People = gc C:\People.txt
$Groups = gc C:\Groups.txt
ForEach ($Group in $Groups) {
   Set-DistributionGroup $Group -AcceptMessagesOnlyFrom((Get-DistributionGroup $Group).AcceptMessagesOnlyFrom + $People)
}

Works well huh?

31
Jan 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 0 Comments
TAGS

Missing LastFullBackup Attribute on Mailbox Database..?

This is more of an annoyance if anything but I noticed today that while I could look on the Properties page of each mailbox database and see the LastFullBackup date and time this wasn’t reflected in the Get-MailboxDatabase -Server “SERVERNAME” | fl command. It was simply empty.

It seems that if you’d like to get details such as LastFullBackup, Mounted, BackupInProgress or OnlineMaintenanceInProgress you need to use the -Status parameter.

So, my command should have been:

Get-MailboxDatabase -Server "SERVERNAME" -Status | fl

I don’t know why, but that’s the way it is.

31
Jan 2012
POSTED BY
POSTED IN Exchange PowerShell
DISCUSSION 0 Comments
TAGS