Tuesday, March 3, 2015

Extract Average Mailbox Size for Exchange 2013 Capacity Planning

Hi folks!

Currently I'm working on the planning of the capacity for new Exchange 2013 solution, namely upgrade from Exchange 2010. To plan server and storage capacity I'm using Exchange engineer's little helper, namely Exchange 2013 Role Requirement calculator. Recently Microsoft has published version 6.6 of it for Exchange 2013 which can be found and downloaded from here.

One of the new inputs that has been introduced Initial Mailbox Size (MB). It helps you to predict how soon will you reach the mailbox maximum size that you define in the Mailbox Size Limit (MB) input.



If you are building a brand new Exchange solution you will need to place value of 0 there. This will give you the following storage usage model by mailboxes for each mailbox tier which can be located on the Mailbox Space Modeling page of the calculator. In my case I set maximum size of the mailbox to be 25 GB (25600 MB) for each profile and the whole mailbox space would be filled within 60 months or 5 years.


However things change when you are upgrading the current Exchange 2007/2010 environment, as I do. In this case you will need to populate Initial Mailbox Size (MB) with the value of the average mailbox size in your current DAG to get more accurate prediction on when mailboxes that will be migrated to Exchange 2013 will reach their maximum size.

To achieve this I used yet one more Exchange engineers later helper, namely PowerShell. Of course your scenario can be different for mine. But let's imagine the scenario when you have DAG named DAG01 and DBs within this DAG are named DAG01-DB01, DAG01-DB02 and so on. Having such a contiguous naming convention will allow you to easily retrieve mailboxes from you databases that are part of your DAG.

So in my case I first create the variable which contains all mailboxes which reside in the mailbox databases within DAG. With naming convention like mine you can easily filter databases by using part of this name which common among all the databases:

 $MBXS = Get-Mailbox -ResultSize Unlimited |where-object {$_.Database -like "*DAG01*"}

To ensure that the variable has been properly populated you may output it to the screen or CSV file using Export-Csv cmdlet.

After this we need to execute Get-MailboxStatistics cmdlet against the mailboxes populated in the variable. The attribute that is interesting to us is TotalItemSize which gives us info about the size of the mailbox. We convert this value to the numeric value and the count the average value for all mailboxes by using Measure-Object cmdlet with -Average parameter. So the code for this looks something like:

$MBXS| Get-MailboxStatistics | %{$_.TotalItemSize.Value.ToMB()} | Measure-Object -Average

This should output the average number on the screen which you can then use in your role calculator.

This works fine when command is executed in the Exchange Management Shell locally on Exchange server. However, there may be a problem when this command executed from the local workstation that is talking to Exchange server via remote PowerShell. Instead of $_.TotalItemSize.Value.ToMB() you will be getting blank values. MS has advised the following workaround in their Technet Blog article. You will have to replace TotalItemSize.Value.ToMB() with @{name="TotalItemSize (MB)"; expression={[math]::Round(($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}} 

As a result it retrieves information to the screen like below



However it won't be able to retrieve average because the numeric value is actually string against which average can't be calculated. I would get screen as below:




To overcome this I extracted output into Excel spreadsheet as below:

 $MBXS| Get-MailboxStatistics | select DisplayName,@{name="TotalItemSize (MB)"; expression={[math]::Round(($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",","")/1MB),2)}} |Export-Csv DAG01-SizeReport.csv

And finally in Excel all you need is to calculate average mailbox size using good old AVERAGE function which gives us a value that we can use in the calculator for the Initial Mailbox Size (MB)





As a result we are getting more accurate prediction on how soon maximum mailbox size will be reached when we migrate from the existing Exchange solution to Exchange 2013.


I hope this will help you as it did help me.

Enjoy



Monday, March 2, 2015

Quick Bulk Mailbox-Enabling

Hi folks,

This is just a quick post for those of you who provision bulks of mailboxes on the regular basis. This scenario assumes that user accouts have already been created in the AD.

All you need to is to have TXT or CSV file with the UserId header. Underneath it you can publish one of these values to identify user accounts which can be wither of the below:

  • GUID
  • Distinguished name (DN)
  • Display name
  • Domain\Account
  • User principal name (UPN)

As soon as the input file is ready you can import it into the pipe and enable mailboxes for each user ID in the file. And it's only one string as follows:


Import-Csv D:\Scripts\Users.txt| foreach {Enable-Mailbox -Identity $_.UserId}

Very helpful for lazy guys like me.

Enjoy.

Tuesday, January 20, 2015

Getting Your User Accounts Activity Under Control


Hi folks,

This is my first blog entry in 2015. Just wanted to share about my recent adventure.

All of you who manage messaging environment have test accounts that are being created and then abandoned and sitting in your AD forever. Or you may be want to avoid a situation when all of them are in use thus creating extra load on your messaging system, especially if there is too many of them.

This is where our good old friend PowerShell comes to play. In this scenario I used Get-ADUser command which is available in the Active Directory module which comes with Windows 2008 R2 and later.

The best way to identify user activity is to extract information about logons and password changes. I prefer to be using both as in some cases password for accounts (even test accounts, can you imagine this!) is set to never expire. So in addition to password set and changes related attributes I used LastLogon attribute.

Additionally it's worthy to mention scenario when you are in a forest with multiple domains (which is not the best practice according to Microsoft). You may connect to multiple servers or in my case I simply used global catalog to extract the information I needed. To user global catalog you will need to type server host name followed by the 3268 which corresponds to the port GC is listening for LDAP requests.

Please note the attribute msDS-UserPasswordExpiryTimeComputed which is used to calculate password expiration date.

And last, but not least don't forget to import AD module for PowerShell to be able to successfully execute the script.

My final code looks like this


Import-Module ActiveDirectory
Import-Csv D:\scripts\Users.txt | foreach {Get-ADUser -Identity $_.samAccountName –Properties * -Server GC01:3268} |
Select-Object "Displayname",SamAccountName,whenCreated,LastLogonDate,PasswordLastSet,PasswordExpired,PasswordNeverExpires,@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} |Export-Csv D:\scripts\UserActivity.csv

And it produced a nice spreadsheet as below:



Please note user accounts with the blank value for LastLogon which indicates that user has never logged in to the AD domain. In addition to that some of the dates may be a long way in the past. Both may indicate that user accounts might not be in use and therefore a good candidates for deletion. But please make sure that you contact the account or service owners before doing so.

And, finally, my special thanks to the author of this great article which gave me a good hint on the way to go.

Enjoy.

Saturday, November 22, 2014

Mailbox Permission Issues After Cross-Forest Migration


Hi folks,

I would love to share with you one old story that I had 3 years ago during the cross-forest Exchange migration (2007 to 2010).

After migration of mailboxes some of them cannot be disabled using Microsoft Exchange Shell or console. In order to resolve this problem Exchange Trusted Subsystem group had to be assigned Read All Properties and Write All Properties permissions on the domain container.

1. Launch ADSI Edit
2. Connect ADSI edit to the Default Naming Context
3. Right click the container that is corresponding to the domain DC=contoso,DC=com and go to the Security tab
4. Click on the Advanced button
5. On the Advanced Security Settings for contoso.com make sure you are on the Permissions tab and clock on the Add button
6. Select All Descendant objects in the Apply to section. In the list of permissions tick boxes next to Allow-Read all properties and Allow-Write all properties. Click OK
7. Wait for Active Directory replication to occur.


And it should do the magic.

Enjoy.

Removing Email Addresses With Obsolete SMTP Domain From Users Mailboxes

Hi folks,

Just wanted to share with you a quick way to remove obsolete SMTP addresses from mailboxes in your Exchange estate.

Imagine a situation when you decommissioning a certain SMTP domain from your organization. First you perform all of the activities to prevent your environment to receive email from this domain. These activities include changes in DNS (removing MX,SPF and PTR records) and also removing accepted domains from your Exchange and hygiene appliances. Additionally you may edit your email address policies to stop provisioning decommissioned SMTP domain to the new mailboxes.

However you are still left with the mailboxes that still contain this email address in their EmailAddresses  attribute. Of course you can attend each mailbox one-by-one and scrap these addresses out, however for bigger environments it won't work.

The below script will help you to remove obsolete email addresses from mailboxes of users located in the OU contoso.com/Staff which have email addresses with adatum.com suffix. The script will go through all the users which may have this domain and scrap it out. Please note that when running this script you may need to adjust the name of the SMTP domain you're removing as well as path to the OU where mailboxes are stored.


$Mailbox = Get-User -OrganizationalUnit contoso.com/Staff -RecipientTypeDetails UserMailbox    
    $Mailbox | foreach { 
    for ($i=$_.EmailAddresses.Count;$i -ge 0; $i--) 
    { 
    $_.EmailAddresses[$i].ProxyAddressString  
     
    if ($_.EmailAddresses[$i].ProxyAddressString  -like "smtp:adatum*" ) 
    { 
    $_.EmailAddresses.RemoveAt($i) 
    } 
     
    } 
    $_|set-mailbox 
   

Enjoy.

Quickly Create OU Structure in the new AD domain


Hi folks,

This is a script that will help you creating OU infrastructure in the brand new Active Directory environment (of course it can also be used in creating OUs in existing AD, provided that you use OU names that are not in use). In addition to this it will protect newly created OUs from accidental deletion which is similar to this:



Make sure that you replace DC=contoso,DC=com with the right LDAP path of your domain and feel free to replace names for OUs (next to OU=) with the names that are in your environment

Import-Module ActiveDirectory

$objDomain =[ADSI]"LDAP://DC=contoso,dc=com "
$objOU = $objDomain.Create("organizationalUnit","ou=Clusters")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Servers")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Groups")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Security Groups,ou=Groups")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Distribution Groups,ou=Groups")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Services")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Staff")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Admins")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Workstations")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=SQL Servers,ou=Servers")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Exchange Servers,ou=Servers")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=Lync Servers,ou=Servers")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=CRM Servers,ou=Servers")
$objOU.SetInfo()

$objOU = $objDomain.Create("organizationalUnit","ou=BES Servers,ou=Servers")
$objOU.SetInfo()

Get-ADOrganizationalUnit -Filter 'Name -like "*"' | Set-ADOrganizationalUnit -ProtectedFromAccidentalDeletion $true

Enjoy

Tuesday, November 11, 2014

PowerShell commands to manipulate mailbox folders

Hi folks,

This is a short post in support to those of you you are using PowerShell to manipulate mailbox folders in Exchange 2010/2013.

The main thing to remember is that Get-MailboxFolder command can be run by the mailbox owners as per this Technet article . If you are trying to run the same command as an administrator you are getting the following error:


No RBAC manipulations will help you to overcome this.

Therefore if you are interested in retrieving user mailbox folders you will need to use Get-MailboxFolderStatistics command. By default, it retrieves all the information in the list format, which doesn't always fit the screen. Of course this can be exported to TXT file for further reviews. Additionally you can use certain parameters.

As an example this command I used to retrieve information about folders and their structure within a mailbox:

Get-MailboxFolderStatistics "Farhad Mahmudov" |select Name,Identity

More details about this command can be found here .

Additionally there are commands that allow you to manage mailbox folders permissions like Set-MailboxFolderPermissionRemove-MailboxFolderPermissionAdd-MailboxFolderPermission and Get-MailboxFolderPermission.

Enjoy.